pax_global_header00006660000000000000000000000064151003343510014505gustar00rootroot0000000000000052 comment=f4f732790c35632427f857395f37c93e19729a2b xkbcommon-libxkbcommon-54ee7ac/000077500000000000000000000000001510033435100166635ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/.clang-tidy000066400000000000000000000074401510033435100207240ustar00rootroot00000000000000--- Checks: - clang-diagnostic-* - clang-analyzer-* - -clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling - -clang-analyzer-optin.core.EnumCastOutOfRange - bugprone-* - -bugprone-suspicious-realloc-usage - -bugprone-easily-swappable-parameters - -bugprone-assignment-in-if-condition - -bugprone-reserved-identifier - -bugprone-multi-level-implicit-pointer-conversion - modernize-* - -modernize-use-nullptr - -modernize-macro-to-enum - performance-* - google-* - -google-readability-braces-around-statements - -google-readability-todo # - misc-* # - -misc-include-cleaner # ExtraArgs: # - '-std=c11' ExtraArgsBefore: - '-std=c11' - '-D_GNU_SOURCE' WarningsAsErrors: '' HeaderFileExtensions: - '' - h ImplementationFileExtensions: - c HeaderFilterRegex: '' ExcludeHeaderFilterRegex: '' FormatStyle: none CheckOptions: cert-dcl16-c.NewSuffixes: 'L;LL;LU;LLU' cert-err33-c.AllowCastToVoid: 'true' cert-err33-c.CheckedFunctions: '^::aligned_alloc;^::asctime_s;^::at_quick_exit;^::atexit;^::bsearch;^::bsearch_s;^::btowc;^::c16rtomb;^::c32rtomb;^::calloc;^::clock;^::cnd_broadcast;^::cnd_init;^::cnd_signal;^::cnd_timedwait;^::cnd_wait;^::ctime_s;^::fclose;^::fflush;^::fgetc;^::fgetpos;^::fgets;^::fgetwc;^::fopen;^::fopen_s;^::fprintf;^::fprintf_s;^::fputc;^::fputs;^::fputwc;^::fputws;^::fread;^::freopen;^::freopen_s;^::fscanf;^::fscanf_s;^::fseek;^::fsetpos;^::ftell;^::fwprintf;^::fwprintf_s;^::fwrite;^::fwscanf;^::fwscanf_s;^::getc;^::getchar;^::getenv;^::getenv_s;^::gets_s;^::getwc;^::getwchar;^::gmtime;^::gmtime_s;^::localtime;^::localtime_s;^::malloc;^::mbrtoc16;^::mbrtoc32;^::mbsrtowcs;^::mbsrtowcs_s;^::mbstowcs;^::mbstowcs_s;^::memchr;^::mktime;^::mtx_init;^::mtx_lock;^::mtx_timedlock;^::mtx_trylock;^::mtx_unlock;^::printf_s;^::putc;^::putwc;^::raise;^::realloc;^::remove;^::rename;^::scanf;^::scanf_s;^::setlocale;^::setvbuf;^::signal;^::snprintf;^::snprintf_s;^::sprintf;^::sprintf_s;^::sscanf;^::sscanf_s;^::strchr;^::strerror_s;^::strftime;^::strpbrk;^::strrchr;^::strstr;^::strtod;^::strtof;^::strtoimax;^::strtok;^::strtok_s;^::strtol;^::strtold;^::strtoll;^::strtoul;^::strtoull;^::strtoumax;^::strxfrm;^::swprintf;^::swprintf_s;^::swscanf;^::swscanf_s;^::thrd_create;^::thrd_detach;^::thrd_join;^::thrd_sleep;^::time;^::timespec_get;^::tmpfile;^::tmpfile_s;^::tmpnam;^::tmpnam_s;^::tss_create;^::tss_get;^::tss_set;^::ungetc;^::ungetwc;^::vfprintf;^::vfprintf_s;^::vfscanf;^::vfscanf_s;^::vfwprintf;^::vfwprintf_s;^::vfwscanf;^::vfwscanf_s;^::vprintf_s;^::vscanf;^::vscanf_s;^::vsnprintf;^::vsnprintf_s;^::vsprintf;^::vsprintf_s;^::vsscanf;^::vsscanf_s;^::vswprintf;^::vswprintf_s;^::vswscanf;^::vswscanf_s;^::vwprintf_s;^::vwscanf;^::vwscanf_s;^::wcrtomb;^::wcschr;^::wcsftime;^::wcspbrk;^::wcsrchr;^::wcsrtombs;^::wcsrtombs_s;^::wcsstr;^::wcstod;^::wcstof;^::wcstoimax;^::wcstok;^::wcstok_s;^::wcstol;^::wcstold;^::wcstoll;^::wcstombs;^::wcstombs_s;^::wcstoul;^::wcstoull;^::wcstoumax;^::wcsxfrm;^::wctob;^::wctrans;^::wctype;^::wmemchr;^::wprintf_s;^::wscanf;^::wscanf_s;' cert-oop54-cpp.WarnOnlyIfThisHasSuspiciousField: 'false' cert-str34-c.DiagnoseSignedUnsignedCharComparisons: 'false' cppcoreguidelines-non-private-member-variables-in-classes.IgnoreClassesWithAllMemberVariablesBeingPublic: 'true' google-readability-braces-around-statements.ShortStatementLines: '1' google-readability-function-size.StatementThreshold: '800' google-readability-namespace-comments.ShortNamespaceLines: '10' google-readability-namespace-comments.SpacesBeforeComments: '2' llvm-else-after-return.WarnOnConditionVariables: 'false' llvm-else-after-return.WarnOnUnfixable: 'false' llvm-qualified-auto.AddConstToQualified: 'false' bugprone-suspicious-enum-usage.StrictMode: 'true' bugprone-signed-char-misuse.CharTypdefsToIgnore: 'int8_t' SystemHeaders: false ... xkbcommon-libxkbcommon-54ee7ac/.clangd000066400000000000000000000003321510033435100201120ustar00rootroot00000000000000CompileFlags: # Treat files as C, not C++. Add: [-xc] Diagnostics: Includes: # config.h should be included at the top of files, even if not needed. # Don't consider it unused. IgnoreHeader: config\.h xkbcommon-libxkbcommon-54ee7ac/.editorconfig000066400000000000000000000003331510033435100213370ustar00rootroot00000000000000root = true [*] charset = utf-8 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true indent_style = space indent_size = 4 max_line_length = 80 [*.yml,*.md] indent_style = space indent_size = 2 xkbcommon-libxkbcommon-54ee7ac/.github/000077500000000000000000000000001510033435100202235ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/.github/dependabot.yml000066400000000000000000000002551510033435100230550ustar00rootroot00000000000000version: 2 updates: # Check for updates to GitHub Actions every month. - package-ecosystem: "github-actions" directory: "/" schedule: interval: "monthly" xkbcommon-libxkbcommon-54ee7ac/.github/workflows/000077500000000000000000000000001510033435100222605ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/.github/workflows/github-release.yml000066400000000000000000000013011510033435100256760ustar00rootroot00000000000000name: github-release on: push: tags: - 'xkbcommon-*' # Set permissions at the job level. permissions: {} jobs: build: name: Automatically create GitHub release for tag runs-on: ubuntu-22.04 permissions: contents: write steps: - uses: actions/checkout@v5 with: fetch-depth: 0 persist-credentials: false - uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} release_name: ${{ github.ref }} body: | See the [NEWS](https://github.com/xkbcommon/libxkbcommon/blob/master/NEWS.md) file for the changes. xkbcommon-libxkbcommon-54ee7ac/.github/workflows/linux.yml000066400000000000000000000100271510033435100241420ustar00rootroot00000000000000name: linux on: push: branches: [ master ] pull_request: branches: [ master ] # Set permissions at the job level. permissions: {} jobs: linux: runs-on: ubuntu-22.04 permissions: contents: read strategy: matrix: compiler: [clang, gcc] sanitizers: ['sanitizers', 'no sanitizer'] exclude: - compiler: clang sanitizers: sanitizers steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: actions/setup-python@v5 with: python-version: '3.12' - name: Install dependencies run: | # Jinja2 is needed for merge-modes tests python -m pip install --upgrade meson PyYAML ruff Jinja2 sudo apt update sudo apt install -y \ locales tzdata \ doxygen libxcb-xkb-dev valgrind ninja-build \ libwayland-dev wayland-protocols bison graphviz libicu-dev \ ${{ matrix.sanitizers == 'sanitizers' && 'libasan8 libubsan1' || '' }} # Generate locale for tests sudo locale-gen fr_FR.UTF-8 - name: Install xkeyboard-config run: | # Install master version of xkeyboard-config, in order to ensure # its latest version works well with xkbcommon. # HACK: We use meson to install, while it would be cleaner # to create a proper package to install or use some PPA. pushd ~ git clone --depth=1 https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config.git pushd "xkeyboard-config" BUILDDIR=build # xkeyboard-config 2.45+ uses symlinks for legacy unversioned files, # but meson cannot overwrite < 2.45 which used regular files and directories. rm /usr/share/pkgconfig/xkeyboard-config.pc rm -r /usr/share/X11/xkb meson setup $BUILDDIR -Dprefix=/usr meson install -C $BUILDDIR popd popd - name: Create custom locale for testing run: | # The locale name must be kept in sync with the Compose test sudo localedef -i en_US -f UTF-8 xx_YY.UTF-8 - name: Setup run: | # -gdwarf-4 - see https://github.com/llvm/llvm-project/issues/56550. CFLAGS='-gdwarf-4 -fno-omit-frame-pointer' \ meson setup -Denable-docs=true -Denable-cool-uris=true \ $MESON_EXTRA_FLAGS \ build env: CC: ${{ matrix.compiler }} # Use sanitizers only if not using Valgrind MESON_EXTRA_FLAGS: ${{ matrix.sanitizers == 'sanitizers' && '-Db_sanitize=address,undefined' || '' }} - name: Build run: | meson compile -C build - name: Test # Use a specific non-US locale run: LC_ALL=fr_FR.UTF-8 meson test -C build --print-errorlogs - name: Test with valgrind if: matrix.sanitizers != 'sanitizers' # Use a specific non-US locale run: | LC_ALL=fr_FR.UTF-8 meson test -C build --print-errorlogs --setup=valgrind \ --no-suite python-tests - name: Upload test logs uses: actions/upload-artifact@v4 if: failure() with: name: test logs path: | build/meson-logs/ - name: Ensure doxygen version is correct run: | doxygen --version > version.txt echo "1.9.6" >> version.txt if [ $(sort -V version.txt | tail -n1) != "1.9.6" ]; then echo "Doxygen version 1.9.6 or earlier expected, see #347" exit 1 fi - name: Store doxygen docs for use by the pages workflow uses: actions/upload-artifact@v4 if: success() && matrix.compiler == 'gcc' && matrix.sanitizers == 'sanitizers' with: name: doxygen-docs path: | build/html/ - name: Ruff format run: ruff format --line-length=88 --check --diff . xkbcommon-libxkbcommon-54ee7ac/.github/workflows/macos.yml000066400000000000000000000031031510033435100241020ustar00rootroot00000000000000name: macos on: push: branches: [ master ] pull_request: branches: [ master ] # Set permissions at the job level. permissions: {} jobs: macos: runs-on: macos-13 permissions: contents: read steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: actions/setup-python@v5 with: python-version: '3.12' - name: Install dependencies run: | brew install bison libxml2 meson ninja xkeyboardconfig xorg-server brew link bison --force brew link libxml2 --force # https://docs.brew.sh/Homebrew-and-Python#pep-668-python312-and-virtual-environments python3 -m venv venv source venv/bin/activate # Jinja2 is needed for merge-modes tests pip3 install PyYaml Jinja2 env: HOMEBREW_NO_AUTO_UPDATE: 1 HOMEBREW_NO_INSTALL_CLEANUP: 1 - name: Setup run: | source venv/bin/activate PATH="/usr/local/opt/bison/bin:${PATH}" \ meson setup \ -Denable-wayland=false \ -Denable-x11=true \ -Dxkb-config-root="$(brew --prefix xkeyboardconfig)/share/X11/xkb" \ -Dx-locale-root="$(brew --prefix xorg-server)/share/X11/locale" \ build - name: Build run: | source venv/bin/activate PATH="/usr/local/opt/bison/bin:${PATH}" meson compile -C build - name: Test run: | source venv/bin/activate meson test -C build --print-errorlogs xkbcommon-libxkbcommon-54ee7ac/.github/workflows/pages.yml000066400000000000000000000017341510033435100241070ustar00rootroot00000000000000name: Deploy to GitHub pages on: push: branches: ["master"] # Allow running this workflow manually from the Actions tab workflow_dispatch: permissions: contents: read pages: write id-token: write # Allow only one concurrent deployment concurrency: group: "pages" cancel-in-progress: false jobs: deploy: runs-on: ubuntu-22.04 environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} steps: - name: Download doxygen from Linux build uses: dawidd6/action-download-artifact@v10 with: workflow: linux.yml workflow_conclusion: success name: doxygen-docs path: doxygen/ - name: Setup Pages uses: actions/configure-pages@v5 - name: Upload pages artifact uses: actions/upload-pages-artifact@v4 with: path: doxygen/ - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 xkbcommon-libxkbcommon-54ee7ac/.github/workflows/windows.yml000066400000000000000000000024131510033435100244750ustar00rootroot00000000000000name: windows on: push: branches: [ master ] pull_request: branches: [ master ] # Set permissions at the job level. permissions: {} jobs: windows: runs-on: windows-2022 permissions: contents: read strategy: matrix: cc: ['cl', 'clang-cl'] env: CC: ${{matrix.cc}} steps: - uses: actions/checkout@v5 with: persist-credentials: false - uses: actions/setup-python@v5 with: python-version: '3.12' - name: Install dependencies shell: cmd run: | # Jinja2 is needed for merge-modes tests python -m pip install --upgrade meson Jinja2 choco install -y winflexbison3 - name: Setup shell: cmd run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 meson setup --backend=vs -Denable-wayland=false -Denable-x11=false -Denable-docs=false -Denable-xkbregistry=false build - name: Build shell: cmd run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 meson compile -C build - name: Test run: meson test -C build --print-errorlogs xkbcommon-libxkbcommon-54ee7ac/.pre-commit-config.yaml000066400000000000000000000015661510033435100231540ustar00rootroot00000000000000# See https://pre-commit.com for more information # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-added-large-files - repo: https://github.com/charliermarsh/ruff-pre-commit rev: v0.9.0 hooks: - id: ruff # ambiguous-variable-name (E741), line-too-long (E501) args: ['--ignore=E741,E501', '.'] - id: ruff-format # 88 is the black default args: ['--line-length=88', '--check', '--diff', '.',] # [TODO] C linter/formatter # Note: There is an old config file for uncrustify (https://uncrustify.sourceforge.net) # in the repo, but we may want to migrate to other modern style. # - repo: https://github.com/pre-commit/mirrors-clang-format # rev: v16.0.6 # hooks: # - id: clang-format xkbcommon-libxkbcommon-54ee7ac/.uncrustify.cfg000066400000000000000000000126401510033435100216400ustar00rootroot00000000000000tok_split_gte=false utf8_byte=true utf8_force=true indent_cmt_with_tabs=false indent_align_string=false indent_braces=false indent_braces_no_func=false indent_braces_no_class=false indent_braces_no_struct=false indent_brace_parent=false indent_namespace=false indent_extern=false indent_class=false indent_class_colon=false indent_else_if=false indent_var_def_cont=false indent_func_call_param=false indent_func_def_param=false indent_func_proto_param=false indent_func_class_param=false indent_func_ctor_var_param=false indent_template_param=false indent_func_param_double=false indent_relative_single_line_comments=false indent_col1_comment=false indent_access_spec_body=false indent_paren_nl=false indent_comma_paren=false indent_bool_paren=false indent_first_bool_expr=false indent_square_nl=false indent_preserve_sql=false indent_align_assign=true sp_balance_nested_parens=false align_keep_tabs=false align_with_tabs=false align_on_tabstop=false align_number_left=false align_func_params=false align_same_func_call_params=false align_var_def_colon=true align_var_def_attribute=true align_var_def_inline=true align_right_cmt_mix=false align_on_operator=false align_mix_var_proto=false align_single_line_func=false align_single_line_brace=false align_nl_cont=false align_left_shift=true align_oc_decl_colon=true nl_collapse_empty_body=true nl_assign_leave_one_liners=true nl_class_leave_one_liners=true nl_enum_leave_one_liners=true nl_getset_leave_one_liners=true nl_func_leave_one_liners=true nl_if_leave_one_liners=true nl_multi_line_cond=false nl_multi_line_define=false nl_before_case=true nl_after_case=true nl_after_return=false nl_after_semicolon=true nl_after_brace_open=true nl_after_brace_open_cmt=false nl_after_vbrace_open=false nl_after_vbrace_open_empty=false nl_after_brace_close=false nl_after_vbrace_close=false nl_define_macro=false nl_squeeze_ifdef=false nl_ds_struct_enum_cmt=false nl_ds_struct_enum_close_brace=false nl_create_if_one_liner=false nl_create_for_one_liner=false nl_create_while_one_liner=false ls_for_split_full=false ls_func_split_full=false nl_after_multiline_comment=false eat_blanks_after_open_brace=false eat_blanks_before_close_brace=false mod_full_brace_if_chain=false mod_pawn_semicolon=false mod_full_paren_if_bool=false mod_remove_extra_semicolon=false mod_sort_import=false mod_sort_using=false mod_sort_include=false mod_move_case_break=false mod_remove_empty_return=false cmt_indent_multi=true cmt_c_group=false cmt_c_nl_start=false cmt_c_nl_end=false cmt_cpp_group=false cmt_cpp_nl_start=false cmt_cpp_nl_end=false cmt_cpp_to_c=true cmt_star_cont=true cmt_multi_check_last=true cmt_insert_before_preproc=false pp_indent_at_level=false pp_region_indent_code=false pp_if_indent_code=false pp_define_at_level=false indent_columns=4 indent_brace=0 indent_switch_case=0 align_struct_init_span=2 align_pp_define_gap=0 align_pp_define_span=2 align_oc_msg_colon_span=16 nl_end_of_file_min=1 nl_func_var_def_blk=0 code_width=78 nl_max=2 newlines=auto indent_with_tabs=0 sp_arith=force sp_assign=force sp_assign_default=force sp_before_assign=force sp_after_assign=force sp_enum_assign=force sp_enum_before_assign=force sp_enum_after_assign=force sp_pp_stringify=add sp_bool=force sp_compare=force sp_inside_paren=remove sp_paren_paren=remove sp_paren_brace=force sp_before_ptr_star=ignore sp_before_unnamed_ptr_star=force sp_before_byref=force sp_before_unnamed_byref=force sp_after_byref=remove sp_after_type=force sp_before_sparen=force sp_inside_sparen=remove sp_inside_sparen_close=remove sp_after_sparen=force sp_sparen_brace=force sp_special_semi=force sp_before_semi=remove sp_after_semi=force sp_after_semi_for=force sp_after_semi_for_empty=force sp_before_square=remove sp_inside_square=remove sp_after_comma=force sp_before_comma=remove sp_paren_comma=force sp_before_ellipsis=force sp_after_class_colon=force sp_before_class_colon=force sp_before_case_colon=remove sp_after_cast=force sp_inside_paren_cast=remove sp_sizeof_paren=remove sp_inside_braces_enum=force sp_inside_braces_struct=force sp_inside_braces=force sp_inside_braces_empty=force sp_func_proto_paren=remove sp_func_def_paren=remove sp_inside_fparens=remove sp_inside_fparen=remove sp_square_fparen=remove sp_fparen_brace=force sp_func_call_paren=remove sp_func_call_paren_empty=remove sp_return_paren=force sp_attribute_paren=remove sp_defined_paren=remove sp_macro=force sp_macro_func=force sp_else_brace=force sp_brace_else=force sp_brace_typedef=force sp_not=remove sp_inv=remove nl_start_of_file=remove nl_end_of_file=force nl_assign_square=remove nl_after_square_assign=remove nl_fcall_brace=remove nl_enum_brace=remove nl_struct_brace=remove nl_union_brace=remove nl_if_brace=remove nl_brace_else=force nl_elseif_brace=remove nl_else_brace=remove nl_else_if=remove nl_for_brace=remove nl_do_brace=remove nl_brace_while=remove nl_switch_brace=remove nl_case_colon_brace=force nl_func_type_name=force nl_func_type_name_class=force nl_func_proto_type_name=force nl_func_paren=remove nl_func_def_paren=remove nl_func_decl_start=remove nl_func_def_start=remove nl_func_decl_args=remove nl_func_decl_end=remove nl_func_def_end=remove nl_func_decl_end_single=remove nl_func_def_end_single=remove nl_func_decl_empty=remove nl_func_def_empty=remove nl_fdef_brace=force nl_return_expr=remove nl_before_if=ignore nl_after_if=ignore nl_before_for=ignore nl_after_for=ignore nl_before_while=ignore nl_after_while=ignore nl_before_switch=ignore nl_after_switch=ignore nl_before_do=ignore nl_after_do=ignore pp_space=remove xkbcommon-libxkbcommon-54ee7ac/LICENSE000066400000000000000000000310241510033435100176700ustar00rootroot00000000000000The following is a list of all copyright notices and license statements which appear in the xkbcommon source tree, along with the SPDX short license identifiers which source files use to refer to them. To see which parts are covered by which license and copyright, refer to the source files. If making new contributions, the MIT License is vastly preferred. All licenses are derivative of the MIT/X11 license, mostly identical other than no-endorsement clauses (e.g. paragraph 4 of The Open Group's license). These statements are split into two sections: one for the code compiled and distributed as part of the libxkbcommon shared library and the code component of all tests, and another only for the test data under test/data, which is distributed with the xkbcommon source code, but not installed to the system. BEGINNING OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS: ------------------------------------------------------------------------------- SPDX full name: MIT License SPDX short identifier: MIT License text: Copyright © 2008-2009 Dan Nicholson Copyright © 2009-2012, 2016 Daniel Stone Copyright © 2012-2014, 2020-2022, 2025 Ran Benita Copyright © 2010-2012, 2016 Intel Corporation Copyright © 2013-2015, 2018-2020 Red Hat, Inc. Copyright © 2023-2024 Pierre Le Marre Copyright (c) 1991, Oracle and/or its affiliates. Copyright © 2008-2011 Kristian Høgsberg Copyright © 2010 Francisco Jerez Copyright © 2012 Collabora, Ltd. Copyright © 2015 Kazunobu Kuriyama Copyright (C) 2011 Joseph Adams Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- SPDX full name: MIT Open Group variant SPDX short identifier: MIT-open-group License text: Copyright 1985, 1987, 1988, 1990, 1998 The Open Group Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the names of the authors or their institutions shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the authors. ------------------------------------------------------------------------------- SPDX full name: Historical Permission Notice and Disclaimer SPDX short identifier: HPND License text: Copyright (c) 1993, 1994, 1995, 1996 by Silicon Graphics Computer Systems, Inc. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Silicon Graphics not be used in advertising or publicity pertaining to distribution of the software without specific prior written permission. Silicon Graphics makes no representation about the suitability of this software for any purpose. It is provided "as is" without any express or implied warranty. SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- SPDX full name: Historical Permission Notice and Disclaimer - sell variant SPDX short identifier: HPND-sell-variant License text: Copyright 1992 by Oki Technosystems Laboratory, Inc. Copyright 1992 by Fuji Xerox Co., Ltd. Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Oki Technosystems Laboratory and Fuji Xerox not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Oki Technosystems Laboratory and Fuji Xerox make no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL OKI TECHNOSYSTEMS LABORATORY AND FUJI XEROX BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- SPDX full name: SPDX short identifier: LicenseRef-digital-equipment-corporation License text: Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- END OF SOFTWARE COPYRIGHT/LICENSE STATEMENTS BEGINNING OF LICENSE STATEMENTS ONLY FOR UNDISTRIBUTED DATA FILES IN test/data, derived from xkeyboard-config and libX11 nls/ directory: ------------------------------------------------------------------------------- SPDX full name: Historical Permission Notice and Disclaimer - sell variant SPDX short identifier: HPND-sell-variant Copyright 1996 by Joseph Moss Copyright (C) 2002-2007 Free Software Foundation, Inc. Copyright (C) Dmitry Golubev , 2003-2004 Copyright (C) 2004, Gregory Mokhin Copyright (C) 2006 Erdal Ronahî Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of the copyright holder(s) not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. The copyright holder(s) makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. THE COPYRIGHT HOLDER(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ------------------------------------------------------------------------------- SPDX full name: MIT License SPDX short identifier: MIT Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved. ------------------------------------------------------------------------------- SPDX full name: X11 License SPDX short identifier: X11 License text: Copyright (c) 1996 X Consortium Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of the X Consortium shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the X Consortium. ------------------------------------------------------------------------------- SPDX full name: MIT Open Group variant SPDX short identifier: MIT-open-group Copyright (C) 2004, 2006 Ævar Arnfjörð Bjarmason ------------------------------------------------------------------------------- SPDX full name: SPDX short identifier: MIT-open-group SPDX short identifier: LicenseRef-anton-zinoviev License text: Copyright (C) 1999, 2000 by Anton Zinoviev This software may be used, modified, copied, distributed, and sold, in both source and binary form provided that the above copyright and these terms are retained. Under no circumstances is the author responsible for the proper functioning of this software, nor does the author assume any responsibility for damages incurred with its use. Permission is granted to anyone to use, distribute and modify this file in any way, provided that the above copyright notice is left intact and the author of the modification summarizes the changes in this header. This file is distributed without any expressed or implied warranty. xkbcommon-libxkbcommon-54ee7ac/NEWS.md000066400000000000000000002247451510033435100177770ustar00rootroot00000000000000libxkbcommon [1.12.3] – 2025-10-29 ================================== [1.12.3]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.12.3 ## API ### Fixes - X11: Hardened against some malformed XKB responses with erroneous modifiers or LEDs counts. ## Tools ### Fixes - Fixed support for Windows compilers other than MSVC ([#897](https://github.com/xkbcommon/libxkbcommon/pull/897), [#898](https://github.com/xkbcommon/libxkbcommon/pull/898), [#899](https://github.com/xkbcommon/libxkbcommon/pull/899)). Contributed by Rosen Penev - Fixed errors in Wayland tools ([#900](https://github.com/xkbcommon/libxkbcommon/pull/900)). Contributed by Ronan Pigott ## Build system ### Fixes - Fixed build setup failing in cross-compiling setups where the build machine cannot run the host binaries ([#885](https://github.com/xkbcommon/libxkbcommon/issues/885)). libxkbcommon [1.12.2] – 2025-10-20 ================================== [1.12.2]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.12.2 ## API ### Fixes - Context: Added fallback to the legacy X11 path for misconfigured setups where the canonical XKB root is not available. Some setups use the assumption that the canonical XKB root is always the legacy X11 one, but this is no longer true since [xkeyboard-config 2.45], where the X11 path is now a mere symlink to a dedicated xkeyboard-config data directory (usually `/usr/share/xkeyboard-config-2`). - Compose: Fixed some C standard libraries such as musl not detecting missing locales. ([#879](https://github.com/xkbcommon/libxkbcommon/issues/879)) [xkeyboard-config 2.45]: https://xkeyboard-config.freedesktop.org/blog/2-45-release/#build-system libxkbcommon [1.12.1] – 2025-10-17 ================================== [1.12.1]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.12.1 ## API ### Fixes - X11: Added a fix to circumvent libX11 and xserver improperly handling missing XKB canonical key types. The fix prevents triggering an error when retrieving such keymap using libxkbcommon-x11. ## Tools ### Fixes - `xkbcli interactive-wayland`: memory error triggering in some setups. Contributed by Jan Alexander Steffens libxkbcommon [1.12.0] – 2025-10-10 ================================== The highlight of this release is the performance improvements for keymap handling: - about 1.6× speedup at *serializing* with default options; - about 1.7× speedup at *parsing* keymaps serialized by libxkbcommon, otherwise at least 1.1×. [1.12.0]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.12.0 ## API ### Breaking changes - `xkb_keymap::xkb_keymap_get_as_string()` does not pretty-print the keymap anymore. Use `xkb_keymap::xkb_keymap_get_as_string2()` with `::XKB_KEYMAP_SERIALIZE_PRETTY` to get the previous behavior. ([#640](https://github.com/xkbcommon/libxkbcommon/issues/640)) - `xkb_keymap::xkb_keymap_get_as_string()` does not serialize *unused* types and compatibility entries anymore. Use `xkb_keymap::xkb_keymap_get_as_string2()` with `::XKB_KEYMAP_SERIALIZE_KEEP_UNUSED` to get the previous behavior. ([#769](https://github.com/xkbcommon/libxkbcommon/issues/769)) - Updated keysyms case mappings to cover full [Unicode 17.0]. [Unicode 17.0]: https://www.unicode.org/versions/Unicode17.0.0/ ### Deprecated - Deprecated keysyms from latest [xorgproto] \(commit: `81931cc0fd4761b42603f7da7d4f50fc282cecc6`, [xorproto-103]): - `XKB_KEY_XF86BrightnessAuto` (use `XKB_KEY_XF86MonBrightnessAuto` instead) [xorproto-103]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/103 ### New - Added `xkb_keymap::xkb_keymap_get_as_string2()`, which enables to configure the serialization. - Added keysyms from latest [xorgproto] \(commit: `81931cc0fd4761b42603f7da7d4f50fc282cecc6`, [xorproto-103]): - `XKB_KEY_XF86Sport` - `XKB_KEY_XF86MonBrightnessAuto` (alias for `XKB_KEY_XF86BrightnessAuto`) - `XKB_KEY_XF86LinkPhone` - `XKB_KEY_XF86Fn_F1` - `XKB_KEY_XF86Fn_F2` - `XKB_KEY_XF86Fn_F3` - `XKB_KEY_XF86Fn_F4` - `XKB_KEY_XF86Fn_F5` - `XKB_KEY_XF86Fn_F6` - `XKB_KEY_XF86Fn_F7` - `XKB_KEY_XF86Fn_F8` - `XKB_KEY_XF86Fn_F9` - `XKB_KEY_XF86Fn_F10` - `XKB_KEY_XF86Fn_F11` - `XKB_KEY_XF86Fn_F12` - `XKB_KEY_XF86Fn_1` - `XKB_KEY_XF86Fn_2` - `XKB_KEY_XF86Fn_D` - `XKB_KEY_XF86Fn_E` - `XKB_KEY_XF86Fn_F` - `XKB_KEY_XF86Fn_S` - `XKB_KEY_XF86Fn_B` - `XKB_KEY_XF86PerformanceMode` - Enable to parse the full range of keycodes `0 .. 0xfffffffe`, which was previously limited to `0 .. 0xfff`. ([#849](https://github.com/xkbcommon/libxkbcommon/issues/849)) - Compose: Custom locales now fallback to `en_US.UTF-8`. Custom locales requiring a dedicated Compose file are not yet supported. The workaround is to use the various ways to [specify a user Compose file]. [specify a user Compose file]: @ref xkb_compose_table::xkb_compose_table_new_from_locale() ## Tools ### New - `xkbcli {compile-keymap,dump-keymap*}`: Added `--no-pretty` to disable pretty-printing in keymap serialization. ([#640](https://github.com/xkbcommon/libxkbcommon/issues/640)) - `xkbcli {compile-keymap,dump-keymap*}`: Added `--keep-unused` to not discard unused bit for keymap serialization. ([#769](https://github.com/xkbcommon/libxkbcommon/issues/769)) - `xkbcli-compile-keymap`: Added `--kccgst-yaml` to output KcCGST components in YAML format. ## Build system ### Breaking changes - The *default* XKB root directory is now set from the *most recent* [xkeyboard-config](https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config) installed package, in case [multiple versions](https://xkeyboard-config.freedesktop.org/doc/versioning/) are installed in parallel. If no such package is found, it fallbacks to the historical X11 directory, as previously. libxkbcommon [1.11.0] – 2025-08-08 ================================== The highlight of this release is the introduction of a new keymap text format, `::XKB_KEYMAP_FORMAT_TEXT_V2`, in order to fix decade-old issues inherited from the X11 ecosystem. See the API section for documentation of its use. [1.11.0]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.11.0 ## Keymap text format ### New A new keymap text format **v2** has been introduced as a superset of the legacy **v1** format. The format is not yet frozen and considered a living standard, although future iterations should be backward-compatible. See the [compatibility page] for detailed information of the features of each format. - Added the new parameter `lockOnRelease` for the key action `LockGroup()` ([#420](https://github.com/xkbcommon/libxkbcommon/issues/420)). It enables to use e.g. the combination `Alt + Shift` *alone* to switch layouts, while keeping the use of `Alt + Shift + other key` (typically for keyboard shortcuts). It enables to fix a [20-year old issue][xserver-258] inherited from the X11 ecosystem, by extending the [XKB protocol key actions]. As it is incompatible with X11, this feature is available only using `::XKB_KEYMAP_FORMAT_TEXT_V2`. - Added the new parameter `unlockOnPress` for the key modifier action `SetMods()`, `LatchMods()` and `LockMods()` ([#372](https://github.com/xkbcommon/libxkbcommon/issues/372) and [#780](https://github.com/xkbcommon/libxkbcommon/issues/780)). It enables e.g. to deactivate `CapsLock` *on press* rather than on release, as in other platforms such as Windows. It enables to fix the following two issues inherited from the X11 ecosystem, by extending the [XKB protocol key actions]: - a [18-year old issue][xkeyboard-config-74]; - a [12-year old issue][xserver-312]. As it is incompatible with X11, this feature is available only using `::XKB_KEYMAP_FORMAT_TEXT_V2`. - Added the new parameter `latchOnPress` for the key action `LatchMods()`. Some keyboard layouts use `ISO_Level3_Latch` or `ISO_Level5_Latch` to define “built-in” dead keys. `latchOnPress` enables to behave as usual dead keys, i.e. to latch on press and to deactivate as soon as another (non-modifier) key is pressed. As it is incompatible with X11, this feature is available only using `::XKB_KEYMAP_FORMAT_TEXT_V2`. - Raised the layout count limit from 4 to 32. Requires using `::XKB_KEYMAP_FORMAT_TEXT_V2`. ([#37](https://github.com/xkbcommon/libxkbcommon/issues/37)) It enables to fix a [16-year old issue][xserver-262] inherited from the X11 ecosystem. - Virtual modifiers are now mapped to their [canonical encoding] if they are not mapped *explicitly* (`virtual_modifiers M = …`) nor *implicitly* (using `modifier_map`/`virtualModifier`). This feature is enabled only when using `::XKB_KEYMAP_FORMAT_TEXT_V2`, as it may result in encodings not compatible with X11. - Added support for the constants `Level` for *any* valid level index, instead of the previous limited range `Level1`..`Level8`. - Enable to use absolute paths and `%`-expansion variables for including *keymap components*, in the same fashion than the *rules* files. [compatibility page]: https://xkbcommon.org/doc/current/xkbcommon-compatibility.html [XKB protocol key actions]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Key_Actions [xkeyboard-config-74]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/issues/74 [xserver-258]: https://gitlab.freedesktop.org/xorg/xserver/-/issues/258 [xserver-262]: https://gitlab.freedesktop.org/xorg/xserver/-/issues/262 [xserver-312]: https://gitlab.freedesktop.org/xorg/xserver/-/issues/312 [canonical encoding]: https://xkbcommon.org/doc/current/keymap-text-format-v1-v2.html#canonical-and-non-canonical-modifiers ## Rules text format ### New - Added support for *layout-specific options*. It enables specifying a layout index for each option by appending `!` + 1-indexed layout, so that it applies only if the layout matches. ([#500](https://github.com/xkbcommon/libxkbcommon/issues/500)) ## API ### Breaking changes - `xkb_keymap_new_from_names()` now uses the new keymap format `::XKB_KEYMAP_FORMAT_TEXT_V2`. - When using `::XKB_KEYMAP_FORMAT_TEXT_V1`, multiple actions per level are now serialized using `VoidAction()`, in order to maintain compatibility with X11. ([#793](https://github.com/xkbcommon/libxkbcommon/issues/793)) ### Deprecated - `xkb_keymap_new_from_names()` is now deprecated; please use `xkb_keymap_new_from_names2()` instead with an explicit keymap format. ### New - Added the new keymap format `::XKB_KEYMAP_FORMAT_TEXT_V2`, which enables libxkbcommon’s extensions incompatible with X11. Note that *fallback* mechanisms ensure that it is possible to parse using one format and serialize using another. **Wayland compositors** may use the new format to *parse* keymaps, but they *must* use the previous format `::XKB_KEYMAP_FORMAT_TEXT_V1` whenever *serializing* for interchange. Since almost features available only in the v2 format deal with state handling which is managed in the server, clients should not be affected by a v2-to-v1 conversion. **Client applications** should use the previous `::XKB_KEYMAP_FORMAT_TEXT_V1` to parse keymaps, at least for now. They may use `::XKB_KEYMAP_FORMAT_TEXT_V2` only if used with a Wayland compositor using the same version of libxkbcommon *and* serializing to the new format. This precaution will be necessary until the new format is stabilized. - Added `xkb_keymap_new_from_names2()` as an alternative to `xkb_keymap_new_from_names()`, which is deprecated. - Added `xkb_keymap_new_from_rmlvo()` to compile a keymap using the new RMLVO builder API. - Added a API to safely build a RMLVO configuration: - `xkb_rmlvo_builder_new()` - `xkb_rmlvo_builder_append_layout()` - `xkb_rmlvo_builder_append_option()` - `xkb_rmlvo_builder_ref()` - `xkb_rmlvo_builder_unref()` - Added `xkb_keymap_mod_get_mask2()` to query the mapping of a modifier by its index rather than it name. - Update keysyms using latest [xorgproto] \(commit: `ce7786ebb90f70897f8038d02ae187ab22766ab2`). Additions ([xorgproto-93]): - `XKB_KEY_XF86MediaSelectCD` (alias for `XKB_KEY_XF86CD`) - `XKB_KEY_XF86OK` - `XKB_KEY_XF86GoTo` - `XKB_KEY_XF86VendorLogo` - `XKB_KEY_XF86MediaSelectProgramGuide` - `XKB_KEY_XF86MediaSelectHome` - `XKB_KEY_XF86MediaLanguageMenu` - `XKB_KEY_XF86MediaTitleMenu` - `XKB_KEY_XF86AudioChannelMode` - `XKB_KEY_XF86MediaSelectPC` - `XKB_KEY_XF86MediaSelectTV` - `XKB_KEY_XF86MediaSelectCable` - `XKB_KEY_XF86MediaSelectVCR` - `XKB_KEY_XF86MediaSelectVCRPlus` - `XKB_KEY_XF86MediaSelectSatellite` - `XKB_KEY_XF86MediaSelectTape` - `XKB_KEY_XF86MediaSelectRadio` - `XKB_KEY_XF86MediaSelectTuner` - `XKB_KEY_XF86MediaPlayer` - `XKB_KEY_XF86MediaSelectTeletext` - `XKB_KEY_XF86MediaSelectDVD` (alias for `XKB_KEY_XF86DVD`) - `XKB_KEY_XF86MediaSelectAuxiliary` - `XKB_KEY_XF86MediaPlaySlow` - `XKB_KEY_XF86NumberEntryMode` [xorgproto-93]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/93 - Registry: added `rxkb_option_is_layout_specific()` to query if an option accepts layout index specifiers to restrict its application to the corresponding layouts. ([#500](https://github.com/xkbcommon/libxkbcommon/issues/500)) ### Fixes - Fixed incorrect implementation of `latchToLock` for `LatchMods()`, which could result in unintended `CapsLock` unlock. ([#808](https://github.com/xkbcommon/libxkbcommon/issues/808)) - Fixed `xkb_utf32_to_keysym()` returning deprecated keysyms for some Unicode code points. - Fixed breaking a latch not honoring `clearLocks=no`. ## Tools ### Breaking changes - The tools now use: - `::XKB_KEYMAP_FORMAT_TEXT_V2` as a default *input* format. - `::XKB_KEYMAP_USE_ORIGINAL_FORMAT` as a default *output* format. So if the input format is not specified, it will resolve to `::XKB_KEYMAP_FORMAT_TEXT_V2`. The formats can be explicitly specified using the new `--*format` options. ### New - Added `--*format` options to various tools for specifying and explicit keymap format for parsing and serializing. - Added commands that automatically select the appropriate backend: - `xkbcli interactive`: try Wayland, X11 then fallback to the evdev backend. - `xkbcli dump-keymap`: try Wayland then fallback to the X11 backend. - Improved `xkbcli interactive-*`: - Print key release events. - Print detailed state change events. - Added `--uniline` to enable uniline event output (default). - Added `--multiline` to enable multiline event output, which provides more details than the uniline mode. - Wayland and X11: Added `--local-state` to enable handling the keyboard state with a local state machine instead of the display server. ([#832](https://github.com/xkbcommon/libxkbcommon/issues/832)) - Wayland and X11: Added `--keymap` to enable to use a custom keymap instead of the keymap from the display server. Implies `--local-state`. ([#833](https://github.com/xkbcommon/libxkbcommon/issues/833)) - `xkbcli how-to-type`: Added `--keymap` to enable loading the keymap from a file or stdin instead of resolving RMLVO names. - `xkbcli how-to-type`: Added Compose support, enabled by default and disabled using `--disable-compose`. ([#361](https://github.com/xkbcommon/libxkbcommon/issues/361)) - `xkbcli-list`: Added `layout-specific` field for options. ([#500](https://github.com/xkbcommon/libxkbcommon/issues/500)) - Added `--verbose` to various tools, so that all tools have the option. ([#833](https://github.com/xkbcommon/libxkbcommon/issues/833)) libxkbcommon [1.10.0] – 2025-05-21 ================================== [1.10.0]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.10.0 ## API ### Breaking changes - *Modifiers masks* handling has been refactored to properly handle virtual modifiers. Modifier masks are now always considered as an *opaque encoding* of the modifiers state: - Modifiers masks should not be interpreted by other means than the provided API. In particular, one should not assume that modifiers masks always denote the modifiers *indices* of the keymap. - It enables using virtual modifiers with arbitrary mappings. E.g. one can now reliably create virtual modifiers without relying on the legacy X11 mechanism, that requires a careful use of keys’ real and virtual modmaps. - It enables *interoperability* with further implementations of XKB. - Changed *Compose* behavior so that sequences defined later always override ones defined earlier, even if the new sequence is shorter. Contributed by Jules Bertholet ### Deprecated - Server applications using `xkb_state_update_mask()` should migrate to using `xkb_state_update_latched_locked()` instead, for proper handling of the keyboard state. ([#310](https://github.com/xkbcommon/libxkbcommon/issues/310)) - The following modifiers names in `xkbcommon/xkbcommon-names.h` are now deprecated and will be removed in a future version: - `XKB_MOD_NAME_ALT`: use `XKB_VMOD_NAME_ALT` instead. - `XKB_MOD_NAME_LOGO`: use `XKB_VMOD_NAME_SUPER` instead. - `XKB_MOD_NAME_NUM`: use `XKB_VMOD_NAME_NUM` instead. ([#538](https://github.com/xkbcommon/libxkbcommon/issues/538)) ### New - Added `xkb_state_update_latched_locked()` to update the keyboard state to change the latched and locked state of the modifiers and layout. This entry point is intended for *server* applications and should not be used by *client* applications. This can be use for e.g. a GUI layout switcher. ([#310](https://github.com/xkbcommon/libxkbcommon/issues/310)) - Added `xkb_keymap_mod_get_mask()` to query the mapping of a modifier. - Added `VoidAction()` action to match the keysym pair `NoSymbol`/`VoidSymbol`. It enables erasing a previous action and breaks latches. This is a libxkbcommon extension. When serializing it will be converted to `LockControls(controls=none,affect=neither)` for backward compatibility. ([#622](https://github.com/xkbcommon/libxkbcommon/issues/622)) - Improved syntax errors in XKB files to include the expected/got tokens. ([#644](https://github.com/xkbcommon/libxkbcommon/issues/644)) ### Fixes - *Compose*: fixed sequence not fully overriden if the new sequence has no keysym or string. ## Tools ### New - `xkbcli-compile-keymap`: Added option `--modmaps` that prints modifiers mappings. This is similar to the legacy `xmodmap -pm`. ## Build system ### Breaking changes - Removed support for byacc -- use bison instead. ([#644](https://github.com/xkbcommon/libxkbcommon/issues/644)) - Required bison ≥ 3.6. libxkbcommon [1.9.2] – 2025-05-07 ================================= [1.9.2]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.9.2 ## API ### Fixes - Fixed empty compatibility interpretation statement not parsable by X11’s `xkbcomp`. This particularly affects Japanese layout `jp` when used with Xwayland. ([#750](https://github.com/xkbcommon/libxkbcommon/issues/750)) - Fixed empty compatibility interpretations map not parsable by X11’s `xkbcomp`. - Fixed key type map entries with a mix of bound and unbound modifiers not being ignored. ([#758](https://github.com/xkbcommon/libxkbcommon/issues/758)) libxkbcommon [1.9.1] – 2025-05-02 ================================= [1.9.1]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.9.1 ## API ### Fixes - X11: Fixed capitalization transformation not set properly, resulting in some keys (e.g. arrows, Home, etc.) not working when Caps Lock is on. ([#740](https://github.com/xkbcommon/libxkbcommon/issues/740)) libxkbcommon [1.9.0] – 2025-04-26 ================================= [1.9.0]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.9.0 ## API ### Breaking changes - *Merge modes* and *include mechanism* were completely refactored to fix inconsistencies. Included files are now always processed in isolation and do not propagate the local merge modes. This makes the reasoning about included files much easier and consistent. - Trailing `NoSymbol` and `NoAction()` are now dropped. This may affect keys that rely on an *implicit* key type. Example: - Input: ```c key <> { [a, A, NoSymbol] }; ``` - Compilation with libxkbcommon \< 1.9.0: ```c key <> { type= "FOUR_LEVEL_SEMIALPHABETIC", [a, A, NoSymbol, NoSymbol] }; ``` - Compilation with libxkbcommon ≥ 1.9.0: ```c key <> { type= "ALPHABETIC", [a, A] }; ``` ### New - Added function `xkb_components_names_from_rules()` to compute KcCGST keymap components from RMLVO names resolution. This mainly for *debugging* purposes and to enable the `--kccgst` option in the tools. ([#669](https://github.com/xkbcommon/libxkbcommon/issues/669)) - Added the following *wild cards* to the **rules** file syntax, in addition to the current `*` legacy wild card: - ``: Match *empty* value. - ``: Match *non-empty* value. - ``: Match *any* (optionally empty) value. Its behavior does not depend on the context, contrary to the legacy wild card `*`. - All keymap components are now optional, e.g. a keymap without a `xkb_types` section is now legal. The missing components will still be serialized explicitly in order to maintain backward compatibility. - Added support for further empty compound statements: - `xkb_types`: `type "xxx" {};` - `xkb_compat`: `interpret x {};` and `indicator "xxx" {};`. Such statements are initialized using the current defaults, i.e. the factory implicit defaults or some explicit custom defaults (e.g. `indicator.modifiers = Shift`). - Added support for actions and keysyms level list of length 0 and 1: respectively `{}` and `{a}`. Example: `key { [{}, {a}, {a, A}] };`. - Enable using the merge mode *replace* in include statements using the prefix `^`, such as: `include "a^b"`. The main motivation is to enable this new syntax in *rules*, which previously could not handle this merge mode. - Added support for sequences of actions in `interpret` statements of the `xkb_compat` component, mirroring the syntax used in `xkb_symbols`. ([#695](https://github.com/xkbcommon/libxkbcommon/issues/695)) - Added support for keysym Capitalization transformation to `xkb_state_key_get_syms()`. ([#552](https://github.com/xkbcommon/libxkbcommon/issues/552)) - `xkb_utf32_to_keysym`: Allow [Unicode noncharacters]. ([#715](https://github.com/xkbcommon/libxkbcommon/issues/715)) - `xkb_keysym_from_name()`: - Unicode format `UNNNN`: allow control characters C0 and C1 and use `xkb_utf32_to_keysym()` for the conversion when `NNNN < 0x100`, for backward compatibility. - Numeric hexadecimal format `0xNNNN`: *unchanged*. Contrary to the Unicode format, it does not normalize any keysym values in order to enable roundtrip with `xkb_keysym_get_name()`. [Unicode noncharacters]: https://en.wikipedia.org/wiki/Universal_Character_Set_characters#Noncharacters ([#715](https://github.com/xkbcommon/libxkbcommon/issues/715)) - Added [Unicode code point] escape sequences `\u{NNNN}`. They are replaced with the [UTF-8] encoding of their corresponding code point `U+NNNN`, if legal. Supported Unicode code points are in the range `1‥0x10ffff`. This is intended mainly for writing keysyms as [UTF-8] encoded strings. [Unicode code point]: https://en.wikipedia.org/wiki/Unicode#Codespace_and_code_points [UTF-8]: https://en.wikipedia.org/wiki/UTF-8 - Enable to write keysyms as UTF-8-encoded strings: - *Single* Unicode code point `U+1F3BA` (TRUMPET) `"🎺"` is converted into a single keysym: `U1F3BA`. - *Multiple* Unicode code points are converted to a keysym *list* where it is allowed (i.e. in key symbols). E.g. `"J́"` is converted to U+004A LATIN CAPITAL LETTER J plus U+0301 COMBINING ACUTE ACCENT: `{J, U0301}`. - An empty string `""` denotes the keysym `NoSymbol`. - Enable displaying bidirectional text in XKB files using the following Unicode code points, wherever a white space can be used: - `U+200E` LEFT-TO-RIGHT MARK - `U+200F` RIGHT-TO-LEFT MARK ### Fixes - Added support for `libxml2-2.14+`, which now disallows parsing trailing `NULL` bytes. ([#692](https://github.com/xkbcommon/libxkbcommon/issues/692)) - Fixed included *default* section not resolving to an *exact* match in some cases. It may occur if one creates a file name in a *user* XKB directory that also exists in the XKB *system* directory. Example: if one creates a custom variant `my_variant` in the file `$XDG_CONFIG_HOME/xkb/symbols/us`, then *before* libxkbcommon 1.9.0 every statement loading the *default* map of the `us` file, `include "us"`, would wrongly resolve including `us(my_variant)` from the *user* configuration directory instead of `us(basic)` from the XKB *system* directory. Starting from libxkbcommon 1.9.0, `include "us"` would correctly resolve to the system file, unless `$XDG_CONFIG_HOME/xkb/symbols/us` contains an *explicit default* section. ([#726](https://github.com/xkbcommon/libxkbcommon/issues/726)) - Fixed floating-point number parsing failling on locales that use a decimal separator different than the period `.`. Note that the issue is unlikely to happen even with such locales, unless *parsing* a keymap with a *geometry* component which contains floating-point numbers. Affected API: - `xkb_keymap_new_from_file()`, - `xkb_keymap_new_from_buffer()`, - `xkb_keymap_new_from_string()`. Unaffected API: - `xkb_keymap_new_from_names()`: none of the components loaded use floating-point number. libxkbcommon does not load *geometry* files. - `libxkbcommon-x11`: no such parsing is involved. - Fixed the handling of empty keys. Previously keys with no symbols nor actions would simply be skipped entirely. E.g. in the following: ```c key { vmods = M }; modifier_map Shift { }; ``` the key `` would be skipped and the virtual modifier `M` would not be mapped to `Shift`. This is now handled properly. - Fixed characters not escaped properly in the keymap serialization, resulting in a keymap string with erroneous string literals and possible syntax errors. - Fixed octal escape sequences valid in Xorg’s xkbcomp but not in xkbcommon. Now up to *4* digits are parsed, compared to *3* previously. - Fixed the serialization of the `whichGroupState` indicator field. ## Tools ### New - `xkbcli compile-keymap`: Added `--kccgst` option to display the result of RMLVO names resolution to KcCGST components. This option has the same function than `setxkbmap -print`. This is particularly useful for debugging issues with the rules. ([#669](https://github.com/xkbcommon/libxkbcommon/issues/669)) - Honor user locale in all tools. libxkbcommon [1.8.1] – 2025-03-12 ================================= [1.8.1]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.8.1 ## API ### Fixes - Fixed segfault due to invalid arithmetic to bring *negative* layout indices into range. It triggers with the following settings: - layouts count (per key or total) N: `N > 0`, and - layout index n: `n = - k * N` (`k > 0`) Note that these settings are unlikely in usual use cases. ## Tools ### Breaking changes - The tools do not load the *default* RMLVO (rules, model, layout, variant, options) values from the environment anymore. The previous behavior may be restored by using the new `--enable-environment-names` option. ## Build system ### New - Source files are now annotated with SPDX short license identifiers. The LICENSE file was updated to accommodate this. ([#628](https://github.com/xkbcommon/libxkbcommon/issues/628)) libxkbcommon [1.8.0] – 2025-02-04 ================================= [1.8.0]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.8.0 ## API ### Breaking changes - `NoSymbol` is now systematically dropped in multi-keysyms levels: ```c // Before normalization key <> { [{NoSymbol}, {a, NoSymbol}, {NoSymbol,b}, {a, NoSymbol, b}] }; // After normalization key <> { [NoSymbol, a, b, {a, b}] }; ``` - Added the upper case mapping ß → ẞ (`ssharp` → `U1E9E`). This enable to type ẞ using CapsLock thanks to the internal capitalization rules. - Updated keysyms case mappings to cover full **[Unicode 16.0]**. This change provides a *consistent behavior* with respect to case mappings, and affects the following: - `xkb_keysym_to_lower()` and `xkb_keysym_to_upper()` give different output for keysyms not covered previously and handle *title*-cased keysyms. Example of title-cased keysym: `U01F2` “Dz”: - `xkb_keysym_to_lower(U01F2) == U01F3` “Dz” → “dz” - `xkb_keysym_to_upper(U01F2) == U01F1` “Dz” → “DZ” - *Implicit* alphabetic key types are better detected, because they use the latest Unicode case mappings and now handle the *title*-cased keysyms the same way as upper-case ones. Note: There is a single *exception* that do not follow the Unicode mappings: - `xkb_keysym_to_upper(ssharp) == U1E9E` “ß” → “ẞ” Note: As before, only *simple* case mappings (i.e. one-to-one) are supported. For example, the full upper case of `U+01F0` “ǰ” is “J̌” (2 characters: `U+004A` and `U+030C`), which would require 2 keysyms, which is not supported by the current API. [Unicode 16.0]: https://www.unicode.org/versions/Unicode16.0.0/ ### New - Implemented the `GroupLatch` action, usually activated with the keysym `ISO_Group_Latch`. ([#455](https://github.com/xkbcommon/libxkbcommon/issues/455)) - Symbols: Added support for *multiple actions per levels:* - When no action is specified, `interpret` statements are used to find an action corresponding to *each* keysym, as expected. - When both keysyms and actions are specified, they may have a different count for each level. - For now, at most one action of each of the following categories is allowed per level: - modifier actions: `SetMods`, `LatchMods`, `LockMods`; - group actions: `SetGroup`, `LatchGroup`, `LockGroup`. Some examples: - `SetMods` + `SetGroup`: ok - `SetMods` + `SetMods`: error - `SetMods` + `LockMods`: error - `SetMods` + `LockGroup`: ok ([#486](https://github.com/xkbcommon/libxkbcommon/issues/486)) - Updated keysyms using latest [xorgproto] \(commit: `d7ea44d5f04cc476dee83ef439a847172f7a6bd1`): Additions: - `XKB_KEY_XF86RefreshRateToggle` - `XKB_KEY_XF86Accessibility` - `XKB_KEY_XF86DoNotDisturb` Relevant upstream merge request: [xorgproto-91]. [xorgproto-91]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/91 - Added deprecated keysym warnings: - *name* deprecation (typo, historical alias), reporting the reference name; - *keysym* deprecation (ambiguous meaning, all names deprecated). These warnings are activated by setting the log verbosity to at least 2. It is advised to fix these warnings, as the deprecated items may be removed in a future release. - `xkbcommon-names.h`: Added the following modifiers names definitions: - `XKB_MOD_NAME_MOD1` - `XKB_MOD_NAME_MOD2` - `XKB_MOD_NAME_MOD3` - `XKB_MOD_NAME_MOD4` - `XKB_MOD_NAME_MOD5` - `XKB_VMOD_NAME_ALT` - `XKB_VMOD_NAME_META` - `XKB_VMOD_NAME_NUM` - `XKB_VMOD_NAME_SUPER` - `XKB_VMOD_NAME_HYPER` - `XKB_VMOD_NAME_LEVEL3` - `XKB_VMOD_NAME_LEVEL5` - `XKB_VMOD_NAME_SCROLL` - `xkbcommon-names.h`: Added `XKB_LED_NAME_COMPOSE` and `XKB_LED_NAME_KANA` definitions to cover all LEDs defined in [USB HID](https://usb.org/sites/default/files/hid1_11.pdf). Contributed by Martin Rys - Rules: Use XKB paths to resolve relative paths in include statements. ([#501](https://github.com/xkbcommon/libxkbcommon/issues/501)) - Rules: Added support for special layouts indices: - *single*: matches a single layout; `layout[single]` is the same as without explicit index: `layout`. - *first*: matches the first layout/variant, no matter how many layouts are in the RMLVO configuration. Acts as both `layout` and `layout[1]`. - *later*: matches all but the first layout. This is an index range. Acts as `layout[2]` .. `layout[MAX_LAYOUT]`, where `MAX_LAYOUT` is currently 4. - *any*: matches layout at any position. This is an index range. Also added: - the special index `%i` which correspond to the index of the matched layout. - the `:all` qualifier: it applies the qualified item to all layouts. See the [documentation](https://xkbcommon.org/doc/current/rule-file-format.html) for further information. ### Fixes - Previously, setting *explicit actions* for a group in symbols files made the parser skip compatibility interpretations for *all* groups in the corresponding key, resulting in possibly broken groups with *no* explicit actions or missing key fields. Fixed by skipping interpretations only for groups with explicit actions when parsing a keymap and setting relevant fields explicitly when serializing a keymap to a string. ([#511](https://github.com/xkbcommon/libxkbcommon/issues/511)) - `xkb_keymap_new_from_names()`: Allow only one group per key in symbols sections. While the original issue was [fixed in `xkeyboard-config`][xkeyboard-config-253] project, the previous handling in `libxkbcommon` of extra key groups was deemed unintuitive. [xkeyboard-config-253]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/merge_requests/253 Note: rules resolution may still produce more groups than the input layouts. This is currently true for some [legacy rules in `xkeyboard-config`][xkeyboard-config-legacy-rules]. ([#262](https://github.com/xkbcommon/libxkbcommon/issues/262)) [xkeyboard-config-legacy-rules]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/6a2eb9e63bcb3c52584580570d31cd91110d1f2e/rules/0013-modellayout_symbols.part#L2 - Fixed `xkb_keymap_get_as_string` truncating the *4* longest keysyms names, such as `Greek_upsilonaccentdieresis`. - `xkb_keysym_to_utf8`: Require only 5 bytes for the buffer, as UTF-8 encodes code points on up to 4 bytes + 1 byte for the NULL-terminating byte. Previous standard [RFC 2279](https://datatracker.ietf.org/doc/html/rfc2279) (1998) required up to 6 bytes per code point, but has been superseded by [RFC 3629](https://datatracker.ietf.org/doc/html/rfc3629) (2003). ([#418](https://github.com/xkbcommon/libxkbcommon/issues/418)) - Registry: Fixed `libxml2` global error handler not reset after parsing, which could trigger a crash if the corresponding `rxkb_context` has been freed. Contributed by Sebastian Keller. ([#529](https://github.com/xkbcommon/libxkbcommon/issues/529)) - Rules: Fix handling of wild card `*` to match the behavior of `libxkbfile`. Previously `*` would match any value, even empty one. Now: - For `model` and `options`: *always* match. - For `layout` and `variant`: match any *non-empty* value. ([#497](https://github.com/xkbcommon/libxkbcommon/issues/497)) - Fixed `LatchGroup` action with the `latchToLock` option disabled not applying its latch effect multiple times. ([#577](https://github.com/xkbcommon/libxkbcommon/issues/577)) - Fixed incorrect handling of group indicators when `whichGroupState` is set with `Base` or `Latched`. ([#579](https://github.com/xkbcommon/libxkbcommon/issues/579)) - Fixed missing explicit virtual modifier mappings when export the keymap as a string. - Fixed the lower case mapping ẞ → ß (`U1E9E` → `ssharp`). This re-enable the detection of alphabetic key types for the pair (ß, ẞ). - Fixed modifiers not properly unset when multiple latches are used simultaneously. ([#583](https://github.com/xkbcommon/libxkbcommon/issues/583)) - The following functions now allow to query also *virtual* modifiers, so they work with *any* modifiers (real *and* virtual): - `xkb_state_mod_index_is_active()` - `xkb_state_mod_indices_are_active()` - `xkb_state_mod_name_is_active()` - `xkb_state_mod_names_are_active()` - `xkb_state_mod_index_is_consumed()` - `xkb_state_mod_index_is_consumed2()` - `xkb_state_mod_mask_remove_consumed()` Warning: they may overmatch in case there are overlappings virtual-to-real modifiers mappings. - X11: Do not drop a level when the keysym is undefined but not the action. ## Tools ### New - Added `xkbcli dump-keymap-wayland` and `xkbcli dump-keymap-x11` debugging tools to dump a keymap from a Wayland compositor or a X server, similar to what `xkbcomp -xkb $DISPLAY -` does for X servers. - `xkbcli compile-compose`: the Compose file may be passed as a positional argument and `--file` is now deprecated. The file can also be piped to the standard input by setting the path to `-`. - `xkbcli compile-keymap`: Added `--keymap` as a more intuitive alias for `--from-xkb`. Both now accept an optional keymap file argument. These flags may be omitted; in this case the keymap file may be passed as a positional argument. - Added `--test` option to `compile-keymap` and `compile-compose`, to enable testing compilation without printing the resulting file. - `xkbcli how-to-type`: added new input formats and their corresponding documentation. *Unicode code points* can be passed in the following formats: - Literal character (requires UTF-8 character encoding of the terminal); - Decimal number; - Hexadecimal number: either `0xNNNN` or `U+NNNN`. *Keysyms* can to be passed in the following formats: - Decimal number; - Hexadecimal number: `0xNNNN`; - Name. ### Fixes - Fixed various tools truncating the *4* longest keysyms names, such as `Greek_upsilonaccentdieresis`. - `xkbcli list`: Fix duplicate variants. ([#587](https://github.com/xkbcommon/libxkbcommon/issues/587)) ## Build system ### Breaking changes - Raised minimal meson version requirement to 0.58. ### Fixes - Make the test of `-Wl,--version-script` more robust. ([#481](https://github.com/xkbcommon/libxkbcommon/issues/481)) libxkbcommon [1.7.0] – 2024-03-24 ================================= [1.7.0]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-1.7.0 API --- ### New - Added early detection of invalid encodings and BOM for keymaps, rules & Compose. Also added a hint that the expected encoding must be UTF-8 compatible. ### Fixes - Updated keysyms using latest [xorgproto] \(commit: `cd33097fc779f280925c6d6bbfbd5150f93ca5bc`): For the sake of compatibility, this reintroduces some deleted keysyms and postpones the effective deprecation of others, that landed in xkbcommon 1.6.0. - Additions (reverted removal): - `XKB_KEY_dead_lowline` - `XKB_KEY_dead_aboveverticalline` - `XKB_KEY_dead_belowverticalline` - `XKB_KEY_dead_longsolidusoverlay` - The following keysyms names remain deprecated, but are set again (i.e. as before xkbcommon 1.6.0) as the reference names for their respective keysyms, in order to ensure the transition to the newer names that replace them. This affects functions such as `xkb_keymap_key_get_name` and `xkb_keymap_get_as_string`. - `XKB_KEY_masculine`: is deprecated in favor of `XKB_KEY_ordmasculine` - `XKB_KEY_guillemotleft`: is deprecated in favor of `XKB_KEY_guillemetleft` - `XKB_KEY_guillemotright`: is deprecated in favor of `XKB_KEY_guillemetright` - `XKB_KEY_dead_small_schwa`: is deprecated in favor of `XKB_KEY_dead_schwa` - `XKB_KEY_dead_capital_schwa`: is deprecated in favor of `XKB_KEY_dead_SCHWA` Relevant upstream merge requests: [xorgproto-83], [xorgproto-84]. [xorgproto-83]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/83 [xorgproto-84]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/84 - Keysyms: Fixed inconsistent results in `xkb_keysym_from_name` when used with the flag `XKB_KEYSYM_CASE_INSENSITIVE`. In some rare cases it would return a keysym with an upper-case name instead of the expected lower-case (e.g. `XKB_KEY_dead_A` instead of `XKB_KEY_dead_a`). - Keysyms: Fixed case mapping for 3 Latin 1 keysyms: - `XKB_KEY_ydiaeresis` - `XKB_KEY_mu` - `XKB_KEY_ssharp` - Keysyms: Fixed `xkb_keysym_is_modifier` to detect also the following keysyms: - `XKB_KEY_ISO_Level5_Shift` - `XKB_KEY_ISO_Level5_Latch` - `XKB_KEY_ISO_Level5_Lock` - Prevent recursive includes of keymap components. - Fixed global default statements `x.y = z;` in wrong scope not raising an error. Contributed by Mikhail Gusarov - Keymap: Fixed empty symbols declaration. Contributed by Yuichiro Hanada. - Rules: Made newline required after `!include` line. Contributed by Mikhail Gusarov. - Rules: Fixed a bug where variant indices were ignored with the layout index used instead. They are practically always the same, but don’t have to be. Contributed by \@wysiwys. - Compose: Fixed a segfault with `xkb_compose_table_iterator_next` when used on an empty table. - Compose: Added check to ensure to open only regular files, not e.g. directories. - Registry: Updated the DTD and always parse the “popularity” attribute. - Fixed a few memory leaks and keymap symbols parsing. Tools ----- ### New - `xkbcli compile-compose`: added new CLI utility to test Compose files. - `xkbcli interactive-evdev`: added `--verbose` option. - `xkbcli interactive-x11`: added support for Compose. - `xkbcli interactive-wayland`: added support for Compose. ### Fixes - Bash completion: Fixed completion in some corner cases. Build system ------------ - Fix building with clang when using `-Wl,--gc-sections`. Contributed by ppw0. - Fixed linking using `lld 1.17`. Contributed by Baptiste Daroussin. - Fix building X11 tests on macOS. - Documentation is no longer built by default; it requires `-Denable-docs=true`. libxkbcommon 1.6.0 – 2023-10-08 ================== API --- ### Breaking changes - *Remove* keysyms that were intended for German T3 layout but are unused: - `XKB_KEY_dead_lowline` - `XKB_KEY_dead_aboveverticalline` - `XKB_KEY_dead_belowverticalline` - `XKB_KEY_dead_longsolidusoverlay` See the upstream [`xorgproto` MR](https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/70). See hereinafter for further changes related to keysyms. ### New - Add Compose iterator API to iterate the entries in a compose table: - `xkb_compose_table_entry_sequence()` - `xkb_compose_table_entry_keysym()` - `xkb_compose_table_entry_utf8()` - `xkb_compose_table_iterator_new()` - `xkb_compose_table_iterator_free()` - `xkb_compose_table_iterator_next()` - *Structured log messages* with a message registry. There is an *ongoing* work to assign unique identifiers to log messages and add a corresponding error index documentation page: - The log entries are preceded with an identifier in the form `XKB-NNN`, where `NNN` is a decimal number. - The log entries can then be parsed with third-party tools, to check for specific identifiers. - The new documentation page “**Error index**” lists all the kind of error messages with their identifiers. The aim is that each entry could present detailed information on the error and how to fix it. - Add a new warning for numeric keysyms references in XKB files: the preferred keysym reference form is its name or its Unicode value, if relevant. - Add the upper bound `XKB_KEYSYM_MAX` to check valid keysyms. - Add a warning when loading a keymap using RMLVO with no layout but with the variant set. The variant is actually discarded and both layout and variant are set to default values, but this was done previously with no warning, confusing end users. - Add support for `modifier_map None { … }`. This feature is missing compared to the X11 implementation. It allows to reset the modifier map of a key. - Update keysyms using latest [xorgproto] \(commit: `1c8128d72df22843a2022576850bc5ab5e3a46ea`): - Additions: - `XKB_KEY_ordmasculine` ([xorgproto-68]) - `XKB_KEY_guillemetleft` ([xorgproto-68]) - `XKB_KEY_guillemetright` ([xorgproto-68]) - `XKB_KEY_dead_schwa` ([xorgproto-78]) - `XKB_KEY_dead_SCHWA` ([xorgproto-78]) - `XKB_KEY_dead_hamza` ([xorgproto-71]) - `XKB_KEY_XF86EmojiPicker` ([xorgproto-44]) - `XKB_KEY_XF86Dictate` ([xorgproto-49]) - `XKB_KEY_XF86CameraAccessEnable` ([xorgproto-82]) - `XKB_KEY_XF86CameraAccessDisable` ([xorgproto-82]) - `XKB_KEY_XF86CameraAccessToggle` ([xorgproto-82]) - `XKB_KEY_XF86NextElement` ([xorgproto-82]) - `XKB_KEY_XF86PreviousElement` ([xorgproto-82]) - `XKB_KEY_XF86AutopilotEngageToggle` ([xorgproto-82]) - `XKB_KEY_XF86MarkWaypoint` ([xorgproto-82]) - `XKB_KEY_XF86Sos` ([xorgproto-82]) - `XKB_KEY_XF86NavChart` ([xorgproto-82]) - `XKB_KEY_XF86FishingChart` ([xorgproto-82]) - `XKB_KEY_XF86SingleRangeRadar` ([xorgproto-82]) - `XKB_KEY_XF86DualRangeRadar` ([xorgproto-82]) - `XKB_KEY_XF86RadarOverlay` ([xorgproto-82]) - `XKB_KEY_XF86TraditionalSonar` ([xorgproto-82]) - `XKB_KEY_XF86ClearvuSonar` ([xorgproto-82]) - `XKB_KEY_XF86SidevuSonar` ([xorgproto-82]) - `XKB_KEY_XF86NavInfo` ([xorgproto-82]) - Deprecations: - `XKB_KEY_masculine`: use `XKB_KEY_ordmasculine` instead ([xorgproto-68]) - `XKB_KEY_guillemotleft`: use `XKB_KEY_guillemetleft` instead ([xorgproto-68]) - `XKB_KEY_guillemotright`: use `XKB_KEY_guillemetright` instead ([xorgproto-68]) - `XKB_KEY_dead_small_schwa`: use `XKB_KEY_dead_schwa` instead ([xorgproto-78]) - `XKB_KEY_dead_capital_schwa`: use `XKB_KEY_dead_SCHWA` instead ([xorgproto-78]) [xorgproto]: https://gitlab.freedesktop.org/xorg/proto/xorgproto [xorgproto-44]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/44 [xorgproto-49]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/49 [xorgproto-68]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/68 [xorgproto-71]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/71 [xorgproto-78]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/78 [xorgproto-82]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/merge_requests/82 - Ongoing work to improve the documentation about XKB and its V1 format. ### Fixes - Prevent `xkb_keysym_from_name` to parse out-of-range hexadecimal keysyms. - Disallow producing NULL character with escape sequences `\0` and `\x0`. - Prevent overflow of octal escape sequences by making `\400..\777` invalid. - Prevent interpreting and emitting invalid Unicode encoding forms: surrogates are invalid in both UTF-32 and UTF-8. - `xkb_keymap_new_from_buffer`: Allow for a NULL-terminated keymap string. - Compose: Increase the limit of possible entries to handle huge Compose files. Contributed by alois31. Tools ----- ### New - Add bash completions for `xkbcli` and its subcommands. - `xkbcli interactive-*`: Add options `--short` to hide some fields. - `xkbcli interactive-evdev`: Add `--includes` and `--include-defaults` options. - Add `xkb-check-messages` *experimental* tool (not installed). It checks whether given log messages identifiers are supported. ### Fixes - `xkbcli compile-keymap`: Allow to use without arguments. - `xkbcli interactive-*`: Always print keycode. - `xkbcli interactive-*`: Escape control characters for Unicode output, instead of printing them as-is, messing the output. Build system ------------ - Bump required meson to 0.52.0. - Allow `xkbcommon` to be used as a subproject. Contributed by Simon Ser. - Improve Windows compilation. libxkbcommon 1.5.0 – 2023-01-02 ================== - Add `xkb_context` flag `XKB_CONTEXT_NO_SECURE_GETENV` and `rxkb_context` flag `RXKB_CONTEXT_NO_SECURE_GETENV`. xkbcommon uses `getenv_secure()` to obtain environment variables. This flag makes xkbcommon use `getenv()` instead. This is useful for some clients that have relatively benign capabilities set, like `CAP_SYS_NICE`, that also want to use e.g. the XKB configuration from the environment and user configs in `$XDG_CONFIG_HOME`. Contributed by Ronan Pigott. - Fix crash in `xkbcli interactive-wayland` under a compositor which supports new versions of the xdg-shell protocol. Contributed by Jan Alexander Steffens (heftig). - Fix some MSVC build issues. - Fix some issues when including xkbcommon as a meson subproject. - meson\>=0.51 is now required. - New API: `XKB_CONTEXT_NO_SECURE_GETENV` `RXKB_CONTEXT_NO_SECURE_GETENV` libxkbcommon 1.4.1 – 2022-05-21 ================== - Fix compose sequence overriding (common prefix) not working correctly. Regressed in 1.2.0. Contributed by Weng Xuetian. - Remove various bogus currency sign (particulary Euro and Korean Won) entries from the keysym ↔ Unicode mappings. They prevented the real keysyms/codepoints for these from mapping correctly. Contributed by Sam Lantinga and Simon Ser. libxkbcommon 1.4.0 – 2022-02-04 ================== - Add `enable-tools` option to Meson build (on by default) to allow disabling the `xkbcli` tools. Contributed by Alex Xu (Hello71). - In `xkbcli list`, fix “YAML Norway problem” in output. Contributed by Peter Hutterer. - In libxkbregistry, variants now inherit iso639, iso3166 and brief from parent layout if omitted. Contributed by M Hickford. - In libxkbregistry, don’t call `xmlCleanupParser()` - it’s not supposed to be called by libraries. Contributed by Peter Hutterer. - In libxkbregistry, skip over invalid ISO-639 or ISO-3166 entries. Contributed by Peter Hutterer. libxkbcommon 1.3.1 – 2021-09-10 ================== - In `xkbcli interactive-x11`, use the Esc keysym instead of the Esc keycode for quitting. Contributed by Simon Ser. - In `xkbcli how-to-type`, add `--keysym` argugment for how to type a keysym instead of a Unicode codepoint. - Fix a crash in `xkb_x11_keymap_new_from_device()` error handling given some invalid keymaps. Regressed in 1.2.0. Reported by Zack Weinberg. Tested by Uli Schlachter. libxkbcommon 1.3.0 – 2021-05-01 ================== - Change `xkbcli list` to output YAML, instead of the previous ad-hoc format. This allows to more easily process the information in a programmetic way, for example xkbcli list | yq -r ".layouts[].layout" Contributed by Peter Hutterer. - Optimize a certain part of keymap compilation (atom interning). - Fix segmentation fault in case-insensitive `xkb_keysym_from_name()` for certain values like the empty string. Contributed by Isaac Freund. - Support building libxkbcommon as a meson subproject. Contributed by Adrian Perez de Castro. - Add `ftruncate` fallback for `posix_fallocate` in `xkbcli interactive-wayland` for FreeBSD. Contributed by Evgeniy Khramtsov. - Properly export library symbols in MSVC. Contributed by Adrian Perez de Castro. libxkbcommon 1.2.1 – 2021-04-07 ================== - Fix `xkb_x11_keymap_new_from_device()` failing when the keymap contains key types with missing level names, like the one used by the `numpad:mac` option in [xkeyboard-config]. Regressed in 1.2.0. libxkbcommon 1.2.0 – 2021-04-03 ================== - `xkb_x11_keymap_new_from_device()` is much faster. It now performs only 2 roundtrips to the X server, instead of dozens (in first-time calls). Contributed by Uli Schlachter. - Case-sensitive `xkb_keysym_from_name()` is much faster. - Keysym names of the form `0x12AB` and `U12AB` are parsed more strictly. Previously the hexadecimal part was parsed with `strtoul()`, now only up to 8 hexadecimal digits (`0-9A-Fa-f`) are allowed. - Compose files now have a size limit (65535 internal nodes). Further sequences are discared and a warning is issued. - Compose table loading (`xkb_compose_table_new_from_locale()` and similar) is much faster. - Use `poll()` instead of `epoll()` for `xlbcli interactive-evdev`, making it portable to FreeBSD which provides evdev but not epoll. On FreeBSD, remember to install the `evdev-proto` package to get the evdev headers. - The build now requires a C11 compiler (uses anonymous structs/unions). libxkbcommon 1.1.0 – 2021-02-27 ================== - Publish the `xkb-format-text-v1.md` file in the HTML documentation. This file existed for a long time but only in the Git repository. Link: https://xkbcommon.org/doc/current/md_doc_keymap_format_text_v1.html - Add partial documentation for `xkb_symbols` to `xkb-format-text-v1.md`. Contributed by Simon Zeni. - Update keysym definitions to latest xorgproto. In particular, this adds many special keysyms corresponding to Linux evdev keycodes. Contributed by Peter Hutterer <\@who-t.net>. - New API: Too many `XKB_KEY_*` definitions to list here. libxkbcommon 1.0.3 – 2020-11-23 ================== - Fix (hopefully) a segfault in `xkb_x11_keymap_new_from_device()` in some unclear situation (bug introduced in 1.0.2). - Fix keymaps created with `xkb_x11_keymap_new_from_device()` don’t have level names (bug introduced in 0.8.0). libxkbcommon 1.0.2 – 2020-11-20 ================== - Fix a bug where a keysym that cannot be resolved in a keymap gets compiled to a garbage keysym. Now it is set to `XKB_KEY_NoSymbol` instead. - Improve the speed of `xkb_x11_keymap_new_from_device()` on repeated calls in the same `xkb_context()`. libxkbcommon 1.0.1 – 2020-09-11 ================== - Fix the `tool-option-parsing` test failing. - Remove requirement for pytest in the tool-option-parsing test. - Make the table output of `xkbcli how-to-type` aligned. - Some portability and test isolation fixes. libxkbcommon 1.0.0 – 2020-09-05 ================== Note: this release is API and ABI compatible with previous releases –the major version bump is only an indication of stability. - Add libxkbregistry as configure-time optional library. libxkbregistry is a C library that lists available XKB models, layouts and variants for a given ruleset. This is a separate library (`libxkbregistry.so`, pkgconfig file `xkbregistry.pc`) and aimed at tools that provide a listing of available keyboard layouts to the user. See the Documentation for details on the API. Contributed by Peter Hutterer <\@who-t.net>. - Better support custom user configuration: * Allow including XKB files from other paths. Previously, a `symbols/us` file in path A would shadow the same file in path B. This is suboptimal, we rarely need to hide the system files - we care mostly about *extending* them. By continuing to check other lookup paths, we make it possible for a `$XDG_CONFIG_HOME/xkb/symbols/us` file to have sections including those from `/usr/share/X11/xkb/symbols/us`. Note that this is not possible for rules files, which need to be manually controlled to get the right bits resolved. * Add /etc/xkb as extra lookup path for system data files. This completes the usual triplet of configuration locations available for most processes: - vendor-provided data files in `/usr/share/X11/xkb` - system-specific data files in `/etc/xkb` - user-specific data files in `$XDG_CONFIG_HOME/xkb` The default lookup order user, system, vendor, just like everything else that uses these conventions. For include directives in rules files, the `%E` resolves to that path. * Add a new section to the documentation for custom user configuration. Contributed by Peter Hutterer <\@who-t.net>. - Add an `xkbcli` command-line utility. This tool offers various subcommands for introspection and debugging. Currently the available subcommands are:
list
List available rules, models, layouts, variants and options
interactive-wayland
Interactive debugger for XKB keymaps for Wayland
interactive-x11
Interactive debugger for XKB keymaps for X11
interactive-evdev
Interactive debugger for XKB keymaps for evdev (Linux)
compile-keymap
Compile an XKB keymap
how-to-type
See separate entry below.
See the manpages for usage information. Contributed by Peter Hutterer <\@who-t.net>. - Add `xkb_utf32_to_keysym()` to translate a Unicode codepoint to a keysym. When a special keysym (`XKB_KEY_` constant) for the codepoint exists, it is returned, otherwise the direct encoding is used, if permissible. Contributed by Jaroslaw Kubik <\@froglogic.com>. - Add `xkb_keymap_key_get_mods_for_level()` which retrieves sets of modifiers which produce a given shift level in a given key+layout. Contributed by Jaroslaw Kubik <\@froglogic.com>. - Add `xkbcli how-to-type` command, which, using `xkb_utf32_to_keysym()` and `xkb_keymap_key_get_mods_for_level()` and other APIs, prints out all the ways to produce a given keysym. For example, how to type `?` (codepoint 63) in a `us,de` keymap? $ xkbcli how-to-type --layout us,de 63 | column -ts $'\t' keysym: question (0x3f) KEYCODE KEY NAME LAYOUT# LAYOUT NAME LEVEL# MODIFIERS 20 AE11 2 German 2 [ Shift ] 20 AE11 2 German 2 [ Shift Lock ] 61 AB10 1 English (US) 2 [ Shift ] - Add a new section to the documentation describing the format of the XKB rules file. - Search for Compose in `$XDG_CONFIG_HOME/XCompose` (fallback to `~/.config/XCompose`) before trying `$HOME/.XCompose`. Note that libX11 still only searches in `$HOME/.XCompose`. Contributed by Emmanuel Gil Peyrot <\@linkmauve.fr>. - Bump meson requirement to \>= 0.49.0. - Fix build with byacc. - Fix building X11 tests on PE targets. Contributed by Jon Turney <\@dronecode.org.uk> - The tests no longer rely on bash, only Python (which is already used by meson). - New API: `xkb_utf32_to_keysym` `xkb_keymap_key_get_mods_for_level` `XKB_KEY_XF86FullScreen` libxkbcommon 0.10.0 – 2020-01-18 =================== - (security) Fix quadratic complexity in the XKB file parser. See commit message 7c42945e04a2107827a057245298dedc0475cc88 for details. - Add `$XDG_CONFIG_HOME/xkb` to the default search path. If `$XDG_CONFIG_HOME` is not set, `$HOME/.config/xkb` is used. If `$HOME` is not set, the path is not added. The XDG path is looked up before the existing default search path $HOME/.xkb. Contributed by Peter Hutterer <\@who-t.net>. - Add support for include statements in XKB rules files. This is a step towards making local XKB customizations more tenable and convenient, without modifying system files. You can now include other rules files like this: ! include %S/evdev Two directives are supported, `%H` to `$HOME` and `%S` for the system-installed rules directory (usually `/usr/share/X11/xkb/rules`). See commit message ca033a29d2ca910fd17b1ae287cb420205bdddc8 and doc/rules-format.txt in the xkbcommon source code for more information. Contributed by Peter Hutterer <\@who-t.net>. - Downgrade “Symbol added to modifier map for multiple modifiers” log to a warning. This error message was too annoying to be shown by default. When working on keymaps, set `XKB_LOG_LEVEL=debug XKB_LOG_VERBOSITY=10` to see all possible messages. - Support building on Windows using the meson MSVC backend. Contributed by Adrian Perez de Castro <\@igalia.com>. - Fix bug where the merge mode only applied to the first vmod in a `virtual_modifiers` statement. Given augment virtual_modifiers NumLock,Alt,LevelThree Previously it was incorrectly treated as augment virtual_modifiers NumLock; virtual_modifiers Alt; virtual_modifiers LevelThree; Now it is treated as augment virtual_modifiers NumLock; augment virtual_modifiers Alt; augment virtual_modifiers LevelThree; - Reject interpret modifier predicate with more than one value. Given interpret ISO_Level3_Shift+AnyOf(all,extraneous) { ... }; Previously, extraneous (and further) was ignored. Now it’s rejected. - Correctly handle capitalization of the ssharp keysym. - Speed up and improve the internal `xkeyboard-config` tool. This tool compiles all layout/variant combinations in the [xkeyboard-config] dataset and reports any issues it finds. Contributed by Peter Hutterer <\@who-t.net>. - Speed up “atoms” (string interning). This code goes back at least to X11R1 (released 1987). libxkbcommon 0.9.1 – 2019-10-19 ================== - Fix context creation failing when run in privileged processes as defined by `secure_getenv(3)`, e.g. GDM. libxkbcommon 0.9.0 – 2019-10-19 ================== - Move `~/.xkb` to before `XKB_CONFIG_ROOT` (the system XKB path, usually `/usr/share/X11/xkb`) in the default include path. This enables the user to have full control of the keymap definitions, instead of only augmenting them. - Remove the Autotools build system. Use the meson build system instead. - Fix invalid names used for levels above 8 when dumping keymaps. Previously, e.g. `Level20` was dumped, but only up to `Level8` is accepted by the parser. Now `20` is dumped. - Change level references to always be dumped as e.g. `5` instead of `Level5`. Change group references to always be dumped capitalized e.g. `Group3` instead of `group3`. Previously it was inconsistent. These changes affect the output of `xkb_keymap_get_as_string()`. - Fix several build issues on macOS/Darwin, Solaris, NetBSD, cross compilation. - Port the `interactive-wayland` test program to the stable version of `xdg-shell`. libxkbcommon 0.8.4 – 2019-02-22 ================== - Fix build of xkbcommon-x11 static library with meson. - Fix building using meson from the tarball generated by autotools. libxkbcommon 0.8.3 – 2019-02-08 ================== - Fix build of static libraries with meson. (Future note: xkbcommon-x11 was *not* fixed in this release.) - New API: `XKB_KEY_XF86MonBrightnessCycle` `XKB_KEY_XF86RotationLockToggle` libxkbcommon 0.8.2 – 2018-08-05 ================== - Fix various problems found with fuzzing (see commit messages for more details): - Fix a few NULL-dereferences, out-of-bounds access and undefined behavior in the XKB text format parser. libxkbcommon 0.8.1 – 2018-08-03 ================== - Fix various problems found in the meson build (see commit messages for more details): - Fix compilation on Darwin. - Fix compilation of the x11 tests and demos when XCB is installed in a non-standard location. - Fix `xkbcommon-x11.pc` missing the Requires specification. - Fix various problems found with fuzzing and Coverity (see commit messages for more details): - Fix stack overflow in the XKB text format parser when evaluating boolean negation. - Fix NULL-dereferences in the XKB text format parser when some unsupported tokens appear (the tokens are still parsed for backward compatibility). - Fix NULL-dereference in the XKB text format parser when parsing an `xkb_geometry` section. - Fix an infinite loop in the Compose text format parser on some inputs. - Fix an invalid `free()` when using multiple keysyms. - Replace the Unicode characters for the leftanglebracket and rightanglebracket keysyms from the deprecated LEFT/RIGHT-POINTING ANGLE BRACKET to MATHEMATICAL LEFT/RIGHT ANGLE BRACKET. - Reject out-of-range Unicode codepoints in `xkb_keysym_to_utf8()` and `xkb_keysym_to_utf32()`. libxkbcommon 0.8.0 – 2017-12-15 ================== - Added `xkb_keysym_to_{upper,lower}` to perform case-conversion directly on keysyms. This is useful in some odd cases, but working with the Unicode representations should be preferred when possible. - Added Unicode conversion rules for the `signifblank` and `permille` keysyms. - Fixed a bug in the parsing of XKB key type definitions where the number of levels were determined by the number of level *names*. Keymaps which omit level names were hence miscompiled. This regressed in version 0.4.3. Keymaps from [xkeyboard-config] were not affected since they don’t omit level names. - New API: `xkb_keysym_to_upper()` `xkb_keysym_to_lower()` [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/ libxkbcommon 0.7.2 – 2017-08-04 ================== - Added a Meson build system as an alternative to existing autotools build system. The intent is to remove the autotools build in one of the next releases. Please try to convert to it and report any problems. See http://mesonbuild.com/Quick-guide.html for basic usage, the `meson_options.txt` for the project-specific configuration options, and the PACKAGING file for more details. There are some noteworthy differences compared to the autotools build: - Feature auto-detection is not performed. By default, all features are enabled (currently: `docs`, `x11`, `wayland`). The build fails if any of the required dependencies are not available. To disable a feature, pass `-Denable-=false` to meson. - The libraries are either installed as shared or static, as specified by the `-Ddefault_library=shared/static` option. With autotools, both versions are installed by default. - `xorg-util-macros` is not used. - A parser generator (bison/byacc) is always required - there is no fallback to pre-generated output bundled in the tarball, as there is in autotools. - Removed `Android.mk` support. - Removed the `*-uninstalled.pc` pkgconfig files. - Ported the `interactive-wayland` demo program to v6 of the `xdg-shell` protocol. - Added new keysym definitions from xproto. - New API: `XKB_KEY_XF86Keyboard` `XKB_KEY_XF86WWAN` `XKB_KEY_XF86RFKill` `XKB_KEY_XF86AudioPreset` libxkbcommon 0.7.1 – 2017-01-18 ================== - Fixed various reported problems when the current locale is `tr_TR.UTF-8`. The function `xkb_keysym_from_name()` used to perform case-insensitive string comparisons in a locale-dependent way, but required it to to work as in the C/ASCII locale (the so called “Turkish i problem”). The function is now no longer affected by the current locale. - Fixed compilation in NetBSD. libxkbcommon 0.7.0 – 2016-11-11 ================== - Added support for different “modes” of calculating consumed modifiers. The existing mode, based on the XKB standard, has proven to be unintuitive in various shortcut implementations. A new mode, based on the calculation used by the GTK toolkit, is added. This mode is less eager to declare a modifier as consumed. - Added a new interactive demo program using the Wayland protocol. See the PACKAGING file for the new (optional) test dependencies. - Fixed a compilation error on GNU Hurd. - New API: `enum xkb_consumed_mode` `XKB_CONSUMED_MODE_XKB` `XKB_CONSUMED_MODE_GTK` `xkb_state_key_get_consumed_mods2()` `xkb_state_mod_index_is_consumed2()` libxkbcommon 0.6.1 – 2016-04-08 ================== - Added LICENSE to distributed files in tarball releases. - Minor typo fix in `xkb_keymap_get_as_string()` documentation. libxkbcommon 0.6.0 – 2016-03-16 ================== - If the `XKB_CONFIG_ROOT` environment variable is set, it is used as the XKB configuration root instead of the path determined at build time. - Tests and benchmarks now build correctly on OSX. - An XKB keymap provides a name for each key it defines. Traditionally, these names are limited to at most 4 characters, and are thus somewhat obscure, but might still be useful (xkbcommon lifts the 4 character limit). The new functions `xkb_keymap_key_get_name()` and `xkb_keymap_key_by_name()` can be used to get the name of a key or find a key by name. Note that a key may have aliases. - Documentation improvements. - New API: `xkb_keymap_key_by_name()` `xkb_keymap_key_get_name()` libxkbcommon 0.5.0 – 2014-10-18 ================== - Added support for Compose/dead keys in a new module (included in libxkbcommon). See the documentation or the `xkbcommon/xkbcommon-compose.h` header file for more details. - Improved and reordered some sections of the documentation. - The doxygen HTML pages were made nicer to read. - Most tests now run also on non-linux platforms. - A warning is emitted by default about RMLVO values which are not used during keymap compilation, which are most often a user misconfiguration. For example, `terminate:ctrl_alt_backspace` instead of `terminate:ctrl_alt_bksp`. - Added symbol versioning for libxkbcommon and libxkbcommon-x11. Note: binaries compiled against this and future versions will not be able to link against the previous versions of the library. - Removed several compatablity symbols from the binary (the API isn’t affected). This affects binaries which 1. Were compiled against a pre-stable (\<0.2.0) version of libxkbcommon, and 2. Are linked against the this or later version of libxkbcommon. Such a scenario is likely to fail already. - If Xvfb is not available, the x11comp test is now correctly skipped instead of hanging. - Benchmarks were moved to a separate bench/ directory. - Build fixes from OpenBSD. - Fixed a bug where key type entries such as `map[None] = Level2;` were ignored. - New API: `XKB_COMPOSE_*` `xkb_compose_*` libxkbcommon 0.4.3 – 2014-08-19 ================== - Fixed a bug which caused `xkb_x11_keymap_new_from_device()` to misrepresent modifiers for some keymaps. https://github.com/xkbcommon/libxkbcommon/issues/9 - Fixed a bug which caused `xkb_x11_keymap_new_from_device()` to ignore XKB `PrivateAction`’s. - Modifiers are now always fully resolved after `xkb_state_update_mask()`. Previously the given state components were used as-is, without considering virtual modifier mappings. Note: this only affects non-standard uses of `xkb_state_update_mask()`. - Added a test for xkbcommon-x11, `x11comp`. The test uses the system’s Xvfb server and xkbcomp. If they do not exist or fail, the test is skipped. - Fixed memory leaks after parse errors in the XKB yacc parser. The fix required changes which are currently incompatible with byacc. libxkbcommon 0.4.2 – 2014-05-15 ================== - Fixed a bug where explicitly passing `--enable-x11` to `./configure` would in fact disable it (regressed in 0.4.1). - Added `@since` version annotations to the API documentation for everything introduced after the initial stable release (0.2.0). - Added a section to the documentation about keysym transformations, and clarified which functions perform a given transformation. - XKB files which fail to compile during keymap construction can no longer have any effect on the resulting keymap: changes are only applied when the entire compilation succeeds. Note: this was a minor correctness issue inherited from xkbcomp. - Fix an out-of-bounds array access in `src/x11/util.c:adopt_atoms()` error-handling code. Note: it seems impossible to trigger in the current code since the input size cannot exceed the required size. libxkbcommon 0.4.1 – 2014-03-27 ================== - Converted README to markdown and added a Quick Guide to the documentation, which breezes through the most common parts of xkbcommon. - Added two new functions, `xkb_state_key_get_utf{8,32}()`. They combine the operations of `xkb_state_key_get_syms()` and `xkb_keysym_to_utf{8,32}()`, and provide a nicer interface for it (especially for multiple-keysyms-per-level). - The `xkb_state_key_get_utf{8,32}()` functions now apply Control transformation: when the Control modifier is active, the string is converted to an appropriate control character. This matches the behavior of libX11’s `XLookupString(3)`, and required by the XKB specification: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier https://bugs.freedesktop.org/show_bug.cgi?id=75892 - The consumed modifiers for a key are now calculated similarly to libX11. The previous behavior caused a bug where Shift would not cancel an active Caps Lock. - Make xkbcommon-x11 work with the keymap reported by the XQuartz X server. https://bugs.freedesktop.org/show_bug.cgi?id=75798 - Reduce memory usage during keymap compilation some more. - New API: `xkb_state_key_get_consumed_mods()` `xkb_state_key_get_utf8()` `xkb_state_key_get_utf32()` - Deprecated API: `XKB_MAP_COMPILE_PLACEHOLDER,` `XKB_MAP_NO_FLAGS` use `XKB_KEYMAP_NO_FLAGS` instead. - Bug fixes. libxkbcommon 0.4.0 – 2014-02-02 ================== - Add a new add-on library, `xkbcommon-x11`, to support creating keymaps with the XKB X11 protocol, by querying the X server directly. See the `xkbcommon/xkbcommon-x11.h` header file for more details. This library requires `libxcb-xkb >= 1.10`, and is enabled by default. It can be disabled with the `--disable-x11` configure switch. Distributions are encouraged to split the necessary files for this library (`libxkbcommon-x11.so`, `xkbcommon-x11.pc`, `xkbcommon/xkbcommon-x11.h`) to a separate package, such that the main package does not depend on X11 libraries. - Fix the keysym ↔ name lookup table to not require huge amounts of relocations. - Fix a bug in the keysym ↔ name lookup, whereby lookup might fail in some rare cases. - Reduce memory usage during keymap compilation. - New API: New keysyms from xproto 7.0.25 (German T3 layout keysyms). `XKB_MOD_NAME_NUM` for the usual NumLock modifier. `xkb_x11_*` types and functions, `XKB_X11_*` constants. libxkbcommon 0.3.2 – 2013-11-22 ================== - Log messages from the library now look like `xkbcommon: ERROR` by default, instead of xkbcomp-like `Error: `. - Apply capitalization transformation on keysyms in `xkb_keysym_get_one_sym()`, to match the behavior specified in the XKB specification: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier - Support byacc for generating the parser, in addition to Bison. - New API: `XKB_KEY_XF86AudioMicMute` keysym from xproto 7.0.24. `XKB_KEYSYM_NO_FLAGS` `XKB_CONTEXT_NO_FLAGS` `XKB_MAP_COMPILE_NO_FLAGS` - Bug fixes. libxkbcommon 0.3.1 – 2013-06-03 ================== - Replace the flex scanner with a hand-written one. flex is no longer a build requirement. - New API: `xkb_keymap_min_keycode()` `xkb_keymap_max_keycode()` `xkb_keymap_key_for_each()` libxkbcommon 0.3.0 – 2013-04-01 ================== - Allow passing NULL to `*_unref()` functions; do nothing instead of crashing. - The functions `xkb_keymap_num_levels_for_key()` and `xkb_keymap_get_syms_by_level()` now allow out-of-range values for the `layout` parameter. The functions now wrap the value around the number of layouts instead of failing. - The function `xkb_keysym_get_name()` now types unicode keysyms in uppercase and 0-padding, to match the format used by `XKeysymToString()`. - Building Linux-specific tests is no longer attempted on non-Linux environments. - The function `xkb_keymap_new_from_names()` now accepts a NULL value for the `names` parameter, instead of failing. This is equivalent to passing a `struct xkb_rule_names` with all fields set to NULL. - New API: `xkb_keymap_new_from_buffer()` - Bug fixes. xkbcommon-libxkbcommon-54ee7ac/PACKAGING000066400000000000000000000051711510033435100200760ustar00rootroot00000000000000libxkbcommon consists of three shared libraries, libxkbcommon (the main library), libxkbcommon-x11 (an addon library for XCB clients) and libxkbregistry (a library to list available RMLVO options). The files for libxkbcommon-x11 are: libxkbcommon-x11.a libxkbcommon-x11.so* xkbcommon/xkbcommon-x11.h xkbcommon-x11.map xkbcommon-x11.pc libxkbcommon-x11 can be disabled with -Denable-x11=false (see `meson configure build` for other options/variables). The files for libxkbregistry are: libxkbregistry.a libxkbregistry.so* xkbcommon/xkbregistry.h xkbregistry.map xkbregistry.pc libxkbregistry can be disabled with -Denable-xkbregistry=false (see `meson configure build` for other options/variables). Dependencies for libxkbcommon: - C compiler, meson, pkg-config, libc. - (build) bison (preferred) or win_bison - (build optional, runtime required) xkeyboard-config. During build, for automatically detecting the value of -Dxkb-config-root instead of guessing (/usr/share/X11/xkb). During runtime, not strictly needed, but most users of the library would need it. - (runtime) libX11. Contains the dataset for Compose support (/usr/share/X11/locale). Please don't depend on it explicitly. - (build optional) doxygen. For generating the HTML documentation. To disable, use -Denable-docs=false. - (build optional) gperf. Output included in git and tarball. To regenerate, use `./scripts/update-keywords`. Dependencies for xkbcli: - libxkbcommon. Dependencies for libxkbcommon-x11: - libxkbcommon. - libxcb>=1.10 with libxcb-xkb. Dependencies for libxkbcommon-x11 tests: - xkbcomp, Xvfb. If they are not available, the relevant tests are skipped. Dependencies for libxkbregistry: - libxkbregistry is a sublibrary of libxkbcommon and cannot be built without building libxbkcommon. The files produced are otherwise independent. - libxml2 - (build optional, runtime requirement) xkeyboard-config During build, for automatically detecting the value of -Dxkb-config-root instead of guessing (/usr/share/X11/xkb). Dependencies for Wayland tests: - wayland-client>=1.2.0, wayland-scanner, wayland-protocols>=1.0. To disable, use -Denable-wayland=false. Unless libxcb is always available as part of the system, it is preferred that libxkbcommon and libxkbcommon-x11 be split into separate packages, such that the main library does not depend on libxcb. This avoids a transitive dependency of Wayland clients on X libraries. It is perferred that libxkbregistry be split into a separate packages as most clients that require libxkbcommon do not require libxkbregistry and clients requiring libxkbregistry may not need libxkbcommon. xkbcommon-libxkbcommon-54ee7ac/README.md000066400000000000000000000111031510033435100201360ustar00rootroot00000000000000# libxkbcommon **libxkbcommon** is a keyboard keymap compiler and support library which processes a reduced subset of keymaps as defined by the [XKB] \(X Keyboard Extension) specification. It also contains a module for handling *Compose* and dead keys, a separate *registry* library for listing available keyboard layouts and a fair set of CLI *tools*. [XKB]: doc/introduction-to-xkb.md ## Quick Guide - [Introduction to XKB][XKB]: to learn the essentials of XKB. - [User-configuration](doc/user-configuration.md): instructions to add a *custom layout* or option. - [Keymap format](doc/keymap-text-format-v1-v2.md): keymap components and keymap text syntax documentation. - [Library quick Guide](doc/quick-guide.md): introduction on how to use this library. - [Tools](./README.md#tools): introduction to the `xkbcli` application. - [Release notes](doc/release-notes.md). - [Frequently Asked Question (FAQ)](doc/faq.md). ## Building libxkbcommon is built with [Meson](http://mesonbuild.com): ```bash meson setup build meson compile -C build meson test -C build # Run the tests. ``` To build for use with Wayland, you can disable X11 support while still using the X11 keyboard configuration resource files thusly: ```bash meson setup build \ -Denable-x11=false \ -Dxkb-config-root=/usr/share/X11/xkb \ -Dx-locale-root=/usr/share/X11/locale meson compile -C build ```
Complete list of user options @include meson_options.txt
## API While libxkbcommon’s API is somewhat derived from the classic XKB API as found in `X11/extensions/XKB.h` and friends, it has been substantially reworked to expose fewer internal details to clients. See the [API Documentation](https://xkbcommon.org/doc/current/topics.html). ## Tools Libxkbcommon has a fair set of CLI tools, grouped under the xkbcli application:
xkbcli compile-keymap
Compile an XKB keymap
xkbcli compile-compose
Compile a compose file
xkbcli how-to-type
Show how to type a given Unicode codepoint
xkbcli interactive-wayland
Interactive debugger for XKB keymaps for Wayland
xkbcli interactive-x11
Interactive debugger for XKB keymaps for X11
xkbcli interactive-evdev
Interactive debugger for XKB keymaps for evdev
xkbcli dump-keymap-wayland
Dump a XKB keymap from a Wayland compositor
xkbcli dump-keymap-x11
Dump a XKB keymap from a X server
xkbcli list
List available layouts and more
It may require the installation of the package `libxkbcommon-tools` or similar name. ## Dataset libxkbcommon *does not distribute a keyboard layout dataset itself*, other than for testing purposes. The most common dataset is **xkeyboard-config**, which is used by all current distributions for their X11 XKB data. Further information on xkeyboard-config is available at its [homepage][xkeyboard-config-home] and at its [repository][xkeyboard-config-repo]. The dataset for *Compose* is distributed in [libX11], as part of the X locale data. [xkeyboard-config-home]: https://www.freedesktop.org/wiki/Software/XKeyboardConfig [xkeyboard-config-repo]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config [libX11]: https://gitlab.freedesktop.org/xorg/lib/libx11 ## Relation to X11 See [Compatibility](doc/compatibility.md) notes. ## Development An project’s homepage can be found at https://xkbcommon.org. xkbcommon is maintained in git at: https://github.com/xkbcommon/libxkbcommon Patches are always welcome, and may be sent to either or or in a [GitHub](https://github.com/xkbcommon/libxkbcommon) pull request. Bug reports (and usage questions) are also welcome, and may be filed at [GitHub](https://github.com/xkbcommon/libxkbcommon/issues). The maintainers are: - [Daniel Stone](mailto:daniel@fooishbar.org) - [Ran Benita](mailto:ran@unusedvar.com) - [Pierre Le Marre](mailto:dev@wismill.eu) ## License See the [LICENSE](doc/license.md) file. ## Credits Many thanks are due to Dan Nicholson for his heroic work in getting xkbcommon off the ground initially. xkbcommon-libxkbcommon-54ee7ac/RELEASING.md000066400000000000000000000055661510033435100205320ustar00rootroot00000000000000# How to make a libxkbcommon release ### Prerequisites - Have write access to xkbcommon Git repositories. - Be subscribed to the [wayland-devel](https://lists.freedesktop.org/postorius/lists/wayland-devel.lists.freedesktop.org/) mailing list. ### Steps #### Prepare the release - [ ] Ensure there is no issue in the tracker blocking the release. Make sure they have their milestone set to the relevant release and the relevant tag “critical”. - [ ] Ensure all items in the current milestone are processed. Remaining items must be *explicitly* postponed by changing their milestone. - [ ] Ensure the keysyms header is up-to-date (see [xorgproto]) - [ ] Create a release branch: `git checkout -b release/vMAJOR.MINOR.PATCH master` - [ ] Update the `NEWS.md` file for the release, following [the corresponding instructions](changes/README.md). - [ ] Bump the `version` in `meson.build`. - [ ] Run `meson dist -C build` to make sure the release is good to go. - [ ] Commit `git commit -m 'Bump version to MAJOR.MINOR.PATCH'`. - [ ] Create a pull request using this template and ensure *all* CI is green. - [ ] Merge the pull request. - [ ] Tag `git switch master && git pull && git tag --annotate -m xkbcommon- xkbcommon-`. - [ ] Push the tag `git push origin xkbcommon-`. [xorgproto]: https://gitlab.freedesktop.org/xorg/proto/xorgproto/-/tree/master/include/X11 #### Send announcement email to wayland-devel - [ ] Send an email to the wayland-devel@lists.freedesktop.org mailing list, using this template: ``` Subject: [ANNOUNCE] libxkbcommon MAJOR.MINOR.PATCH Git tag: -------- git tag: xkbcommon- git commit: ``` #### Update website - [ ] Pull the latest [website repository](https://github.com/xkbcommon/website). - [ ] Add the doc for the release: `cp -r /build/html doc/`. Check carefully that there is no warning during generation with Doxygen. It may be necessary to use another version of Doxygen to get a clean build. Building from source using the main branch is also a good option. - [ ] Apply manual Doxygen fixes: - [ ] Fix labels of the TOC in the “Release notes” page. - [ ] Update the `current` symlink: `ln -nsrf doc/ doc/current`. - [ ] Grab a link to the announcement mail from the [wayland-devel archives](https://lore.freedesktop.org/wayland-devel/). - [ ] Update the `index.html`: - "Our latest API- and ABI-stable release ..." - Add entry to the `releases` HTML list. - [ ] Commit `git commit -m MAJOR.MINOR.PATCH`. - [ ] Push `git push`. This automatically publishes the website after a few seconds. xkbcommon-libxkbcommon-54ee7ac/bench/000077500000000000000000000000001510033435100177425ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/bench/atom.c000066400000000000000000000031611510033435100210470ustar00rootroot00000000000000/* * Copyright © 2021 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include "atom.h" #include "bench.h" #include "darray.h" #define BENCHMARK_ITERATIONS 100 int main(void) { FILE *file; char wordbuf[1024]; darray(char *) words; char **worditer; struct atom_table *table; xkb_atom_t atom; const char *text; struct bench bench; char *elapsed; darray_init(words); file = fopen("/usr/share/dict/words", "rb"); if (file == NULL) { perror("/usr/share/dict/words"); return -1; } while (fgets(wordbuf, sizeof(wordbuf), file)) { size_t len = strlen(wordbuf); if (len > 0 && wordbuf[len - 1] == '\n') wordbuf[len - 1] = '\0'; darray_append(words, strdup(wordbuf)); } fclose(file); bench_start(&bench); for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { table = atom_table_new(); assert(table); darray_foreach(worditer, words) { atom = atom_intern(table, *worditer, strlen(*worditer) - 1, true); assert(atom != XKB_ATOM_NONE); text = atom_text(table, atom); assert(text != NULL); } atom_table_free(table); } bench_stop(&bench); elapsed = bench_elapsed_str(&bench); fprintf(stderr, "%d iterations in %ss\n", BENCHMARK_ITERATIONS, elapsed); free(elapsed); darray_foreach(worditer, words) { free(*worditer); } darray_free(words); return 0; } xkbcommon-libxkbcommon-54ee7ac/bench/bench.c000066400000000000000000000073671510033435100212020ustar00rootroot00000000000000/* * Copyright © 2015 Kazunobu Kuriyama * Copyright © 2015 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "bench.h" #include "../src/utils.h" #ifndef _WIN32 #include #include #else #include #include struct timeval { long tv_sec, tv_usec; }; static int gettimeofday(struct timeval *tv, void *unused) { static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); SYSTEMTIME system_time; FILETIME file_time; uint64_t t; GetSystemTime(&system_time); SystemTimeToFileTime(&system_time, &file_time); t = (uint64_t) file_time.dwLowDateTime; t += ((uint64_t) file_time.dwHighDateTime) << 32; tv->tv_sec = (long) ((t - EPOCH) / 10000000L); tv->tv_usec = (long) (system_time.wMilliseconds * 1000); return 0; } #endif void bench_start(struct bench *bench) { struct timeval val; (void) gettimeofday(&val, NULL); bench->start = (struct bench_time) { .seconds = val.tv_sec, .nanoseconds = val.tv_usec * 1000, }; } void bench_stop(struct bench *bench) { struct timeval val; (void) gettimeofday(&val, NULL); bench->stop = (struct bench_time) { .seconds = val.tv_sec, .nanoseconds = val.tv_usec * 1000, }; } #ifndef _WIN32 void bench_start2(struct bench *bench) { struct timespec t; (void) clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); // (void) clock_gettime(CLOCK_MONOTONIC, &t); bench->start = (struct bench_time) { .seconds = t.tv_sec, .nanoseconds = t.tv_nsec, }; } void bench_stop2(struct bench *bench) { struct timespec t; (void) clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t); // (void) clock_gettime(CLOCK_MONOTONIC, &t); bench->stop = (struct bench_time) { .seconds = t.tv_sec, .nanoseconds = t.tv_nsec, }; } #endif void bench_elapsed(const struct bench *bench, struct bench_time *result) { result->seconds = bench->stop.seconds - bench->start.seconds; result->nanoseconds = bench->stop.nanoseconds - bench->start.nanoseconds; if (result->nanoseconds < 0) { result->nanoseconds += 1000000000; result->seconds--; } } char * bench_elapsed_str(const struct bench *bench) { struct bench_time elapsed; char *buf; int ret; bench_elapsed(bench, &elapsed); ret = asprintf(&buf, "%ld.%06ld", elapsed.seconds, elapsed.nanoseconds / 1000); assert(ret >= 0); return buf; } /* Utils for bench method adapted from: https://hackage.haskell.org/package/tasty-bench */ #define fit(x1, x2) ((x1) / 5 + 2 * ((x2) / 5)) #define sqr(x) ((x) * (x)) static void predict(long long t1, long long t2, struct estimate *est) { const long long t = fit(t1, t2); est->elapsed = t; est->stdev = llroundl(sqrtl((long double)sqr(t1 - t) + (long double)sqr(t2 - 2 * t))); } #define high(t, prec) ((t) + (prec)) #define low(t, prec) ((t) - (prec)) #define MIN_PRECISION 1000000 /* 1ms */ void predictPerturbed(const struct bench_time *b1, const struct bench_time *b2, struct estimate *est) { const long long t1 = bench_time_elapsed_nanoseconds(b1); const long long t2 = bench_time_elapsed_nanoseconds(b2); #ifndef _WIN32 struct timespec ts; (void) clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts); long long precision = MAX(ts.tv_sec * 1000000000 + ts.tv_nsec, MIN_PRECISION); #else long long precision = MIN_PRECISION; #endif struct estimate est1; struct estimate est2; predict(t1, t2, est); predict(low(t1, precision), high(t2, precision), &est1); predict(high(t1, precision), low(t2, precision), &est2); est->stdev = MAX(est1.stdev, est2.stdev); } xkbcommon-libxkbcommon-54ee7ac/bench/bench.h000066400000000000000000000070641510033435100212010ustar00rootroot00000000000000/* * Copyright © 2015 Kazunobu Kuriyama * Copyright © 2015 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once struct bench_time { long seconds; long nanoseconds; }; struct bench { struct bench_time start; struct bench_time stop; }; struct estimate { long long int elapsed; long long int stdev; }; void bench_start(struct bench *bench); void bench_stop(struct bench *bench); #ifndef _WIN32 void bench_start2(struct bench *bench); void bench_stop2(struct bench *bench); #else /* TODO: implement clock_getres for Windows */ #define bench_start2 bench_start #define bench_stop2 bench_stop #endif void bench_elapsed(const struct bench *bench, struct bench_time *result); #define bench_time_elapsed_microseconds(elapsed) \ ((elapsed)->nanoseconds / 1000 + 1000000 * (elapsed)->seconds) #define bench_time_elapsed_nanoseconds(elapsed) \ ((elapsed)->nanoseconds + 1000000000 * (elapsed)->seconds) /* The caller is responsibile to free() the returned string. */ char * bench_elapsed_str(const struct bench *bench); /* Bench method adapted from: https://hackage.haskell.org/package/tasty-bench */ #define BENCH(target_stdev, n, time, est, ...) do { \ struct bench _bench; \ struct bench_time _t1; \ struct bench_time _t2; \ n = 1; \ bench_start2(&_bench); \ do { __VA_ARGS__ } while (0); \ bench_stop2(&_bench); \ bench_elapsed(&_bench, &_t1); \ do { \ bench_start2(&_bench); \ for (unsigned int k = 0; k < 2 * n; k++) { \ __VA_ARGS__ \ } \ bench_stop2(&_bench); \ bench_elapsed(&_bench, &_t2); \ predictPerturbed(&_t1, &_t2, &est); \ if (est.stdev < (long long)(MAX(0, target_stdev * (double)est.elapsed))) {\ scale_estimate(est, n); \ time = _t2; \ n *= 2; \ break; \ } \ n *= 2; \ _t1 = _t2; \ } while (1); \ } while (0) void predictPerturbed(const struct bench_time *t1, const struct bench_time *t2, struct estimate *est); #define scale_estimate(est, n) do { \ (est).elapsed /= (n); \ (est).stdev /= (n); \ } while (0); xkbcommon-libxkbcommon-54ee7ac/bench/compile-keymap.c000066400000000000000000000317631510033435100230340ustar00rootroot00000000000000/* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "utils.h" #include "keymap-formats.h" #include "bench.h" #define DEFAULT_ITERATIONS 3000 #define DEFAULT_STDEV 0.05 static void usage(FILE *fp, char **argv) { fprintf(fp, "Usage: %s [OPTIONS]\n" "\n" "Benchmark compilation of the given RMLVO\n" "\n" "Options:\n" " --help\n" " Print this help and exit\n" " --iter\n" " Exact number of iterations to run\n" " --stdev\n" " Minimal relative standard deviation (percentage) to reach.\n" " (default: %f)\n" "Note: --iter and --stdev are mutually exclusive.\n" "\n" "XKB-specific options:\n" " --input-format \n" " The keymap format to use for parsing (default: %d)\n" #ifdef KEYMAP_DUMP " --output-format \n" " The keymap format to use for serializing (default: %d)\n" #endif " --pretty\n" " Enable pretty-printing in keymap serialization\n" " --keep-unused\n" " Keep unused bits in keymap serialization\n" " --keymap\n" " Load the corresponding XKB file, ignore RMLVO options.\n" " --rules \n" " The XKB ruleset (default: '%s')\n" " --model \n" " The XKB model (default: '%s')\n" " --layout \n" " The XKB layout (default: '%s')\n" " --variant \n" " The XKB layout variant (default: '%s')\n" " --options \n" " The XKB options (default: '%s')\n" "\n", argv[0], DEFAULT_STDEV * 100, DEFAULT_INPUT_KEYMAP_FORMAT, #ifdef KEYMAP_DUMP DEFAULT_OUTPUT_KEYMAP_FORMAT, #endif DEFAULT_XKB_RULES, DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT, DEFAULT_XKB_VARIANT ? DEFAULT_XKB_VARIANT : "", DEFAULT_XKB_OPTIONS ? DEFAULT_XKB_OPTIONS : ""); } static struct xkb_keymap * load_keymap(struct xkb_context *ctx, const char *keymap_path, const struct xkb_rule_names * rmlvo, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { if (keymap_path) { FILE *file = fopen(keymap_path, "r"); if (!file) { fprintf(stderr, "ERROR: cannot open file: %s\n", keymap_path); return NULL; } struct xkb_keymap *keymap = xkb_keymap_new_from_file( ctx, file, format, XKB_KEYMAP_COMPILE_NO_FLAGS ); fclose(file); return keymap; } else { return xkb_keymap_new_from_names2(ctx, rmlvo, format, XKB_KEYMAP_COMPILE_NO_FLAGS); } } int main(int argc, char **argv) { struct xkb_context *context; struct bench bench; struct bench_time elapsed; struct estimate est; enum xkb_keymap_format keymap_input_format = DEFAULT_INPUT_KEYMAP_FORMAT; #ifdef KEYMAP_DUMP enum xkb_keymap_format keymap_output_format = DEFAULT_OUTPUT_KEYMAP_FORMAT; #endif enum xkb_keymap_serialize_flags serialize_flags = XKB_KEYMAP_SERIALIZE_NO_FLAGS; bool explicit_iterations = false; int ret = 0; char *keymap_path = NULL; struct xkb_rule_names rmlvo = { .rules = DEFAULT_XKB_RULES, .model = DEFAULT_XKB_MODEL, /* layout and variant are tied together, so we either get user-supplied for * both or default for both, see below */ .layout = NULL, .variant = NULL, .options = DEFAULT_XKB_OPTIONS, }; unsigned int max_iterations = DEFAULT_ITERATIONS; double stdev = DEFAULT_STDEV; enum options { OPT_KEYMAP_INPUT_FORMAT, OPT_KEYMAP_OUTPUT_FORMAT, OPT_KEYMAP_PRETTY, OPT_KEYMAP_KEEP_UNUSED, OPT_KEYMAP, OPT_RULES, OPT_MODEL, OPT_LAYOUT, OPT_VARIANT, OPT_OPTION, OPT_ITERATIONS, OPT_STDEV, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"input-format", required_argument, 0, OPT_KEYMAP_INPUT_FORMAT}, #ifdef KEYMAP_DUMP {"output-format", required_argument, 0, OPT_KEYMAP_OUTPUT_FORMAT}, #endif {"pretty", no_argument, 0, OPT_KEYMAP_PRETTY}, {"keep-unused", no_argument, 0, OPT_KEYMAP_KEEP_UNUSED}, {"keymap", required_argument, 0, OPT_KEYMAP}, {"rules", required_argument, 0, OPT_RULES}, {"model", required_argument, 0, OPT_MODEL}, {"layout", required_argument, 0, OPT_LAYOUT}, {"variant", required_argument, 0, OPT_VARIANT}, {"options", required_argument, 0, OPT_OPTION}, {"iter", required_argument, 0, OPT_ITERATIONS}, {"stdev", required_argument, 0, OPT_STDEV}, {0, 0, 0, 0}, }; while (1) { int c; int option_index = 0; c = getopt_long(argc, argv, "h", opts, &option_index); if (c == -1) break; switch (c) { case 'h': usage(stdout, argv); exit(EXIT_SUCCESS); case OPT_KEYMAP_INPUT_FORMAT: keymap_input_format = xkb_keymap_parse_format(optarg); if (!keymap_input_format) { fprintf(stderr, "ERROR: invalid --input-format: \"%s\"\n", optarg); usage(stderr, argv); exit(EXIT_INVALID_USAGE); } break; #ifdef KEYMAP_DUMP case OPT_KEYMAP_OUTPUT_FORMAT: keymap_output_format = xkb_keymap_parse_format(optarg); if (!keymap_output_format) { fprintf(stderr, "ERROR: invalid --output-format: \"%s\"\n", optarg); usage(stderr, argv); exit(EXIT_INVALID_USAGE); } break; #endif case OPT_KEYMAP_PRETTY: serialize_flags |= XKB_KEYMAP_SERIALIZE_PRETTY; break; case OPT_KEYMAP_KEEP_UNUSED: serialize_flags |= XKB_KEYMAP_SERIALIZE_KEEP_UNUSED; break; case OPT_KEYMAP: keymap_path = optarg; break; case OPT_RULES: rmlvo.rules = optarg; break; case OPT_MODEL: rmlvo.model = optarg; break; case OPT_LAYOUT: rmlvo.layout = optarg; break; case OPT_VARIANT: rmlvo.variant = optarg; break; case OPT_OPTION: rmlvo.options = optarg; break; case OPT_ITERATIONS: if (max_iterations == 0) { usage(stderr, argv); exit(EXIT_INVALID_USAGE); } { const int max_iterations_raw = atoi(optarg); if (max_iterations_raw <= 0) max_iterations = DEFAULT_ITERATIONS; else max_iterations = (unsigned int) max_iterations_raw; } explicit_iterations = true; break; case OPT_STDEV: if (explicit_iterations) { usage(stderr, argv); exit(EXIT_INVALID_USAGE); } stdev = atof(optarg) / 100; if (stdev <= 0) stdev = DEFAULT_STDEV; max_iterations = 0; break; default: usage(stderr, argv); exit(EXIT_INVALID_USAGE); } } /* Now fill in the layout */ if (!rmlvo.layout || !*rmlvo.layout) { if (rmlvo.variant && *rmlvo.variant) { fprintf(stderr, "Error: a variant requires a layout\n"); return EXIT_INVALID_USAGE; } rmlvo.layout = DEFAULT_XKB_LAYOUT; rmlvo.variant = DEFAULT_XKB_VARIANT; } context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) exit(1); struct xkb_keymap *keymap = load_keymap(context, keymap_path, &rmlvo, keymap_input_format, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { fprintf(stderr, "ERROR: Cannot compile keymap.\n"); ret = EXIT_FAILURE; goto keymap_error; } #ifndef KEYMAP_DUMP /* Cache the keymap input to mitigate I/O latency */ char *keymap_str = NULL; size_t keymap_str_length = 0; FILE *keymap_file = NULL; if (keymap_path) { /* Load keymap file into memory */ keymap_file = fopen(keymap_path, "r"); if (!keymap_file) { fprintf(stderr, "ERROR: cannot open file: %s\n", keymap_path); ret = EXIT_FAILURE; goto keymap_error; } if (!map_file(keymap_file, &keymap_str, &keymap_str_length)) { fclose(keymap_file); ret = EXIT_FAILURE; goto keymap_error; } } else { /* * Serialize from RMLVO * * This has the caveat that the benchmarked input is different from the * original KcCGST files. */ keymap_str = xkb_keymap_get_as_string2( keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT, serialize_flags ); if (!keymap_str) { fprintf(stderr, "ERROR: cannot serialize keymap\n"); ret = EXIT_FAILURE; goto keymap_error; } keymap_str_length = strlen(keymap_str); } xkb_keymap_unref(keymap); #endif /* Suspend stdout and stderr outputs */ fflush(stdout); int stdout_old = dup(STDOUT_FILENO); int stdout_new = open("/dev/null", O_WRONLY); if (stdout_old == -1 || stdout_new == -1 || dup2(stdout_new, STDOUT_FILENO) == -1) { perror("Stdout error"); exit(EXIT_FAILURE); } close(stdout_new); fflush(stderr); int stderr_old = dup(STDERR_FILENO); int stderr_new = open("/dev/null", O_WRONLY); if (stderr_old == -1 || stderr_new == -1 || dup2(stderr_new, STDERR_FILENO) == -1) { perror("Stderr error"); exit(EXIT_FAILURE); } close(stderr_new); if (explicit_iterations) { stdev = 0; bench_start2(&bench); for (unsigned int i = 0; i < max_iterations; i++) { #ifdef KEYMAP_DUMP char *s = xkb_keymap_get_as_string2(keymap, keymap_output_format, serialize_flags); assert(s); free(s); #else keymap = xkb_keymap_new_from_buffer( context, keymap_str, keymap_str_length, keymap_input_format, XKB_KEYMAP_COMPILE_NO_FLAGS ); assert(keymap); xkb_keymap_unref(keymap); #endif } bench_stop2(&bench); bench_elapsed(&bench, &elapsed); est.elapsed = (bench_time_elapsed_nanoseconds(&elapsed)) / max_iterations; est.stdev = 0; } else { bench_start2(&bench); #ifdef KEYMAP_DUMP BENCH(stdev, max_iterations, elapsed, est, char *s = xkb_keymap_get_as_string2(keymap, keymap_output_format, serialize_flags); assert(s); free(s); ); #else BENCH(stdev, max_iterations, elapsed, est, keymap = xkb_keymap_new_from_buffer( context, keymap_str, keymap_str_length, keymap_input_format, XKB_KEYMAP_COMPILE_NO_FLAGS ); assert(keymap); xkb_keymap_unref(keymap); ); #endif bench_stop2(&bench); } /* Restore stdout and stderr outputs */ fflush(stdout); dup2(stdout_old, STDOUT_FILENO); close(stdout_old); fflush(stderr); dup2(stderr_old, STDERR_FILENO); close(stderr_old); #ifdef KEYMAP_DUMP xkb_keymap_unref(keymap); #else if (keymap_str && keymap_file) { unmap_file(keymap_str, keymap_str_length); fclose(keymap_file); } else { free(keymap_str); } #endif struct bench_time total_elapsed; bench_elapsed(&bench, &total_elapsed); if (explicit_iterations) { fprintf(stderr, "mean: %lld µs; compiled %u keymaps in %ld.%06lds\n", est.elapsed / 1000, max_iterations, total_elapsed.seconds, total_elapsed.nanoseconds / 1000); } else { fprintf(stderr, "mean: %lld µs; stdev: %Lf%% (target: %f%%); " "last run: compiled %u keymaps in %ld.%06lds; " "total time: %ld.%06lds\n", est.elapsed / 1000, (long double) est.stdev * 100.0 / (long double) est.elapsed, stdev * 100, max_iterations, elapsed.seconds, elapsed.nanoseconds / 1000, total_elapsed.seconds, total_elapsed.nanoseconds / 1000); } keymap_error: xkb_context_unref(context); return ret; } xkbcommon-libxkbcommon-54ee7ac/bench/compose-traversal.c000066400000000000000000000043261510033435100235610ustar00rootroot00000000000000/* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "xkbcommon/xkbcommon-compose.h" #include "../test/compose-iter.h" #include "../test/test.h" #include "bench.h" #define BENCHMARK_ITERATIONS 1000 static void compose_fn(struct xkb_compose_table_entry *entry, void *data) { assert (entry); } /* Benchmark compose traversal using: * • the internal recursive function `xkb_compose_table_for_each` if `foreach` is * is passed as argument to the program; * • else the iterator API (`xkb_compose_table_iterator_new`, …). */ int main(int argc, char *argv[]) { struct xkb_context *ctx; char *path; FILE *file; struct xkb_compose_table *table; struct bench bench; char *elapsed; bool use_foreach_impl = (argc > 1 && strcmp(argv[1], "foreach") == 0); ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); path = test_get_path("locale/en_US.UTF-8/Compose"); file = fopen(path, "rb"); if (file == NULL) { perror(path); free(path); xkb_context_unref(ctx); return -1; } free(path); xkb_enable_quiet_logging(ctx); table = xkb_compose_table_new_from_file(ctx, file, "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); fclose(file); assert(table); bench_start(&bench); for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { if (use_foreach_impl) { xkb_compose_table_for_each(table, compose_fn, NULL); } else { struct xkb_compose_table_iterator *iter; struct xkb_compose_table_entry *entry; iter = xkb_compose_table_iterator_new(table); while ((entry = xkb_compose_table_iterator_next(iter))) { assert (entry); } xkb_compose_table_iterator_free(iter); } } bench_stop(&bench); xkb_compose_table_unref(table); elapsed = bench_elapsed_str(&bench); fprintf(stderr, "traversed %d compose tables in %ss\n", BENCHMARK_ITERATIONS, elapsed); free(elapsed); xkb_context_unref(ctx); return 0; } xkbcommon-libxkbcommon-54ee7ac/bench/compose.c000066400000000000000000000025551510033435100215620ustar00rootroot00000000000000/* * Copyright © 2014 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "xkbcommon/xkbcommon-compose.h" #include "../test/test.h" #include "bench.h" #define BENCHMARK_ITERATIONS 1000 int main(void) { struct xkb_context *ctx; char *path; FILE *file; struct xkb_compose_table *table; struct bench bench; char *elapsed; ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); path = test_get_path("locale/en_US.UTF-8/Compose"); file = fopen(path, "rb"); if (file == NULL) { perror(path); free(path); xkb_context_unref(ctx); return -1; } xkb_enable_quiet_logging(ctx); bench_start(&bench); for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { fseek(file, 0, SEEK_SET); table = xkb_compose_table_new_from_file(ctx, file, "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); xkb_compose_table_unref(table); } bench_stop(&bench); fclose(file); free(path); elapsed = bench_elapsed_str(&bench); fprintf(stderr, "compiled %d compose tables in %ss\n", BENCHMARK_ITERATIONS, elapsed); free(elapsed); xkb_context_unref(ctx); return 0; } xkbcommon-libxkbcommon-54ee7ac/bench/custom-parsers.c000066400000000000000000000221231510033435100230750ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include "utils.h" #include "utils-numbers.h" #include "bench.h" const double DEFAULT_STDEV = 0.05; static void usage(char **argv) { printf("Usage: %s [OPTIONS]\n" "\n" "Benchmark compilation of the given RMLVO\n" "\n" "Options:\n" " --help\n" " Print this help and exit\n" " --stdev\n" " Minimal relative standard deviation (percentage) to reach.\n" " (default: %f)\n" "\n", argv[0], DEFAULT_STDEV * 100); } static void print_stats(double stdev, unsigned int max_iterations, struct bench_time *elapsed, struct bench *bench, struct estimate *est) { struct bench_time total_elapsed; bench_elapsed(bench, &total_elapsed); fprintf(stderr, "mean: %lld µs; stdev: %Lf%% (target: %f%%); " "last run: parsed %u times in %ld.%06lds; " "total time: %ld.%06lds\n", est->elapsed / 1000, (long double) est->stdev * 100.0 / (long double) est->elapsed, stdev * 100, max_iterations, elapsed->seconds, elapsed->nanoseconds / 1000, total_elapsed.seconds, total_elapsed.nanoseconds / 1000); } /* NOTE: Old parser, for comparison */ static bool parse_keysym_hex(const char *s, uint32_t *out) { uint32_t result = 0; unsigned int i; for (i = 0; i < 8 && s[i] != '\0'; i++) { result <<= 4; if ('0' <= s[i] && s[i] <= '9') result += s[i] - '0'; else if ('a' <= s[i] && s[i] <= 'f') result += 10 + s[i] - 'a'; else if ('A' <= s[i] && s[i] <= 'F') result += 10 + s[i] - 'A'; else return false; } *out = result; return s[i] == '\0' && i > 0; } int main(int argc, char **argv) { struct bench bench; struct bench_time elapsed; struct estimate est; int ret = 0; double stdev = DEFAULT_STDEV; enum options { OPT_STDEV, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"stdev", required_argument, 0, OPT_STDEV}, {0, 0, 0, 0}, }; while (1) { int c; int option_index = 0; c = getopt_long(argc, argv, "h", opts, &option_index); if (c == -1) break; switch (c) { case 'h': usage(argv); exit(EXIT_SUCCESS); case OPT_STDEV: stdev = atof(optarg) / 100; if (stdev <= 0) stdev = DEFAULT_STDEV; break; default: usage(argv); exit(EXIT_INVALID_USAGE); } } FILE *file = fopen(__FILE__, "r"); assert(file); size_t size = 0; char *content = NULL; map_file(file, &content, &size); assert(content); /* * Some numbers for the parsers, do not delete. * * 0x0000000000000000 0x0000000000000002 0x0000000000000003 * 0x0000000000000001 0x00000000000000FE 0x00000000000001FE * 0x000000000000000A 0x0000000000000200 0x0000000000000400 * 0x00000000000000FF 0x0000000000020000 0x0000000000040000 * 0x0000000000000100 0x0000000002000000 0x0000000004000000 * 0x0000000000001000 0x0000000200000000 0x0000000400000000 * 0x0000000000010000 0x0000020000000000 0x0000040000000000 * 0x0000000001000000 0x0002000000000000 0x0004000000000000 * 0x0000000100000000 0x0200000000000000 0x0400000000000000 * 0x0000010000000000 0x2000000000000000 0x4000000000000001 * 0x0001000000000000 0x4000000000000000 0x3FFFFFFFFFFFFFFF * 0x0100000000000000 0x6FFFFFFFFFFFFFFF 0xA000000000000000 * 0x1000000000000000 0x9000000000000000 0xCFFFFFFFFFFFFFFF * 0x7FFFFFFFFFFFFFFF 0xEFFFFFFFFFFFFFFF 0xD000000000000000 * 0x8000000000000000 0xF000000000000000 0xE000000000000000 * 0xFFFFFFFFFFFFFFFF 0x1A2B3C4D5E6F7089 0x0807060504030201 * 0x123456789ABCDEF0 0x89706F5E4D3C2B1A 0xF1E2D3C4B5A69788 * 0xFEDCBA9876543210 0x5A5A5A5A5A5A5A5A 0x6B6B6B6B6B6B6B6B * 0xABABABABABABABAB 0xA5A5A5A5A5A5A5A5 0xB6B6B6B6B6B6B6B6 * 0xCDCDCDCDCDCDCDCD 0xC3D2E1F00F1E2D3C 0x1122334455667788 * 0x0123456789ABCDEF 0x3C2D1E0F0FE1D2C3 0x8877665544332211 * 0x9876543210FEDCBA 0x0000000080000000 0x0000000040000000 * 0x00000000FFFFFFFF 0x8000000000000000 0x4000000000000000 * 0xFFFFFFFF00000000 0x6666666666666666 0x7777777777777777 * 0x5555555555555555 0x9999999999999999 0x8888888888888888 * 0x0AAAAAAAAAAAAAAA 0x0000000200000002 0x0000000300000003 * 0x0000000100000001 0x4444444444444444 0x5F5F5F5F5F5F5F5F * 0x1111111111111111 0xBBBBBBBBBBBBBBBB 0xC0C0C0C0C0C0C0C0 * 0x2222222222222222 0xCCCCCCCCCCCCCCCC 0xE1E1E1E1E1E1E1E1 * 0x3333333333333333 0xDDDDDDDDDDDDDDDD 0xF2F2F2F2F2F2F2F2 * 0x1A3F5C7E9D2B4A68 0x8E6D4C2B1A0F9E7D 0x3F9A8B7C6D5E4F2A * 0x7B6C5D4E3F2A1B09 0x2D4E6F8A9C0B1D3E 0x5A4B3C2D1E0F9A8B * 0x9E8D7C6B5A4F3E2D 0x1C3E5F7A9D0B2E4F 0x6D5E4F3A2B1C0D9E * 0xA0B1C2D3E4F56789 0x3B4D5F6E7A8C9D0E 0x7E8F9A0B1C2D3E4F * 0x2C3D4E5F6A7B8C9D 0x9A8B7C6D5E4F3A2B 0x1E2D3C4B5A6F7E8D * 0x4D5E6F7A8B9C0D1E 0x3A2B1C0D9E8F7A6B 0x8C9D0E1F2A3B4C5D * 0x5F6E7D8C9B0A1F2E 0x0A1B2C3D4E5F6A7B 0x9C0D1E2F3A4B5C6D * 0x6A7B8C9D0E1F2A3B 0x2E3F4A5B6C7D8E9F 0x1D2C3B4A5F6E7D8C * 0x7D8E9F0A1B2C3D4E 0x4B5C6D7E8F9A0B1C 0x0F1E2D3C4B5A6F7E * 0x8B9C0D1E2F3A4B5C 0x5A6B7C8D9E0F1A2B 0x3C4D5E6F7A8B9C0D * 0x9D0E1F2A3B4C5D6E 0x6B7C8D9E0F1A2B3C 0x2A3B4C5D6E7F8A9B * 0x0E1F2A3B4C5D6E7F 0x7C8D9E0F1A2B3C4D 0x4A5B6C7D8E9F0A1B * 0x1F2A3B4C5D6E7F8A 0x8D9E0F1A2B3C4D5E 0x5B6C7D8E9F0A1B2C * 0x2B3C4D5E6F7A8B9C 0x9E0F1A2B3C4D5E6F 0x6C7D8E9F0A1B2C3D * 0x0A1B2C3D4E5F6A7B 0x7E8F9A0B1C2D3E4F 0x3D4E5F6A7B8C9D0E * 0x1B2C3D4E5F6A7B8C 0x8F9A0B1C2D3E4F5A 0x4E5F6A7B8C9D0E1F * 0x3A4B5C6D7E8F9A0B 0x9F0A1B2C3D4E5F6A 0x5C6D7E8F9A0B1C2D * 0x0B1C2D3E4F5A6B7C 0x7F8A9B0C1D2E3F4A 0x2D3E4F5A6B7C8D9E * 0x1C2D3E4F5A6B7C8D 0x9A0B1C2D3E4F5A6B 0x4F5A6B7C8D9E0F1A * 0x6D7E8F9A0B1C2D3E 0x0C1D2E3F4A5B6C7D 0x3B4C5D6E7F8A9B0C * 0x8E9F0A1B2C3D4E5F 0x5D6E7F8A9B0C1D2E 0x1A2B3C4D5E6F7A8B * 0x0D1E2F3A4B5C6D7E 0x7A8B9C0D1E2F3A4B 0x2E3F4A5B6C7D8E9F * 0x9B0C1D2E3F4A5B6C 0x6E7F8A9B0C1D2E3F 0x0F1A2B3C4D5E6F7A */ volatile uint32_t __attribute__((unused)) dummy32 = 0; volatile uint64_t __attribute__((unused)) dummy64 = 0; unsigned int max_iterations; printf("*** parse_hex_to_uint32_t ***\n"); bench_start2(&bench); BENCH(stdev, max_iterations, elapsed, est, for (size_t n = 0; n < size; n++) { uint32_t val = 0; parse_hex_to_uint32_t(content + n, 8, &val); dummy32 += val; } ); bench_stop2(&bench); print_stats(stdev, max_iterations, &elapsed, &bench, &est); printf("*** parse_keysym_hex ***\n"); bench_start2(&bench); BENCH(stdev, max_iterations, elapsed, est, for (size_t n = 0; n < size; n++) { uint32_t val = 0; parse_keysym_hex(content + n, &val); dummy32 += val; } ); bench_stop2(&bench); print_stats(stdev, max_iterations, &elapsed, &bench, &est); printf("*** parse_dec_to_uint64_t ***\n"); bench_start2(&bench); BENCH(stdev, max_iterations, elapsed, est, for (size_t n = 0; n < size; n++) { uint64_t val = 0; parse_dec_to_uint64_t(content + n, size - n, &val); dummy64 += val; } ); bench_stop2(&bench); print_stats(stdev, max_iterations, &elapsed, &bench, &est); printf("*** strtol, base 10 ***\n"); bench_start2(&bench); BENCH(stdev, max_iterations, elapsed, est, for (size_t n = 0; n < size; n++) { dummy64 += strtol(content + n, NULL, 10); } ); bench_stop2(&bench); print_stats(stdev, max_iterations, &elapsed, &bench, &est); printf("*** parse_hex_to_uint64_t ***\n"); bench_start2(&bench); BENCH(stdev, max_iterations, elapsed, est, for (size_t n = 0; n < size; n++) { uint64_t val = 0; parse_hex_to_uint64_t(content + n, size - n, &val); dummy64 += val; } ); bench_stop2(&bench); print_stats(stdev, max_iterations, &elapsed, &bench, &est); printf("*** strtol, base 16 ***\n"); bench_start2(&bench); BENCH(stdev, max_iterations, elapsed, est, for (size_t n = 0; n < size; n++) { dummy64 += strtol(content + n, NULL, 16); } ); bench_stop2(&bench); print_stats(stdev, max_iterations, &elapsed, &bench, &est); unmap_file(content, size); fclose(file); return ret; } xkbcommon-libxkbcommon-54ee7ac/bench/key-proc.c000066400000000000000000000032761510033435100216470ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "../test/test.h" #include "bench.h" #define BENCHMARK_ITERATIONS 20000000 static void bench_key_proc(struct xkb_state *state) { int8_t keys[256] = { 0 }; xkb_keycode_t keycode; xkb_keysym_t keysym; int i; for (i = 0; i < BENCHMARK_ITERATIONS; i++) { keycode = (rand() % (255 - 9)) + 9; if (keys[keycode]) { xkb_state_update_key(state, keycode, XKB_KEY_UP); keys[keycode] = 0; keysym = xkb_state_key_get_one_sym(state, keycode); (void) keysym; } else { xkb_state_update_key(state, keycode, XKB_KEY_DOWN); keys[keycode] = 1; } } } int main(void) { struct xkb_context *ctx; struct xkb_keymap *keymap; struct xkb_state *state; struct bench bench; char *elapsed; ctx = test_get_context(0); assert(ctx); keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "us,ru,il,de", ",,,neo", "grp:menu_toggle"); assert(keymap); state = xkb_state_new(keymap); assert(state); xkb_enable_quiet_logging(ctx); srand((unsigned) time(NULL)); bench_start(&bench); bench_key_proc(state); bench_stop(&bench); elapsed = bench_elapsed_str(&bench); fprintf(stderr, "ran %d iterations in %ss\n", BENCHMARK_ITERATIONS, elapsed); free(elapsed); xkb_state_unref(state); xkb_keymap_unref(keymap); xkb_context_unref(ctx); return 0; } xkbcommon-libxkbcommon-54ee7ac/bench/keysym-case-mappings.c000066400000000000000000000041021510033435100241510ustar00rootroot00000000000000/* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "src/keysym.h" #include "../test/test.h" #include "bench.h" #define BENCHMARK_ITERATIONS 300 typedef uint32_t (*CaseMappingFunc)(xkb_keysym_t ks); typedef bool (*CaseTestFunc)(xkb_keysym_t ks); struct TestedFunction { union { struct { CaseMappingFunc toLower; CaseMappingFunc toUpper; }; struct { CaseTestFunc isLower; CaseTestFunc isUpper; }; }; const char *name; }; static const struct TestedFunction functions[] = { { {.toLower = xkb_keysym_to_lower, .toUpper = xkb_keysym_to_upper}, "to_lower & to_upper" }, { {.isLower = xkb_keysym_is_lower, .isUpper = xkb_keysym_is_upper_or_title}, "is_lower & is_upper" }, }; int main(void) { struct bench bench; for (size_t f = 0; f < ARRAY_SIZE(functions); f++) { for (int explicit = 1; explicit >= 0; explicit--) { fprintf(stderr, "Benchmarking %s...\n", functions[f].name); bench_start(&bench); for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { struct xkb_keysym_iterator *iter = xkb_keysym_iterator_new(explicit); while (xkb_keysym_iterator_next(iter)) { xkb_keysym_t ks = xkb_keysym_iterator_get_keysym(iter); functions[f].toLower(ks); functions[f].toUpper(ks); } /* Avoid dangling pointers * NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores) */ iter = xkb_keysym_iterator_unref(iter); } bench_stop(&bench); char *elapsed = bench_elapsed_str(&bench); fprintf(stderr, "Applied %d times \"%s\" to %s assigned keysyms in %ss\n", BENCHMARK_ITERATIONS, functions[f].name, explicit ? "explicitly" : "all", elapsed); free(elapsed); } } return 0; } xkbcommon-libxkbcommon-54ee7ac/bench/rules.c000066400000000000000000000155171510033435100212510ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "../test/test.h" #include "xkbcomp/rules.h" #include "bench.h" const unsigned int DEFAULT_ITERATIONS = 20000; const double DEFAULT_STDEV = 0.05; static void usage(char **argv) { printf("Usage: %s [OPTIONS]\n" "\n" "Benchmark compilation of the given RMLVO\n" "\n" "Options:\n" " --help\n" " Print this help and exit\n" " --iter\n" " Exact number of iterations to run\n" " --stdev\n" " Minimal relative standard deviation (percentage) to reach.\n" " (default: %f)\n" "Note: --iter and --stdev are mutually exclusive.\n" "\n" "XKB-specific options:\n" " --rules \n" " The XKB ruleset (default: '%s')\n" " --model \n" " The XKB model (default: '%s')\n" " --layout \n" " The XKB layout (default: '%s')\n" " --variant \n" " The XKB layout variant (default: '%s')\n" " --options \n" " The XKB options (default: '%s')\n" "\n", argv[0], DEFAULT_STDEV * 100, DEFAULT_XKB_RULES, DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT, DEFAULT_XKB_VARIANT ? DEFAULT_XKB_VARIANT : "", DEFAULT_XKB_OPTIONS ? DEFAULT_XKB_OPTIONS : ""); } int main(int argc, char *argv[]) { struct bench bench; struct bench_time elapsed; struct estimate est; bool explicit_iterations = false; struct xkb_rule_names rmlvo = { .rules = DEFAULT_XKB_RULES, .model = DEFAULT_XKB_MODEL, /* layout and variant are tied together, so we either get user-supplied for * both or default for both, see below */ .layout = NULL, .variant = NULL, .options = DEFAULT_XKB_OPTIONS, }; unsigned int max_iterations = DEFAULT_ITERATIONS; double stdev = DEFAULT_STDEV; enum options { OPT_RULES, OPT_MODEL, OPT_LAYOUT, OPT_VARIANT, OPT_OPTION, OPT_ITERATIONS, OPT_STDEV, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"rules", required_argument, 0, OPT_RULES}, {"model", required_argument, 0, OPT_MODEL}, {"layout", required_argument, 0, OPT_LAYOUT}, {"variant", required_argument, 0, OPT_VARIANT}, {"options", required_argument, 0, OPT_OPTION}, {"iter", required_argument, 0, OPT_ITERATIONS}, {"stdev", required_argument, 0, OPT_STDEV}, {0, 0, 0, 0}, }; while (1) { int c; int option_index = 0; c = getopt_long(argc, argv, "h", opts, &option_index); if (c == -1) break; switch (c) { case 'h': usage(argv); exit(EXIT_SUCCESS); case OPT_RULES: rmlvo.rules = optarg; break; case OPT_MODEL: rmlvo.model = optarg; break; case OPT_LAYOUT: rmlvo.layout = optarg; break; case OPT_VARIANT: rmlvo.variant = optarg; break; case OPT_OPTION: rmlvo.options = optarg; break; case OPT_ITERATIONS: if (max_iterations == 0) { usage(argv); exit(EXIT_INVALID_USAGE); } { const int max_iterations_raw = atoi(optarg); if (max_iterations_raw <= 0) max_iterations = DEFAULT_ITERATIONS; else max_iterations = (unsigned int) max_iterations_raw; } explicit_iterations = true; break; case OPT_STDEV: if (explicit_iterations) { usage(argv); exit(EXIT_INVALID_USAGE); } stdev = atof(optarg) / 100; if (stdev <= 0) stdev = DEFAULT_STDEV; max_iterations = 0; break; default: usage(argv); exit(EXIT_INVALID_USAGE); } } /* Now fill in the layout */ if (!rmlvo.layout || !*rmlvo.layout) { if (rmlvo.variant && *rmlvo.variant) { fprintf(stderr, "Error: a variant requires a layout\n"); return EXIT_INVALID_USAGE; } rmlvo.layout = DEFAULT_XKB_LAYOUT; rmlvo.variant = DEFAULT_XKB_VARIANT; } struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) exit(EXIT_FAILURE); xkb_enable_quiet_logging(context); if (explicit_iterations) { stdev = 0; bench_start2(&bench); for (unsigned int i = 0; i < max_iterations; i++) { struct xkb_component_names kccgst; assert(xkb_components_from_rules_names(context, &rmlvo, &kccgst, NULL)); free(kccgst.keycodes); free(kccgst.types); free(kccgst.compatibility); free(kccgst.symbols); free(kccgst.geometry); } bench_stop2(&bench); bench_elapsed(&bench, &elapsed); est.elapsed = (bench_time_elapsed_nanoseconds(&elapsed)) / max_iterations; est.stdev = 0; } else { bench_start2(&bench); BENCH(stdev, max_iterations, elapsed, est, struct xkb_component_names kccgst; assert(xkb_components_from_rules_names(context, &rmlvo, &kccgst, NULL)); free(kccgst.keycodes); free(kccgst.types); free(kccgst.compatibility); free(kccgst.symbols); free(kccgst.geometry); ); bench_stop2(&bench); } struct bench_time total_elapsed; bench_elapsed(&bench, &total_elapsed); if (explicit_iterations) { fprintf(stderr, "mean: %lld µs; compiled %u rules in %ld.%06lds\n", est.elapsed / 1000, max_iterations, total_elapsed.seconds, total_elapsed.nanoseconds / 1000); } else { fprintf(stderr, "mean: %lld µs; stdev: %Lf%% (target: %f%%); " "last run: compiled %u rules in %ld.%06lds; " "total time: %ld.%06lds\n", est.elapsed / 1000, (long double) est.stdev * 100.0 / (long double) est.elapsed, stdev * 100, max_iterations, elapsed.seconds, elapsed.nanoseconds / 1000, total_elapsed.seconds, total_elapsed.nanoseconds / 1000); } xkb_context_unref(context); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/bench/rulescomp.c000066400000000000000000000017051510033435100221220ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "../test/test.h" #include "bench.h" #include "xkbcommon/xkbcommon.h" #define BENCHMARK_ITERATIONS 1000 int main(int argc, char *argv[]) { struct xkb_context *ctx; struct xkb_keymap *keymap; struct bench bench; char *elapsed; int i; ctx = test_get_context(0); assert(ctx); xkb_enable_quiet_logging(ctx); bench_start(&bench); for (i = 0; i < BENCHMARK_ITERATIONS; i++) { keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "us", "", ""); assert(keymap); xkb_keymap_unref(keymap); } bench_stop(&bench); elapsed = bench_elapsed_str(&bench); fprintf(stderr, "compiled %d keymaps in %ss\n", BENCHMARK_ITERATIONS, elapsed); free(elapsed); xkb_context_unref(ctx); return 0; } xkbcommon-libxkbcommon-54ee7ac/bench/x11.c000066400000000000000000000044411510033435100205220ustar00rootroot00000000000000/* * Copyright © 2020 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-x11.h" #include "bench.h" #define BENCHMARK_ITERATIONS 2500 int main(void) { int ret; xcb_connection_t *conn; int32_t device_id; struct xkb_context *ctx; struct bench bench; char *elapsed; conn = xcb_connect(NULL, NULL); if (!conn || xcb_connection_has_error(conn)) { fprintf(stderr, "Couldn't connect to X server: error code %d\n", conn ? xcb_connection_has_error(conn) : -1); ret = -1; goto err_out; } ret = xkb_x11_setup_xkb_extension(conn, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, NULL, NULL); if (!ret) { fprintf(stderr, "Couldn't setup XKB extension\n"); goto err_conn; } device_id = xkb_x11_get_core_keyboard_device_id(conn); if (device_id == -1) { ret = -1; fprintf(stderr, "Couldn't find core keyboard device\n"); goto err_conn; } ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!ctx) { ret = -1; fprintf(stderr, "Couldn't create xkb context\n"); goto err_conn; } bench_start(&bench); for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { struct xkb_keymap *keymap; struct xkb_state *state; keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); assert(keymap); state = xkb_x11_state_new_from_device(keymap, conn, device_id); assert(state); xkb_state_unref(state); xkb_keymap_unref(keymap); } bench_stop(&bench); ret = 0; elapsed = bench_elapsed_str(&bench); fprintf(stderr, "retrieved %d keymaps from X in %ss\n", BENCHMARK_ITERATIONS, elapsed); free(elapsed); xkb_context_unref(ctx); err_conn: xcb_disconnect(conn); err_out: return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } xkbcommon-libxkbcommon-54ee7ac/changes/000077500000000000000000000000001510033435100202735ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/README.md000066400000000000000000000032771510033435100215630ustar00rootroot00000000000000# Fragments for the changelog This directory contains fragments for the future [NEWS](../NEWS.md) file. ## Introduction We use [towncrier] to produce useful, summarized news files. There are 3 sections types: - API: `changes/api` - Tools: `changes/tools` - Build System: `changes/build` There are 4 news fragments types: - Breaking changes: `.breaking` - Deprecated: `.deprecated` - New: `.feature` - Fixes: `.bugfix` [towncrier]: https://pypi.org/project/towncrier/ ## Adding a fragment Add a short description of the change in a file `changes/SECTION/ID.FRAGMENT.md`, where: - `SECTION` and `FRAGMENT` values are described in the [previous section](#introduction). - `ID` is the corresponding issue identifier on Github, if relevant. If there is no such issue, then `ID` should start with `+` and some identifier that make the file unique in the directory. Examples: - A _bug fix_ for the _issue #463_ is an _API_ change, so the corresponding file should be named `changes/api/463.bugfix.md`. - A _new feature_ for _tools_ like #448 corresponds to e.g. `changes/tools/+add-verbose-opt.feature.md`. Guidelines for the fragment files: - Use the [Markdown] markup. - Use past tense, e.g. “Fixed a segfault”. - Look at the previous releases [NEWS](../NEWS.md) file for further examples. [Markdown]: https://daringfireball.net/projects/markdown/ ## Build the changelog Install [towncrier] from Pypi: ```bash python3 -m pip install towncrier ``` Then build the changelog: ```bash # Only check the result. Useful after adding a new fragment. towncrier build --draft --version 1.8.0 # Write the changelog & delete the news fragments towncrier build --yes --version 1.8.0 ``` xkbcommon-libxkbcommon-54ee7ac/changes/api/000077500000000000000000000000001510033435100210445ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/api/.gitignore000066400000000000000000000000001510033435100230220ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/build/000077500000000000000000000000001510033435100213725ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/build/.gitignore000066400000000000000000000000001510033435100233500ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/keymap-text-format/000077500000000000000000000000001510033435100240315ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/keymap-text-format/.gitignore000066400000000000000000000000001510033435100260070ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/rules-text-format/000077500000000000000000000000001510033435100236755ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/rules-text-format/.gitignore000066400000000000000000000000001510033435100256530ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/tools/000077500000000000000000000000001510033435100214335ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/changes/tools/.gitignore000066400000000000000000000000001510033435100234110ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/data/000077500000000000000000000000001510033435100175745ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/data/keysyms.yaml000066400000000000000000003757131510033435100222040ustar00rootroot000000000000000x0000: name: NoSymbol 0x0020: name: space code point: 0x0020 0x0021: name: exclam code point: 0x0021 0x0022: name: quotedbl code point: 0x0022 0x0023: name: numbersign code point: 0x0023 0x0024: name: dollar code point: 0x0024 0x0025: name: percent code point: 0x0025 0x0026: name: ampersand code point: 0x0026 0x0027: name: apostrophe code point: 0x0027 0x0028: name: parenleft code point: 0x0028 0x0029: name: parenright code point: 0x0029 0x002a: name: asterisk code point: 0x002A 0x002b: name: plus code point: 0x002B 0x002c: name: comma code point: 0x002C 0x002d: name: minus code point: 0x002D 0x002e: name: period code point: 0x002E 0x002f: name: slash code point: 0x002F 0x0030: name: 0 code point: 0x0030 0x0031: name: 1 code point: 0x0031 0x0032: name: 2 code point: 0x0032 0x0033: name: 3 code point: 0x0033 0x0034: name: 4 code point: 0x0034 0x0035: name: 5 code point: 0x0035 0x0036: name: 6 code point: 0x0036 0x0037: name: 7 code point: 0x0037 0x0038: name: 8 code point: 0x0038 0x0039: name: 9 code point: 0x0039 0x003a: name: colon code point: 0x003A 0x003b: name: semicolon code point: 0x003B 0x003c: name: less code point: 0x003C 0x003d: name: equal code point: 0x003D 0x003e: name: greater code point: 0x003E 0x003f: name: question code point: 0x003F 0x0040: name: at code point: 0x0040 0x0041: name: A code point: 0x0041 lower: 0x0061 # a 0x0042: name: B code point: 0x0042 lower: 0x0062 # b 0x0043: name: C code point: 0x0043 lower: 0x0063 # c 0x0044: name: D code point: 0x0044 lower: 0x0064 # d 0x0045: name: E code point: 0x0045 lower: 0x0065 # e 0x0046: name: F code point: 0x0046 lower: 0x0066 # f 0x0047: name: G code point: 0x0047 lower: 0x0067 # g 0x0048: name: H code point: 0x0048 lower: 0x0068 # h 0x0049: name: I code point: 0x0049 lower: 0x0069 # i 0x004a: name: J code point: 0x004A lower: 0x006a # j 0x004b: name: K code point: 0x004B lower: 0x006b # k 0x004c: name: L code point: 0x004C lower: 0x006c # l 0x004d: name: M code point: 0x004D lower: 0x006d # m 0x004e: name: N code point: 0x004E lower: 0x006e # n 0x004f: name: O code point: 0x004F lower: 0x006f # o 0x0050: name: P code point: 0x0050 lower: 0x0070 # p 0x0051: name: Q code point: 0x0051 lower: 0x0071 # q 0x0052: name: R code point: 0x0052 lower: 0x0072 # r 0x0053: name: S code point: 0x0053 lower: 0x0073 # s 0x0054: name: T code point: 0x0054 lower: 0x0074 # t 0x0055: name: U code point: 0x0055 lower: 0x0075 # u 0x0056: name: V code point: 0x0056 lower: 0x0076 # v 0x0057: name: W code point: 0x0057 lower: 0x0077 # w 0x0058: name: X code point: 0x0058 lower: 0x0078 # x 0x0059: name: Y code point: 0x0059 lower: 0x0079 # y 0x005a: name: Z code point: 0x005A lower: 0x007a # z 0x005b: name: bracketleft code point: 0x005B 0x005c: name: backslash code point: 0x005C 0x005d: name: bracketright code point: 0x005D 0x005e: name: asciicircum code point: 0x005E 0x005f: name: underscore code point: 0x005F 0x0060: name: grave code point: 0x0060 0x0061: name: a code point: 0x0061 upper: 0x0041 # A 0x0062: name: b code point: 0x0062 upper: 0x0042 # B 0x0063: name: c code point: 0x0063 upper: 0x0043 # C 0x0064: name: d code point: 0x0064 upper: 0x0044 # D 0x0065: name: e code point: 0x0065 upper: 0x0045 # E 0x0066: name: f code point: 0x0066 upper: 0x0046 # F 0x0067: name: g code point: 0x0067 upper: 0x0047 # G 0x0068: name: h code point: 0x0068 upper: 0x0048 # H 0x0069: name: i code point: 0x0069 upper: 0x0049 # I 0x006a: name: j code point: 0x006A upper: 0x004a # J 0x006b: name: k code point: 0x006B upper: 0x004b # K 0x006c: name: l code point: 0x006C upper: 0x004c # L 0x006d: name: m code point: 0x006D upper: 0x004d # M 0x006e: name: n code point: 0x006E upper: 0x004e # N 0x006f: name: o code point: 0x006F upper: 0x004f # O 0x0070: name: p code point: 0x0070 upper: 0x0050 # P 0x0071: name: q code point: 0x0071 upper: 0x0051 # Q 0x0072: name: r code point: 0x0072 upper: 0x0052 # R 0x0073: name: s code point: 0x0073 upper: 0x0053 # S 0x0074: name: t code point: 0x0074 upper: 0x0054 # T 0x0075: name: u code point: 0x0075 upper: 0x0055 # U 0x0076: name: v code point: 0x0076 upper: 0x0056 # V 0x0077: name: w code point: 0x0077 upper: 0x0057 # W 0x0078: name: x code point: 0x0078 upper: 0x0058 # X 0x0079: name: y code point: 0x0079 upper: 0x0059 # Y 0x007a: name: z code point: 0x007A upper: 0x005a # Z 0x007b: name: braceleft code point: 0x007B 0x007c: name: bar code point: 0x007C 0x007d: name: braceright code point: 0x007D 0x007e: name: asciitilde code point: 0x007E 0x00a0: name: nobreakspace code point: 0x00A0 0x00a1: name: exclamdown code point: 0x00A1 0x00a2: name: cent code point: 0x00A2 0x00a3: name: sterling code point: 0x00A3 0x00a4: name: currency code point: 0x00A4 0x00a5: name: yen code point: 0x00A5 0x00a6: name: brokenbar code point: 0x00A6 0x00a7: name: section code point: 0x00A7 0x00a8: name: diaeresis code point: 0x00A8 0x00a9: name: copyright code point: 0x00A9 0x00aa: name: ordfeminine code point: 0x00AA 0x00ab: name: guillemotleft code point: 0x00AB 0x00ac: name: notsign code point: 0x00AC 0x00ad: name: hyphen code point: 0x00AD 0x00ae: name: registered code point: 0x00AE 0x00af: name: macron code point: 0x00AF 0x00b0: name: degree code point: 0x00B0 0x00b1: name: plusminus code point: 0x00B1 0x00b2: name: twosuperior code point: 0x00B2 0x00b3: name: threesuperior code point: 0x00B3 0x00b4: name: acute code point: 0x00B4 0x00b5: name: mu code point: 0x00B5 upper: 0x07cc # Greek_MU 0x00b6: name: paragraph code point: 0x00B6 0x00b7: name: periodcentered code point: 0x00B7 0x00b8: name: cedilla code point: 0x00B8 0x00b9: name: onesuperior code point: 0x00B9 0x00ba: name: masculine code point: 0x00BA 0x00bb: name: guillemotright code point: 0x00BB 0x00bc: name: onequarter code point: 0x00BC 0x00bd: name: onehalf code point: 0x00BD 0x00be: name: threequarters code point: 0x00BE 0x00bf: name: questiondown code point: 0x00BF 0x00c0: name: Agrave code point: 0x00C0 lower: 0x00e0 # agrave 0x00c1: name: Aacute code point: 0x00C1 lower: 0x00e1 # aacute 0x00c2: name: Acircumflex code point: 0x00C2 lower: 0x00e2 # acircumflex 0x00c3: name: Atilde code point: 0x00C3 lower: 0x00e3 # atilde 0x00c4: name: Adiaeresis code point: 0x00C4 lower: 0x00e4 # adiaeresis 0x00c5: name: Aring code point: 0x00C5 lower: 0x00e5 # aring 0x00c6: name: AE code point: 0x00C6 lower: 0x00e6 # ae 0x00c7: name: Ccedilla code point: 0x00C7 lower: 0x00e7 # ccedilla 0x00c8: name: Egrave code point: 0x00C8 lower: 0x00e8 # egrave 0x00c9: name: Eacute code point: 0x00C9 lower: 0x00e9 # eacute 0x00ca: name: Ecircumflex code point: 0x00CA lower: 0x00ea # ecircumflex 0x00cb: name: Ediaeresis code point: 0x00CB lower: 0x00eb # ediaeresis 0x00cc: name: Igrave code point: 0x00CC lower: 0x00ec # igrave 0x00cd: name: Iacute code point: 0x00CD lower: 0x00ed # iacute 0x00ce: name: Icircumflex code point: 0x00CE lower: 0x00ee # icircumflex 0x00cf: name: Idiaeresis code point: 0x00CF lower: 0x00ef # idiaeresis 0x00d0: name: ETH code point: 0x00D0 lower: 0x00f0 # eth 0x00d1: name: Ntilde code point: 0x00D1 lower: 0x00f1 # ntilde 0x00d2: name: Ograve code point: 0x00D2 lower: 0x00f2 # ograve 0x00d3: name: Oacute code point: 0x00D3 lower: 0x00f3 # oacute 0x00d4: name: Ocircumflex code point: 0x00D4 lower: 0x00f4 # ocircumflex 0x00d5: name: Otilde code point: 0x00D5 lower: 0x00f5 # otilde 0x00d6: name: Odiaeresis code point: 0x00D6 lower: 0x00f6 # odiaeresis 0x00d7: name: multiply code point: 0x00D7 0x00d8: name: Oslash code point: 0x00D8 lower: 0x00f8 # oslash 0x00d9: name: Ugrave code point: 0x00D9 lower: 0x00f9 # ugrave 0x00da: name: Uacute code point: 0x00DA lower: 0x00fa # uacute 0x00db: name: Ucircumflex code point: 0x00DB lower: 0x00fb # ucircumflex 0x00dc: name: Udiaeresis code point: 0x00DC lower: 0x00fc # udiaeresis 0x00dd: name: Yacute code point: 0x00DD lower: 0x00fd # yacute 0x00de: name: THORN code point: 0x00DE lower: 0x00fe # thorn 0x00df: name: ssharp code point: 0x00DF upper: 0x1001e9e # U1E9E 0x00e0: name: agrave code point: 0x00E0 upper: 0x00c0 # Agrave 0x00e1: name: aacute code point: 0x00E1 upper: 0x00c1 # Aacute 0x00e2: name: acircumflex code point: 0x00E2 upper: 0x00c2 # Acircumflex 0x00e3: name: atilde code point: 0x00E3 upper: 0x00c3 # Atilde 0x00e4: name: adiaeresis code point: 0x00E4 upper: 0x00c4 # Adiaeresis 0x00e5: name: aring code point: 0x00E5 upper: 0x00c5 # Aring 0x00e6: name: ae code point: 0x00E6 upper: 0x00c6 # AE 0x00e7: name: ccedilla code point: 0x00E7 upper: 0x00c7 # Ccedilla 0x00e8: name: egrave code point: 0x00E8 upper: 0x00c8 # Egrave 0x00e9: name: eacute code point: 0x00E9 upper: 0x00c9 # Eacute 0x00ea: name: ecircumflex code point: 0x00EA upper: 0x00ca # Ecircumflex 0x00eb: name: ediaeresis code point: 0x00EB upper: 0x00cb # Ediaeresis 0x00ec: name: igrave code point: 0x00EC upper: 0x00cc # Igrave 0x00ed: name: iacute code point: 0x00ED upper: 0x00cd # Iacute 0x00ee: name: icircumflex code point: 0x00EE upper: 0x00ce # Icircumflex 0x00ef: name: idiaeresis code point: 0x00EF upper: 0x00cf # Idiaeresis 0x00f0: name: eth code point: 0x00F0 upper: 0x00d0 # ETH 0x00f1: name: ntilde code point: 0x00F1 upper: 0x00d1 # Ntilde 0x00f2: name: ograve code point: 0x00F2 upper: 0x00d2 # Ograve 0x00f3: name: oacute code point: 0x00F3 upper: 0x00d3 # Oacute 0x00f4: name: ocircumflex code point: 0x00F4 upper: 0x00d4 # Ocircumflex 0x00f5: name: otilde code point: 0x00F5 upper: 0x00d5 # Otilde 0x00f6: name: odiaeresis code point: 0x00F6 upper: 0x00d6 # Odiaeresis 0x00f7: name: division code point: 0x00F7 0x00f8: name: oslash code point: 0x00F8 upper: 0x00d8 # Oslash 0x00f9: name: ugrave code point: 0x00F9 upper: 0x00d9 # Ugrave 0x00fa: name: uacute code point: 0x00FA upper: 0x00da # Uacute 0x00fb: name: ucircumflex code point: 0x00FB upper: 0x00db # Ucircumflex 0x00fc: name: udiaeresis code point: 0x00FC upper: 0x00dc # Udiaeresis 0x00fd: name: yacute code point: 0x00FD upper: 0x00dd # Yacute 0x00fe: name: thorn code point: 0x00FE upper: 0x00de # THORN 0x00ff: name: ydiaeresis code point: 0x00FF upper: 0x13be # Ydiaeresis 0x01a1: name: Aogonek code point: 0x0104 lower: 0x01b1 # aogonek 0x01a2: name: breve code point: 0x02D8 0x01a3: name: Lstroke code point: 0x0141 lower: 0x01b3 # lstroke 0x01a5: name: Lcaron code point: 0x013D lower: 0x01b5 # lcaron 0x01a6: name: Sacute code point: 0x015A lower: 0x01b6 # sacute 0x01a9: name: Scaron code point: 0x0160 lower: 0x01b9 # scaron 0x01aa: name: Scedilla code point: 0x015E lower: 0x01ba # scedilla 0x01ab: name: Tcaron code point: 0x0164 lower: 0x01bb # tcaron 0x01ac: name: Zacute code point: 0x0179 lower: 0x01bc # zacute 0x01ae: name: Zcaron code point: 0x017D lower: 0x01be # zcaron 0x01af: name: Zabovedot code point: 0x017B lower: 0x01bf # zabovedot 0x01b1: name: aogonek code point: 0x0105 upper: 0x01a1 # Aogonek 0x01b2: name: ogonek code point: 0x02DB 0x01b3: name: lstroke code point: 0x0142 upper: 0x01a3 # Lstroke 0x01b5: name: lcaron code point: 0x013E upper: 0x01a5 # Lcaron 0x01b6: name: sacute code point: 0x015B upper: 0x01a6 # Sacute 0x01b7: name: caron code point: 0x02C7 0x01b9: name: scaron code point: 0x0161 upper: 0x01a9 # Scaron 0x01ba: name: scedilla code point: 0x015F upper: 0x01aa # Scedilla 0x01bb: name: tcaron code point: 0x0165 upper: 0x01ab # Tcaron 0x01bc: name: zacute code point: 0x017A upper: 0x01ac # Zacute 0x01bd: name: doubleacute code point: 0x02DD 0x01be: name: zcaron code point: 0x017E upper: 0x01ae # Zcaron 0x01bf: name: zabovedot code point: 0x017C upper: 0x01af # Zabovedot 0x01c0: name: Racute code point: 0x0154 lower: 0x01e0 # racute 0x01c3: name: Abreve code point: 0x0102 lower: 0x01e3 # abreve 0x01c5: name: Lacute code point: 0x0139 lower: 0x01e5 # lacute 0x01c6: name: Cacute code point: 0x0106 lower: 0x01e6 # cacute 0x01c8: name: Ccaron code point: 0x010C lower: 0x01e8 # ccaron 0x01ca: name: Eogonek code point: 0x0118 lower: 0x01ea # eogonek 0x01cc: name: Ecaron code point: 0x011A lower: 0x01ec # ecaron 0x01cf: name: Dcaron code point: 0x010E lower: 0x01ef # dcaron 0x01d0: name: Dstroke code point: 0x0110 lower: 0x01f0 # dstroke 0x01d1: name: Nacute code point: 0x0143 lower: 0x01f1 # nacute 0x01d2: name: Ncaron code point: 0x0147 lower: 0x01f2 # ncaron 0x01d5: name: Odoubleacute code point: 0x0150 lower: 0x01f5 # odoubleacute 0x01d8: name: Rcaron code point: 0x0158 lower: 0x01f8 # rcaron 0x01d9: name: Uring code point: 0x016E lower: 0x01f9 # uring 0x01db: name: Udoubleacute code point: 0x0170 lower: 0x01fb # udoubleacute 0x01de: name: Tcedilla code point: 0x0162 lower: 0x01fe # tcedilla 0x01e0: name: racute code point: 0x0155 upper: 0x01c0 # Racute 0x01e3: name: abreve code point: 0x0103 upper: 0x01c3 # Abreve 0x01e5: name: lacute code point: 0x013A upper: 0x01c5 # Lacute 0x01e6: name: cacute code point: 0x0107 upper: 0x01c6 # Cacute 0x01e8: name: ccaron code point: 0x010D upper: 0x01c8 # Ccaron 0x01ea: name: eogonek code point: 0x0119 upper: 0x01ca # Eogonek 0x01ec: name: ecaron code point: 0x011B upper: 0x01cc # Ecaron 0x01ef: name: dcaron code point: 0x010F upper: 0x01cf # Dcaron 0x01f0: name: dstroke code point: 0x0111 upper: 0x01d0 # Dstroke 0x01f1: name: nacute code point: 0x0144 upper: 0x01d1 # Nacute 0x01f2: name: ncaron code point: 0x0148 upper: 0x01d2 # Ncaron 0x01f5: name: odoubleacute code point: 0x0151 upper: 0x01d5 # Odoubleacute 0x01f8: name: rcaron code point: 0x0159 upper: 0x01d8 # Rcaron 0x01f9: name: uring code point: 0x016F upper: 0x01d9 # Uring 0x01fb: name: udoubleacute code point: 0x0171 upper: 0x01db # Udoubleacute 0x01fe: name: tcedilla code point: 0x0163 upper: 0x01de # Tcedilla 0x01ff: name: abovedot code point: 0x02D9 0x02a1: name: Hstroke code point: 0x0126 lower: 0x02b1 # hstroke 0x02a6: name: Hcircumflex code point: 0x0124 lower: 0x02b6 # hcircumflex 0x02a9: name: Iabovedot code point: 0x0130 lower: 0x0069 # i 0x02ab: name: Gbreve code point: 0x011E lower: 0x02bb # gbreve 0x02ac: name: Jcircumflex code point: 0x0134 lower: 0x02bc # jcircumflex 0x02b1: name: hstroke code point: 0x0127 upper: 0x02a1 # Hstroke 0x02b6: name: hcircumflex code point: 0x0125 upper: 0x02a6 # Hcircumflex 0x02b9: name: idotless code point: 0x0131 upper: 0x0049 # I 0x02bb: name: gbreve code point: 0x011F upper: 0x02ab # Gbreve 0x02bc: name: jcircumflex code point: 0x0135 upper: 0x02ac # Jcircumflex 0x02c5: name: Cabovedot code point: 0x010A lower: 0x02e5 # cabovedot 0x02c6: name: Ccircumflex code point: 0x0108 lower: 0x02e6 # ccircumflex 0x02d5: name: Gabovedot code point: 0x0120 lower: 0x02f5 # gabovedot 0x02d8: name: Gcircumflex code point: 0x011C lower: 0x02f8 # gcircumflex 0x02dd: name: Ubreve code point: 0x016C lower: 0x02fd # ubreve 0x02de: name: Scircumflex code point: 0x015C lower: 0x02fe # scircumflex 0x02e5: name: cabovedot code point: 0x010B upper: 0x02c5 # Cabovedot 0x02e6: name: ccircumflex code point: 0x0109 upper: 0x02c6 # Ccircumflex 0x02f5: name: gabovedot code point: 0x0121 upper: 0x02d5 # Gabovedot 0x02f8: name: gcircumflex code point: 0x011D upper: 0x02d8 # Gcircumflex 0x02fd: name: ubreve code point: 0x016D upper: 0x02dd # Ubreve 0x02fe: name: scircumflex code point: 0x015D upper: 0x02de # Scircumflex 0x03a2: name: kra code point: 0x0138 0x03a3: name: Rcedilla code point: 0x0156 lower: 0x03b3 # rcedilla 0x03a5: name: Itilde code point: 0x0128 lower: 0x03b5 # itilde 0x03a6: name: Lcedilla code point: 0x013B lower: 0x03b6 # lcedilla 0x03aa: name: Emacron code point: 0x0112 lower: 0x03ba # emacron 0x03ab: name: Gcedilla code point: 0x0122 lower: 0x03bb # gcedilla 0x03ac: name: Tslash code point: 0x0166 lower: 0x03bc # tslash 0x03b3: name: rcedilla code point: 0x0157 upper: 0x03a3 # Rcedilla 0x03b5: name: itilde code point: 0x0129 upper: 0x03a5 # Itilde 0x03b6: name: lcedilla code point: 0x013C upper: 0x03a6 # Lcedilla 0x03ba: name: emacron code point: 0x0113 upper: 0x03aa # Emacron 0x03bb: name: gcedilla code point: 0x0123 upper: 0x03ab # Gcedilla 0x03bc: name: tslash code point: 0x0167 upper: 0x03ac # Tslash 0x03bd: name: ENG code point: 0x014A lower: 0x03bf # eng 0x03bf: name: eng code point: 0x014B upper: 0x03bd # ENG 0x03c0: name: Amacron code point: 0x0100 lower: 0x03e0 # amacron 0x03c7: name: Iogonek code point: 0x012E lower: 0x03e7 # iogonek 0x03cc: name: Eabovedot code point: 0x0116 lower: 0x03ec # eabovedot 0x03cf: name: Imacron code point: 0x012A lower: 0x03ef # imacron 0x03d1: name: Ncedilla code point: 0x0145 lower: 0x03f1 # ncedilla 0x03d2: name: Omacron code point: 0x014C lower: 0x03f2 # omacron 0x03d3: name: Kcedilla code point: 0x0136 lower: 0x03f3 # kcedilla 0x03d9: name: Uogonek code point: 0x0172 lower: 0x03f9 # uogonek 0x03dd: name: Utilde code point: 0x0168 lower: 0x03fd # utilde 0x03de: name: Umacron code point: 0x016A lower: 0x03fe # umacron 0x03e0: name: amacron code point: 0x0101 upper: 0x03c0 # Amacron 0x03e7: name: iogonek code point: 0x012F upper: 0x03c7 # Iogonek 0x03ec: name: eabovedot code point: 0x0117 upper: 0x03cc # Eabovedot 0x03ef: name: imacron code point: 0x012B upper: 0x03cf # Imacron 0x03f1: name: ncedilla code point: 0x0146 upper: 0x03d1 # Ncedilla 0x03f2: name: omacron code point: 0x014D upper: 0x03d2 # Omacron 0x03f3: name: kcedilla code point: 0x0137 upper: 0x03d3 # Kcedilla 0x03f9: name: uogonek code point: 0x0173 upper: 0x03d9 # Uogonek 0x03fd: name: utilde code point: 0x0169 upper: 0x03dd # Utilde 0x03fe: name: umacron code point: 0x016B upper: 0x03de # Umacron 0x047e: name: overline code point: 0x203E 0x04a1: name: kana_fullstop code point: 0x3002 0x04a2: name: kana_openingbracket code point: 0x300C 0x04a3: name: kana_closingbracket code point: 0x300D 0x04a4: name: kana_comma code point: 0x3001 0x04a5: name: kana_conjunctive code point: 0x30FB 0x04a6: name: kana_WO code point: 0x30F2 0x04a7: name: kana_a code point: 0x30A1 0x04a8: name: kana_i code point: 0x30A3 0x04a9: name: kana_u code point: 0x30A5 0x04aa: name: kana_e code point: 0x30A7 0x04ab: name: kana_o code point: 0x30A9 0x04ac: name: kana_ya code point: 0x30E3 0x04ad: name: kana_yu code point: 0x30E5 0x04ae: name: kana_yo code point: 0x30E7 0x04af: name: kana_tsu code point: 0x30C3 0x04b0: name: prolongedsound code point: 0x30FC 0x04b1: name: kana_A code point: 0x30A2 0x04b2: name: kana_I code point: 0x30A4 0x04b3: name: kana_U code point: 0x30A6 0x04b4: name: kana_E code point: 0x30A8 0x04b5: name: kana_O code point: 0x30AA 0x04b6: name: kana_KA code point: 0x30AB 0x04b7: name: kana_KI code point: 0x30AD 0x04b8: name: kana_KU code point: 0x30AF 0x04b9: name: kana_KE code point: 0x30B1 0x04ba: name: kana_KO code point: 0x30B3 0x04bb: name: kana_SA code point: 0x30B5 0x04bc: name: kana_SHI code point: 0x30B7 0x04bd: name: kana_SU code point: 0x30B9 0x04be: name: kana_SE code point: 0x30BB 0x04bf: name: kana_SO code point: 0x30BD 0x04c0: name: kana_TA code point: 0x30BF 0x04c1: name: kana_CHI code point: 0x30C1 0x04c2: name: kana_TSU code point: 0x30C4 0x04c3: name: kana_TE code point: 0x30C6 0x04c4: name: kana_TO code point: 0x30C8 0x04c5: name: kana_NA code point: 0x30CA 0x04c6: name: kana_NI code point: 0x30CB 0x04c7: name: kana_NU code point: 0x30CC 0x04c8: name: kana_NE code point: 0x30CD 0x04c9: name: kana_NO code point: 0x30CE 0x04ca: name: kana_HA code point: 0x30CF 0x04cb: name: kana_HI code point: 0x30D2 0x04cc: name: kana_FU code point: 0x30D5 0x04cd: name: kana_HE code point: 0x30D8 0x04ce: name: kana_HO code point: 0x30DB 0x04cf: name: kana_MA code point: 0x30DE 0x04d0: name: kana_MI code point: 0x30DF 0x04d1: name: kana_MU code point: 0x30E0 0x04d2: name: kana_ME code point: 0x30E1 0x04d3: name: kana_MO code point: 0x30E2 0x04d4: name: kana_YA code point: 0x30E4 0x04d5: name: kana_YU code point: 0x30E6 0x04d6: name: kana_YO code point: 0x30E8 0x04d7: name: kana_RA code point: 0x30E9 0x04d8: name: kana_RI code point: 0x30EA 0x04d9: name: kana_RU code point: 0x30EB 0x04da: name: kana_RE code point: 0x30EC 0x04db: name: kana_RO code point: 0x30ED 0x04dc: name: kana_WA code point: 0x30EF 0x04dd: name: kana_N code point: 0x30F3 0x04de: name: voicedsound code point: 0x309B 0x04df: name: semivoicedsound code point: 0x309C 0x05ac: name: Arabic_comma code point: 0x060C 0x05bb: name: Arabic_semicolon code point: 0x061B 0x05bf: name: Arabic_question_mark code point: 0x061F 0x05c1: name: Arabic_hamza code point: 0x0621 0x05c2: name: Arabic_maddaonalef code point: 0x0622 0x05c3: name: Arabic_hamzaonalef code point: 0x0623 0x05c4: name: Arabic_hamzaonwaw code point: 0x0624 0x05c5: name: Arabic_hamzaunderalef code point: 0x0625 0x05c6: name: Arabic_hamzaonyeh code point: 0x0626 0x05c7: name: Arabic_alef code point: 0x0627 0x05c8: name: Arabic_beh code point: 0x0628 0x05c9: name: Arabic_tehmarbuta code point: 0x0629 0x05ca: name: Arabic_teh code point: 0x062A 0x05cb: name: Arabic_theh code point: 0x062B 0x05cc: name: Arabic_jeem code point: 0x062C 0x05cd: name: Arabic_hah code point: 0x062D 0x05ce: name: Arabic_khah code point: 0x062E 0x05cf: name: Arabic_dal code point: 0x062F 0x05d0: name: Arabic_thal code point: 0x0630 0x05d1: name: Arabic_ra code point: 0x0631 0x05d2: name: Arabic_zain code point: 0x0632 0x05d3: name: Arabic_seen code point: 0x0633 0x05d4: name: Arabic_sheen code point: 0x0634 0x05d5: name: Arabic_sad code point: 0x0635 0x05d6: name: Arabic_dad code point: 0x0636 0x05d7: name: Arabic_tah code point: 0x0637 0x05d8: name: Arabic_zah code point: 0x0638 0x05d9: name: Arabic_ain code point: 0x0639 0x05da: name: Arabic_ghain code point: 0x063A 0x05e0: name: Arabic_tatweel code point: 0x0640 0x05e1: name: Arabic_feh code point: 0x0641 0x05e2: name: Arabic_qaf code point: 0x0642 0x05e3: name: Arabic_kaf code point: 0x0643 0x05e4: name: Arabic_lam code point: 0x0644 0x05e5: name: Arabic_meem code point: 0x0645 0x05e6: name: Arabic_noon code point: 0x0646 0x05e7: name: Arabic_ha code point: 0x0647 0x05e8: name: Arabic_waw code point: 0x0648 0x05e9: name: Arabic_alefmaksura code point: 0x0649 0x05ea: name: Arabic_yeh code point: 0x064A 0x05eb: name: Arabic_fathatan code point: 0x064B 0x05ec: name: Arabic_dammatan code point: 0x064C 0x05ed: name: Arabic_kasratan code point: 0x064D 0x05ee: name: Arabic_fatha code point: 0x064E 0x05ef: name: Arabic_damma code point: 0x064F 0x05f0: name: Arabic_kasra code point: 0x0650 0x05f1: name: Arabic_shadda code point: 0x0651 0x05f2: name: Arabic_sukun code point: 0x0652 0x06a1: name: Serbian_dje code point: 0x0452 upper: 0x06b1 # Serbian_DJE 0x06a2: name: Macedonia_gje code point: 0x0453 upper: 0x06b2 # Macedonia_GJE 0x06a3: name: Cyrillic_io code point: 0x0451 upper: 0x06b3 # Cyrillic_IO 0x06a4: name: Ukrainian_ie code point: 0x0454 upper: 0x06b4 # Ukrainian_IE 0x06a5: name: Macedonia_dse code point: 0x0455 upper: 0x06b5 # Macedonia_DSE 0x06a6: name: Ukrainian_i code point: 0x0456 upper: 0x06b6 # Ukrainian_I 0x06a7: name: Ukrainian_yi code point: 0x0457 upper: 0x06b7 # Ukrainian_YI 0x06a8: name: Cyrillic_je code point: 0x0458 upper: 0x06b8 # Cyrillic_JE 0x06a9: name: Cyrillic_lje code point: 0x0459 upper: 0x06b9 # Cyrillic_LJE 0x06aa: name: Cyrillic_nje code point: 0x045A upper: 0x06ba # Cyrillic_NJE 0x06ab: name: Serbian_tshe code point: 0x045B upper: 0x06bb # Serbian_TSHE 0x06ac: name: Macedonia_kje code point: 0x045C upper: 0x06bc # Macedonia_KJE 0x06ad: name: Ukrainian_ghe_with_upturn code point: 0x0491 upper: 0x06bd # Ukrainian_GHE_WITH_UPTURN 0x06ae: name: Byelorussian_shortu code point: 0x045E upper: 0x06be # Byelorussian_SHORTU 0x06af: name: Cyrillic_dzhe code point: 0x045F upper: 0x06bf # Cyrillic_DZHE 0x06b0: name: numerosign code point: 0x2116 0x06b1: name: Serbian_DJE code point: 0x0402 lower: 0x06a1 # Serbian_dje 0x06b2: name: Macedonia_GJE code point: 0x0403 lower: 0x06a2 # Macedonia_gje 0x06b3: name: Cyrillic_IO code point: 0x0401 lower: 0x06a3 # Cyrillic_io 0x06b4: name: Ukrainian_IE code point: 0x0404 lower: 0x06a4 # Ukrainian_ie 0x06b5: name: Macedonia_DSE code point: 0x0405 lower: 0x06a5 # Macedonia_dse 0x06b6: name: Ukrainian_I code point: 0x0406 lower: 0x06a6 # Ukrainian_i 0x06b7: name: Ukrainian_YI code point: 0x0407 lower: 0x06a7 # Ukrainian_yi 0x06b8: name: Cyrillic_JE code point: 0x0408 lower: 0x06a8 # Cyrillic_je 0x06b9: name: Cyrillic_LJE code point: 0x0409 lower: 0x06a9 # Cyrillic_lje 0x06ba: name: Cyrillic_NJE code point: 0x040A lower: 0x06aa # Cyrillic_nje 0x06bb: name: Serbian_TSHE code point: 0x040B lower: 0x06ab # Serbian_tshe 0x06bc: name: Macedonia_KJE code point: 0x040C lower: 0x06ac # Macedonia_kje 0x06bd: name: Ukrainian_GHE_WITH_UPTURN code point: 0x0490 lower: 0x06ad # Ukrainian_ghe_with_upturn 0x06be: name: Byelorussian_SHORTU code point: 0x040E lower: 0x06ae # Byelorussian_shortu 0x06bf: name: Cyrillic_DZHE code point: 0x040F lower: 0x06af # Cyrillic_dzhe 0x06c0: name: Cyrillic_yu code point: 0x044E upper: 0x06e0 # Cyrillic_YU 0x06c1: name: Cyrillic_a code point: 0x0430 upper: 0x06e1 # Cyrillic_A 0x06c2: name: Cyrillic_be code point: 0x0431 upper: 0x06e2 # Cyrillic_BE 0x06c3: name: Cyrillic_tse code point: 0x0446 upper: 0x06e3 # Cyrillic_TSE 0x06c4: name: Cyrillic_de code point: 0x0434 upper: 0x06e4 # Cyrillic_DE 0x06c5: name: Cyrillic_ie code point: 0x0435 upper: 0x06e5 # Cyrillic_IE 0x06c6: name: Cyrillic_ef code point: 0x0444 upper: 0x06e6 # Cyrillic_EF 0x06c7: name: Cyrillic_ghe code point: 0x0433 upper: 0x06e7 # Cyrillic_GHE 0x06c8: name: Cyrillic_ha code point: 0x0445 upper: 0x06e8 # Cyrillic_HA 0x06c9: name: Cyrillic_i code point: 0x0438 upper: 0x06e9 # Cyrillic_I 0x06ca: name: Cyrillic_shorti code point: 0x0439 upper: 0x06ea # Cyrillic_SHORTI 0x06cb: name: Cyrillic_ka code point: 0x043A upper: 0x06eb # Cyrillic_KA 0x06cc: name: Cyrillic_el code point: 0x043B upper: 0x06ec # Cyrillic_EL 0x06cd: name: Cyrillic_em code point: 0x043C upper: 0x06ed # Cyrillic_EM 0x06ce: name: Cyrillic_en code point: 0x043D upper: 0x06ee # Cyrillic_EN 0x06cf: name: Cyrillic_o code point: 0x043E upper: 0x06ef # Cyrillic_O 0x06d0: name: Cyrillic_pe code point: 0x043F upper: 0x06f0 # Cyrillic_PE 0x06d1: name: Cyrillic_ya code point: 0x044F upper: 0x06f1 # Cyrillic_YA 0x06d2: name: Cyrillic_er code point: 0x0440 upper: 0x06f2 # Cyrillic_ER 0x06d3: name: Cyrillic_es code point: 0x0441 upper: 0x06f3 # Cyrillic_ES 0x06d4: name: Cyrillic_te code point: 0x0442 upper: 0x06f4 # Cyrillic_TE 0x06d5: name: Cyrillic_u code point: 0x0443 upper: 0x06f5 # Cyrillic_U 0x06d6: name: Cyrillic_zhe code point: 0x0436 upper: 0x06f6 # Cyrillic_ZHE 0x06d7: name: Cyrillic_ve code point: 0x0432 upper: 0x06f7 # Cyrillic_VE 0x06d8: name: Cyrillic_softsign code point: 0x044C upper: 0x06f8 # Cyrillic_SOFTSIGN 0x06d9: name: Cyrillic_yeru code point: 0x044B upper: 0x06f9 # Cyrillic_YERU 0x06da: name: Cyrillic_ze code point: 0x0437 upper: 0x06fa # Cyrillic_ZE 0x06db: name: Cyrillic_sha code point: 0x0448 upper: 0x06fb # Cyrillic_SHA 0x06dc: name: Cyrillic_e code point: 0x044D upper: 0x06fc # Cyrillic_E 0x06dd: name: Cyrillic_shcha code point: 0x0449 upper: 0x06fd # Cyrillic_SHCHA 0x06de: name: Cyrillic_che code point: 0x0447 upper: 0x06fe # Cyrillic_CHE 0x06df: name: Cyrillic_hardsign code point: 0x044A upper: 0x06ff # Cyrillic_HARDSIGN 0x06e0: name: Cyrillic_YU code point: 0x042E lower: 0x06c0 # Cyrillic_yu 0x06e1: name: Cyrillic_A code point: 0x0410 lower: 0x06c1 # Cyrillic_a 0x06e2: name: Cyrillic_BE code point: 0x0411 lower: 0x06c2 # Cyrillic_be 0x06e3: name: Cyrillic_TSE code point: 0x0426 lower: 0x06c3 # Cyrillic_tse 0x06e4: name: Cyrillic_DE code point: 0x0414 lower: 0x06c4 # Cyrillic_de 0x06e5: name: Cyrillic_IE code point: 0x0415 lower: 0x06c5 # Cyrillic_ie 0x06e6: name: Cyrillic_EF code point: 0x0424 lower: 0x06c6 # Cyrillic_ef 0x06e7: name: Cyrillic_GHE code point: 0x0413 lower: 0x06c7 # Cyrillic_ghe 0x06e8: name: Cyrillic_HA code point: 0x0425 lower: 0x06c8 # Cyrillic_ha 0x06e9: name: Cyrillic_I code point: 0x0418 lower: 0x06c9 # Cyrillic_i 0x06ea: name: Cyrillic_SHORTI code point: 0x0419 lower: 0x06ca # Cyrillic_shorti 0x06eb: name: Cyrillic_KA code point: 0x041A lower: 0x06cb # Cyrillic_ka 0x06ec: name: Cyrillic_EL code point: 0x041B lower: 0x06cc # Cyrillic_el 0x06ed: name: Cyrillic_EM code point: 0x041C lower: 0x06cd # Cyrillic_em 0x06ee: name: Cyrillic_EN code point: 0x041D lower: 0x06ce # Cyrillic_en 0x06ef: name: Cyrillic_O code point: 0x041E lower: 0x06cf # Cyrillic_o 0x06f0: name: Cyrillic_PE code point: 0x041F lower: 0x06d0 # Cyrillic_pe 0x06f1: name: Cyrillic_YA code point: 0x042F lower: 0x06d1 # Cyrillic_ya 0x06f2: name: Cyrillic_ER code point: 0x0420 lower: 0x06d2 # Cyrillic_er 0x06f3: name: Cyrillic_ES code point: 0x0421 lower: 0x06d3 # Cyrillic_es 0x06f4: name: Cyrillic_TE code point: 0x0422 lower: 0x06d4 # Cyrillic_te 0x06f5: name: Cyrillic_U code point: 0x0423 lower: 0x06d5 # Cyrillic_u 0x06f6: name: Cyrillic_ZHE code point: 0x0416 lower: 0x06d6 # Cyrillic_zhe 0x06f7: name: Cyrillic_VE code point: 0x0412 lower: 0x06d7 # Cyrillic_ve 0x06f8: name: Cyrillic_SOFTSIGN code point: 0x042C lower: 0x06d8 # Cyrillic_softsign 0x06f9: name: Cyrillic_YERU code point: 0x042B lower: 0x06d9 # Cyrillic_yeru 0x06fa: name: Cyrillic_ZE code point: 0x0417 lower: 0x06da # Cyrillic_ze 0x06fb: name: Cyrillic_SHA code point: 0x0428 lower: 0x06db # Cyrillic_sha 0x06fc: name: Cyrillic_E code point: 0x042D lower: 0x06dc # Cyrillic_e 0x06fd: name: Cyrillic_SHCHA code point: 0x0429 lower: 0x06dd # Cyrillic_shcha 0x06fe: name: Cyrillic_CHE code point: 0x0427 lower: 0x06de # Cyrillic_che 0x06ff: name: Cyrillic_HARDSIGN code point: 0x042A lower: 0x06df # Cyrillic_hardsign 0x07a1: name: Greek_ALPHAaccent code point: 0x0386 lower: 0x07b1 # Greek_alphaaccent 0x07a2: name: Greek_EPSILONaccent code point: 0x0388 lower: 0x07b2 # Greek_epsilonaccent 0x07a3: name: Greek_ETAaccent code point: 0x0389 lower: 0x07b3 # Greek_etaaccent 0x07a4: name: Greek_IOTAaccent code point: 0x038A lower: 0x07b4 # Greek_iotaaccent 0x07a5: name: Greek_IOTAdieresis code point: 0x03AA lower: 0x07b5 # Greek_iotadieresis 0x07a7: name: Greek_OMICRONaccent code point: 0x038C lower: 0x07b7 # Greek_omicronaccent 0x07a8: name: Greek_UPSILONaccent code point: 0x038E lower: 0x07b8 # Greek_upsilonaccent 0x07a9: name: Greek_UPSILONdieresis code point: 0x03AB lower: 0x07b9 # Greek_upsilondieresis 0x07ab: name: Greek_OMEGAaccent code point: 0x038F lower: 0x07bb # Greek_omegaaccent 0x07ae: name: Greek_accentdieresis code point: 0x0385 0x07af: name: Greek_horizbar code point: 0x2015 0x07b1: name: Greek_alphaaccent code point: 0x03AC upper: 0x07a1 # Greek_ALPHAaccent 0x07b2: name: Greek_epsilonaccent code point: 0x03AD upper: 0x07a2 # Greek_EPSILONaccent 0x07b3: name: Greek_etaaccent code point: 0x03AE upper: 0x07a3 # Greek_ETAaccent 0x07b4: name: Greek_iotaaccent code point: 0x03AF upper: 0x07a4 # Greek_IOTAaccent 0x07b5: name: Greek_iotadieresis code point: 0x03CA upper: 0x07a5 # Greek_IOTAdieresis 0x07b6: name: Greek_iotaaccentdieresis code point: 0x0390 0x07b7: name: Greek_omicronaccent code point: 0x03CC upper: 0x07a7 # Greek_OMICRONaccent 0x07b8: name: Greek_upsilonaccent code point: 0x03CD upper: 0x07a8 # Greek_UPSILONaccent 0x07b9: name: Greek_upsilondieresis code point: 0x03CB upper: 0x07a9 # Greek_UPSILONdieresis 0x07ba: name: Greek_upsilonaccentdieresis code point: 0x03B0 0x07bb: name: Greek_omegaaccent code point: 0x03CE upper: 0x07ab # Greek_OMEGAaccent 0x07c1: name: Greek_ALPHA code point: 0x0391 lower: 0x07e1 # Greek_alpha 0x07c2: name: Greek_BETA code point: 0x0392 lower: 0x07e2 # Greek_beta 0x07c3: name: Greek_GAMMA code point: 0x0393 lower: 0x07e3 # Greek_gamma 0x07c4: name: Greek_DELTA code point: 0x0394 lower: 0x07e4 # Greek_delta 0x07c5: name: Greek_EPSILON code point: 0x0395 lower: 0x07e5 # Greek_epsilon 0x07c6: name: Greek_ZETA code point: 0x0396 lower: 0x07e6 # Greek_zeta 0x07c7: name: Greek_ETA code point: 0x0397 lower: 0x07e7 # Greek_eta 0x07c8: name: Greek_THETA code point: 0x0398 lower: 0x07e8 # Greek_theta 0x07c9: name: Greek_IOTA code point: 0x0399 lower: 0x07e9 # Greek_iota 0x07ca: name: Greek_KAPPA code point: 0x039A lower: 0x07ea # Greek_kappa 0x07cb: name: Greek_LAMDA code point: 0x039B lower: 0x07eb # Greek_lamda 0x07cc: name: Greek_MU code point: 0x039C lower: 0x07ec # Greek_mu 0x07cd: name: Greek_NU code point: 0x039D lower: 0x07ed # Greek_nu 0x07ce: name: Greek_XI code point: 0x039E lower: 0x07ee # Greek_xi 0x07cf: name: Greek_OMICRON code point: 0x039F lower: 0x07ef # Greek_omicron 0x07d0: name: Greek_PI code point: 0x03A0 lower: 0x07f0 # Greek_pi 0x07d1: name: Greek_RHO code point: 0x03A1 lower: 0x07f1 # Greek_rho 0x07d2: name: Greek_SIGMA code point: 0x03A3 lower: 0x07f2 # Greek_sigma 0x07d4: name: Greek_TAU code point: 0x03A4 lower: 0x07f4 # Greek_tau 0x07d5: name: Greek_UPSILON code point: 0x03A5 lower: 0x07f5 # Greek_upsilon 0x07d6: name: Greek_PHI code point: 0x03A6 lower: 0x07f6 # Greek_phi 0x07d7: name: Greek_CHI code point: 0x03A7 lower: 0x07f7 # Greek_chi 0x07d8: name: Greek_PSI code point: 0x03A8 lower: 0x07f8 # Greek_psi 0x07d9: name: Greek_OMEGA code point: 0x03A9 lower: 0x07f9 # Greek_omega 0x07e1: name: Greek_alpha code point: 0x03B1 upper: 0x07c1 # Greek_ALPHA 0x07e2: name: Greek_beta code point: 0x03B2 upper: 0x07c2 # Greek_BETA 0x07e3: name: Greek_gamma code point: 0x03B3 upper: 0x07c3 # Greek_GAMMA 0x07e4: name: Greek_delta code point: 0x03B4 upper: 0x07c4 # Greek_DELTA 0x07e5: name: Greek_epsilon code point: 0x03B5 upper: 0x07c5 # Greek_EPSILON 0x07e6: name: Greek_zeta code point: 0x03B6 upper: 0x07c6 # Greek_ZETA 0x07e7: name: Greek_eta code point: 0x03B7 upper: 0x07c7 # Greek_ETA 0x07e8: name: Greek_theta code point: 0x03B8 upper: 0x07c8 # Greek_THETA 0x07e9: name: Greek_iota code point: 0x03B9 upper: 0x07c9 # Greek_IOTA 0x07ea: name: Greek_kappa code point: 0x03BA upper: 0x07ca # Greek_KAPPA 0x07eb: name: Greek_lamda code point: 0x03BB upper: 0x07cb # Greek_LAMDA 0x07ec: name: Greek_mu code point: 0x03BC upper: 0x07cc # Greek_MU 0x07ed: name: Greek_nu code point: 0x03BD upper: 0x07cd # Greek_NU 0x07ee: name: Greek_xi code point: 0x03BE upper: 0x07ce # Greek_XI 0x07ef: name: Greek_omicron code point: 0x03BF upper: 0x07cf # Greek_OMICRON 0x07f0: name: Greek_pi code point: 0x03C0 upper: 0x07d0 # Greek_PI 0x07f1: name: Greek_rho code point: 0x03C1 upper: 0x07d1 # Greek_RHO 0x07f2: name: Greek_sigma code point: 0x03C3 upper: 0x07d2 # Greek_SIGMA 0x07f3: name: Greek_finalsmallsigma code point: 0x03C2 upper: 0x07d2 # Greek_SIGMA 0x07f4: name: Greek_tau code point: 0x03C4 upper: 0x07d4 # Greek_TAU 0x07f5: name: Greek_upsilon code point: 0x03C5 upper: 0x07d5 # Greek_UPSILON 0x07f6: name: Greek_phi code point: 0x03C6 upper: 0x07d6 # Greek_PHI 0x07f7: name: Greek_chi code point: 0x03C7 upper: 0x07d7 # Greek_CHI 0x07f8: name: Greek_psi code point: 0x03C8 upper: 0x07d8 # Greek_PSI 0x07f9: name: Greek_omega code point: 0x03C9 upper: 0x07d9 # Greek_OMEGA 0x08a1: name: leftradical code point: 0x23B7 0x08a2: name: topleftradical code point: 0x250C 0x08a3: name: horizconnector code point: 0x2500 0x08a4: name: topintegral code point: 0x2320 0x08a5: name: botintegral code point: 0x2321 0x08a6: name: vertconnector code point: 0x2502 0x08a7: name: topleftsqbracket code point: 0x23A1 0x08a8: name: botleftsqbracket code point: 0x23A3 0x08a9: name: toprightsqbracket code point: 0x23A4 0x08aa: name: botrightsqbracket code point: 0x23A6 0x08ab: name: topleftparens code point: 0x239B 0x08ac: name: botleftparens code point: 0x239D 0x08ad: name: toprightparens code point: 0x239E 0x08ae: name: botrightparens code point: 0x23A0 0x08af: name: leftmiddlecurlybrace code point: 0x23A8 0x08b0: name: rightmiddlecurlybrace code point: 0x23AC 0x08b1: name: topleftsummation 0x08b2: name: botleftsummation 0x08b3: name: topvertsummationconnector 0x08b4: name: botvertsummationconnector 0x08b5: name: toprightsummation 0x08b6: name: botrightsummation 0x08b7: name: rightmiddlesummation 0x08bc: name: lessthanequal code point: 0x2264 0x08bd: name: notequal code point: 0x2260 0x08be: name: greaterthanequal code point: 0x2265 0x08bf: name: integral code point: 0x222B 0x08c0: name: therefore code point: 0x2234 0x08c1: name: variation code point: 0x221D 0x08c2: name: infinity code point: 0x221E 0x08c5: name: nabla code point: 0x2207 0x08c8: name: approximate code point: 0x223C 0x08c9: name: similarequal code point: 0x2243 0x08cd: name: ifonlyif code point: 0x21D4 0x08ce: name: implies code point: 0x21D2 0x08cf: name: identical code point: 0x2261 0x08d6: name: radical code point: 0x221A 0x08da: name: includedin code point: 0x2282 0x08db: name: includes code point: 0x2283 0x08dc: name: intersection code point: 0x2229 0x08dd: name: union code point: 0x222A 0x08de: name: logicaland code point: 0x2227 0x08df: name: logicalor code point: 0x2228 0x08ef: name: partialderivative code point: 0x2202 0x08f6: name: function code point: 0x0192 upper: 0x1000191 # U0191 0x08fb: name: leftarrow code point: 0x2190 0x08fc: name: uparrow code point: 0x2191 0x08fd: name: rightarrow code point: 0x2192 0x08fe: name: downarrow code point: 0x2193 0x09df: name: blank 0x09e0: name: soliddiamond code point: 0x25C6 0x09e1: name: checkerboard code point: 0x2592 0x09e2: name: ht code point: 0x2409 0x09e3: name: ff code point: 0x240C 0x09e4: name: cr code point: 0x240D 0x09e5: name: lf code point: 0x240A 0x09e8: name: nl code point: 0x2424 0x09e9: name: vt code point: 0x240B 0x09ea: name: lowrightcorner code point: 0x2518 0x09eb: name: uprightcorner code point: 0x2510 0x09ec: name: upleftcorner code point: 0x250C 0x09ed: name: lowleftcorner code point: 0x2514 0x09ee: name: crossinglines code point: 0x253C 0x09ef: name: horizlinescan1 code point: 0x23BA 0x09f0: name: horizlinescan3 code point: 0x23BB 0x09f1: name: horizlinescan5 code point: 0x2500 0x09f2: name: horizlinescan7 code point: 0x23BC 0x09f3: name: horizlinescan9 code point: 0x23BD 0x09f4: name: leftt code point: 0x251C 0x09f5: name: rightt code point: 0x2524 0x09f6: name: bott code point: 0x2534 0x09f7: name: topt code point: 0x252C 0x09f8: name: vertbar code point: 0x2502 0x0aa1: name: emspace code point: 0x2003 0x0aa2: name: enspace code point: 0x2002 0x0aa3: name: em3space code point: 0x2004 0x0aa4: name: em4space code point: 0x2005 0x0aa5: name: digitspace code point: 0x2007 0x0aa6: name: punctspace code point: 0x2008 0x0aa7: name: thinspace code point: 0x2009 0x0aa8: name: hairspace code point: 0x200A 0x0aa9: name: emdash code point: 0x2014 0x0aaa: name: endash code point: 0x2013 0x0aac: name: signifblank code point: 0x2423 0x0aae: name: ellipsis code point: 0x2026 0x0aaf: name: doubbaselinedot code point: 0x2025 0x0ab0: name: onethird code point: 0x2153 0x0ab1: name: twothirds code point: 0x2154 0x0ab2: name: onefifth code point: 0x2155 0x0ab3: name: twofifths code point: 0x2156 0x0ab4: name: threefifths code point: 0x2157 0x0ab5: name: fourfifths code point: 0x2158 0x0ab6: name: onesixth code point: 0x2159 0x0ab7: name: fivesixths code point: 0x215A 0x0ab8: name: careof code point: 0x2105 0x0abb: name: figdash code point: 0x2012 0x0abc: name: leftanglebracket code point: 0x27E8 0x0abd: name: decimalpoint code point: 0x002E 0x0abe: name: rightanglebracket code point: 0x27E9 0x0abf: name: marker 0x0ac3: name: oneeighth code point: 0x215B 0x0ac4: name: threeeighths code point: 0x215C 0x0ac5: name: fiveeighths code point: 0x215D 0x0ac6: name: seveneighths code point: 0x215E 0x0ac9: name: trademark code point: 0x2122 0x0aca: name: signaturemark code point: 0x2613 0x0acb: name: trademarkincircle 0x0acc: name: leftopentriangle code point: 0x25C1 0x0acd: name: rightopentriangle code point: 0x25B7 0x0ace: name: emopencircle code point: 0x25CB 0x0acf: name: emopenrectangle code point: 0x25AF 0x0ad0: name: leftsinglequotemark code point: 0x2018 0x0ad1: name: rightsinglequotemark code point: 0x2019 0x0ad2: name: leftdoublequotemark code point: 0x201C 0x0ad3: name: rightdoublequotemark code point: 0x201D 0x0ad4: name: prescription code point: 0x211E 0x0ad5: name: permille code point: 0x2030 0x0ad6: name: minutes code point: 0x2032 0x0ad7: name: seconds code point: 0x2033 0x0ad9: name: latincross code point: 0x271D 0x0ada: name: hexagram 0x0adb: name: filledrectbullet code point: 0x25AC 0x0adc: name: filledlefttribullet code point: 0x25C0 0x0add: name: filledrighttribullet code point: 0x25B6 0x0ade: name: emfilledcircle code point: 0x25CF 0x0adf: name: emfilledrect code point: 0x25AE 0x0ae0: name: enopencircbullet code point: 0x25E6 0x0ae1: name: enopensquarebullet code point: 0x25AB 0x0ae2: name: openrectbullet code point: 0x25AD 0x0ae3: name: opentribulletup code point: 0x25B3 0x0ae4: name: opentribulletdown code point: 0x25BD 0x0ae5: name: openstar code point: 0x2606 0x0ae6: name: enfilledcircbullet code point: 0x2022 0x0ae7: name: enfilledsqbullet code point: 0x25AA 0x0ae8: name: filledtribulletup code point: 0x25B2 0x0ae9: name: filledtribulletdown code point: 0x25BC 0x0aea: name: leftpointer code point: 0x261C 0x0aeb: name: rightpointer code point: 0x261E 0x0aec: name: club code point: 0x2663 0x0aed: name: diamond code point: 0x2666 0x0aee: name: heart code point: 0x2665 0x0af0: name: maltesecross code point: 0x2720 0x0af1: name: dagger code point: 0x2020 0x0af2: name: doubledagger code point: 0x2021 0x0af3: name: checkmark code point: 0x2713 0x0af4: name: ballotcross code point: 0x2717 0x0af5: name: musicalsharp code point: 0x266F 0x0af6: name: musicalflat code point: 0x266D 0x0af7: name: malesymbol code point: 0x2642 0x0af8: name: femalesymbol code point: 0x2640 0x0af9: name: telephone code point: 0x260E 0x0afa: name: telephonerecorder code point: 0x2315 0x0afb: name: phonographcopyright code point: 0x2117 0x0afc: name: caret code point: 0x2038 0x0afd: name: singlelowquotemark code point: 0x201A 0x0afe: name: doublelowquotemark code point: 0x201E 0x0aff: name: cursor 0x0ba3: name: leftcaret code point: 0x003C 0x0ba6: name: rightcaret code point: 0x003E 0x0ba8: name: downcaret code point: 0x2228 0x0ba9: name: upcaret code point: 0x2227 0x0bc0: name: overbar code point: 0x00AF 0x0bc2: name: downtack code point: 0x22A4 0x0bc3: name: upshoe code point: 0x2229 0x0bc4: name: downstile code point: 0x230A 0x0bc6: name: underbar code point: 0x005F 0x0bca: name: jot code point: 0x2218 0x0bcc: name: quad code point: 0x2395 0x0bce: name: uptack code point: 0x22A5 0x0bcf: name: circle code point: 0x25CB 0x0bd3: name: upstile code point: 0x2308 0x0bd6: name: downshoe code point: 0x222A 0x0bd8: name: rightshoe code point: 0x2283 0x0bda: name: leftshoe code point: 0x2282 0x0bdc: name: lefttack code point: 0x22A3 0x0bfc: name: righttack code point: 0x22A2 0x0cdf: name: hebrew_doublelowline code point: 0x2017 0x0ce0: name: hebrew_aleph code point: 0x05D0 0x0ce1: name: hebrew_bet code point: 0x05D1 0x0ce2: name: hebrew_gimel code point: 0x05D2 0x0ce3: name: hebrew_dalet code point: 0x05D3 0x0ce4: name: hebrew_he code point: 0x05D4 0x0ce5: name: hebrew_waw code point: 0x05D5 0x0ce6: name: hebrew_zain code point: 0x05D6 0x0ce7: name: hebrew_chet code point: 0x05D7 0x0ce8: name: hebrew_tet code point: 0x05D8 0x0ce9: name: hebrew_yod code point: 0x05D9 0x0cea: name: hebrew_finalkaph code point: 0x05DA 0x0ceb: name: hebrew_kaph code point: 0x05DB 0x0cec: name: hebrew_lamed code point: 0x05DC 0x0ced: name: hebrew_finalmem code point: 0x05DD 0x0cee: name: hebrew_mem code point: 0x05DE 0x0cef: name: hebrew_finalnun code point: 0x05DF 0x0cf0: name: hebrew_nun code point: 0x05E0 0x0cf1: name: hebrew_samech code point: 0x05E1 0x0cf2: name: hebrew_ayin code point: 0x05E2 0x0cf3: name: hebrew_finalpe code point: 0x05E3 0x0cf4: name: hebrew_pe code point: 0x05E4 0x0cf5: name: hebrew_finalzade code point: 0x05E5 0x0cf6: name: hebrew_zade code point: 0x05E6 0x0cf7: name: hebrew_qoph code point: 0x05E7 0x0cf8: name: hebrew_resh code point: 0x05E8 0x0cf9: name: hebrew_shin code point: 0x05E9 0x0cfa: name: hebrew_taw code point: 0x05EA 0x0da1: name: Thai_kokai code point: 0x0E01 0x0da2: name: Thai_khokhai code point: 0x0E02 0x0da3: name: Thai_khokhuat code point: 0x0E03 0x0da4: name: Thai_khokhwai code point: 0x0E04 0x0da5: name: Thai_khokhon code point: 0x0E05 0x0da6: name: Thai_khorakhang code point: 0x0E06 0x0da7: name: Thai_ngongu code point: 0x0E07 0x0da8: name: Thai_chochan code point: 0x0E08 0x0da9: name: Thai_choching code point: 0x0E09 0x0daa: name: Thai_chochang code point: 0x0E0A 0x0dab: name: Thai_soso code point: 0x0E0B 0x0dac: name: Thai_chochoe code point: 0x0E0C 0x0dad: name: Thai_yoying code point: 0x0E0D 0x0dae: name: Thai_dochada code point: 0x0E0E 0x0daf: name: Thai_topatak code point: 0x0E0F 0x0db0: name: Thai_thothan code point: 0x0E10 0x0db1: name: Thai_thonangmontho code point: 0x0E11 0x0db2: name: Thai_thophuthao code point: 0x0E12 0x0db3: name: Thai_nonen code point: 0x0E13 0x0db4: name: Thai_dodek code point: 0x0E14 0x0db5: name: Thai_totao code point: 0x0E15 0x0db6: name: Thai_thothung code point: 0x0E16 0x0db7: name: Thai_thothahan code point: 0x0E17 0x0db8: name: Thai_thothong code point: 0x0E18 0x0db9: name: Thai_nonu code point: 0x0E19 0x0dba: name: Thai_bobaimai code point: 0x0E1A 0x0dbb: name: Thai_popla code point: 0x0E1B 0x0dbc: name: Thai_phophung code point: 0x0E1C 0x0dbd: name: Thai_fofa code point: 0x0E1D 0x0dbe: name: Thai_phophan code point: 0x0E1E 0x0dbf: name: Thai_fofan code point: 0x0E1F 0x0dc0: name: Thai_phosamphao code point: 0x0E20 0x0dc1: name: Thai_moma code point: 0x0E21 0x0dc2: name: Thai_yoyak code point: 0x0E22 0x0dc3: name: Thai_rorua code point: 0x0E23 0x0dc4: name: Thai_ru code point: 0x0E24 0x0dc5: name: Thai_loling code point: 0x0E25 0x0dc6: name: Thai_lu code point: 0x0E26 0x0dc7: name: Thai_wowaen code point: 0x0E27 0x0dc8: name: Thai_sosala code point: 0x0E28 0x0dc9: name: Thai_sorusi code point: 0x0E29 0x0dca: name: Thai_sosua code point: 0x0E2A 0x0dcb: name: Thai_hohip code point: 0x0E2B 0x0dcc: name: Thai_lochula code point: 0x0E2C 0x0dcd: name: Thai_oang code point: 0x0E2D 0x0dce: name: Thai_honokhuk code point: 0x0E2E 0x0dcf: name: Thai_paiyannoi code point: 0x0E2F 0x0dd0: name: Thai_saraa code point: 0x0E30 0x0dd1: name: Thai_maihanakat code point: 0x0E31 0x0dd2: name: Thai_saraaa code point: 0x0E32 0x0dd3: name: Thai_saraam code point: 0x0E33 0x0dd4: name: Thai_sarai code point: 0x0E34 0x0dd5: name: Thai_saraii code point: 0x0E35 0x0dd6: name: Thai_saraue code point: 0x0E36 0x0dd7: name: Thai_sarauee code point: 0x0E37 0x0dd8: name: Thai_sarau code point: 0x0E38 0x0dd9: name: Thai_sarauu code point: 0x0E39 0x0dda: name: Thai_phinthu code point: 0x0E3A 0x0dde: name: Thai_maihanakat_maitho code point: 0x0E3E 0x0ddf: name: Thai_baht code point: 0x0E3F 0x0de0: name: Thai_sarae code point: 0x0E40 0x0de1: name: Thai_saraae code point: 0x0E41 0x0de2: name: Thai_sarao code point: 0x0E42 0x0de3: name: Thai_saraaimaimuan code point: 0x0E43 0x0de4: name: Thai_saraaimaimalai code point: 0x0E44 0x0de5: name: Thai_lakkhangyao code point: 0x0E45 0x0de6: name: Thai_maiyamok code point: 0x0E46 0x0de7: name: Thai_maitaikhu code point: 0x0E47 0x0de8: name: Thai_maiek code point: 0x0E48 0x0de9: name: Thai_maitho code point: 0x0E49 0x0dea: name: Thai_maitri code point: 0x0E4A 0x0deb: name: Thai_maichattawa code point: 0x0E4B 0x0dec: name: Thai_thanthakhat code point: 0x0E4C 0x0ded: name: Thai_nikhahit code point: 0x0E4D 0x0df0: name: Thai_leksun code point: 0x0E50 0x0df1: name: Thai_leknung code point: 0x0E51 0x0df2: name: Thai_leksong code point: 0x0E52 0x0df3: name: Thai_leksam code point: 0x0E53 0x0df4: name: Thai_leksi code point: 0x0E54 0x0df5: name: Thai_lekha code point: 0x0E55 0x0df6: name: Thai_lekhok code point: 0x0E56 0x0df7: name: Thai_lekchet code point: 0x0E57 0x0df8: name: Thai_lekpaet code point: 0x0E58 0x0df9: name: Thai_lekkao code point: 0x0E59 0x0ea1: name: Hangul_Kiyeog code point: 0x3131 0x0ea2: name: Hangul_SsangKiyeog code point: 0x3132 0x0ea3: name: Hangul_KiyeogSios code point: 0x3133 0x0ea4: name: Hangul_Nieun code point: 0x3134 0x0ea5: name: Hangul_NieunJieuj code point: 0x3135 0x0ea6: name: Hangul_NieunHieuh code point: 0x3136 0x0ea7: name: Hangul_Dikeud code point: 0x3137 0x0ea8: name: Hangul_SsangDikeud code point: 0x3138 0x0ea9: name: Hangul_Rieul code point: 0x3139 0x0eaa: name: Hangul_RieulKiyeog code point: 0x313A 0x0eab: name: Hangul_RieulMieum code point: 0x313B 0x0eac: name: Hangul_RieulPieub code point: 0x313C 0x0ead: name: Hangul_RieulSios code point: 0x313D 0x0eae: name: Hangul_RieulTieut code point: 0x313E 0x0eaf: name: Hangul_RieulPhieuf code point: 0x313F 0x0eb0: name: Hangul_RieulHieuh code point: 0x3140 0x0eb1: name: Hangul_Mieum code point: 0x3141 0x0eb2: name: Hangul_Pieub code point: 0x3142 0x0eb3: name: Hangul_SsangPieub code point: 0x3143 0x0eb4: name: Hangul_PieubSios code point: 0x3144 0x0eb5: name: Hangul_Sios code point: 0x3145 0x0eb6: name: Hangul_SsangSios code point: 0x3146 0x0eb7: name: Hangul_Ieung code point: 0x3147 0x0eb8: name: Hangul_Jieuj code point: 0x3148 0x0eb9: name: Hangul_SsangJieuj code point: 0x3149 0x0eba: name: Hangul_Cieuc code point: 0x314A 0x0ebb: name: Hangul_Khieuq code point: 0x314B 0x0ebc: name: Hangul_Tieut code point: 0x314C 0x0ebd: name: Hangul_Phieuf code point: 0x314D 0x0ebe: name: Hangul_Hieuh code point: 0x314E 0x0ebf: name: Hangul_A code point: 0x314F 0x0ec0: name: Hangul_AE code point: 0x3150 0x0ec1: name: Hangul_YA code point: 0x3151 0x0ec2: name: Hangul_YAE code point: 0x3152 0x0ec3: name: Hangul_EO code point: 0x3153 0x0ec4: name: Hangul_E code point: 0x3154 0x0ec5: name: Hangul_YEO code point: 0x3155 0x0ec6: name: Hangul_YE code point: 0x3156 0x0ec7: name: Hangul_O code point: 0x3157 0x0ec8: name: Hangul_WA code point: 0x3158 0x0ec9: name: Hangul_WAE code point: 0x3159 0x0eca: name: Hangul_OE code point: 0x315A 0x0ecb: name: Hangul_YO code point: 0x315B 0x0ecc: name: Hangul_U code point: 0x315C 0x0ecd: name: Hangul_WEO code point: 0x315D 0x0ece: name: Hangul_WE code point: 0x315E 0x0ecf: name: Hangul_WI code point: 0x315F 0x0ed0: name: Hangul_YU code point: 0x3160 0x0ed1: name: Hangul_EU code point: 0x3161 0x0ed2: name: Hangul_YI code point: 0x3162 0x0ed3: name: Hangul_I code point: 0x3163 0x0ed4: name: Hangul_J_Kiyeog code point: 0x11A8 0x0ed5: name: Hangul_J_SsangKiyeog code point: 0x11A9 0x0ed6: name: Hangul_J_KiyeogSios code point: 0x11AA 0x0ed7: name: Hangul_J_Nieun code point: 0x11AB 0x0ed8: name: Hangul_J_NieunJieuj code point: 0x11AC 0x0ed9: name: Hangul_J_NieunHieuh code point: 0x11AD 0x0eda: name: Hangul_J_Dikeud code point: 0x11AE 0x0edb: name: Hangul_J_Rieul code point: 0x11AF 0x0edc: name: Hangul_J_RieulKiyeog code point: 0x11B0 0x0edd: name: Hangul_J_RieulMieum code point: 0x11B1 0x0ede: name: Hangul_J_RieulPieub code point: 0x11B2 0x0edf: name: Hangul_J_RieulSios code point: 0x11B3 0x0ee0: name: Hangul_J_RieulTieut code point: 0x11B4 0x0ee1: name: Hangul_J_RieulPhieuf code point: 0x11B5 0x0ee2: name: Hangul_J_RieulHieuh code point: 0x11B6 0x0ee3: name: Hangul_J_Mieum code point: 0x11B7 0x0ee4: name: Hangul_J_Pieub code point: 0x11B8 0x0ee5: name: Hangul_J_PieubSios code point: 0x11B9 0x0ee6: name: Hangul_J_Sios code point: 0x11BA 0x0ee7: name: Hangul_J_SsangSios code point: 0x11BB 0x0ee8: name: Hangul_J_Ieung code point: 0x11BC 0x0ee9: name: Hangul_J_Jieuj code point: 0x11BD 0x0eea: name: Hangul_J_Cieuc code point: 0x11BE 0x0eeb: name: Hangul_J_Khieuq code point: 0x11BF 0x0eec: name: Hangul_J_Tieut code point: 0x11C0 0x0eed: name: Hangul_J_Phieuf code point: 0x11C1 0x0eee: name: Hangul_J_Hieuh code point: 0x11C2 0x0eef: name: Hangul_RieulYeorinHieuh code point: 0x316D 0x0ef0: name: Hangul_SunkyeongeumMieum code point: 0x3171 0x0ef1: name: Hangul_SunkyeongeumPieub code point: 0x3178 0x0ef2: name: Hangul_PanSios code point: 0x317F 0x0ef3: name: Hangul_KkogjiDalrinIeung code point: 0x3181 0x0ef4: name: Hangul_SunkyeongeumPhieuf code point: 0x3184 0x0ef5: name: Hangul_YeorinHieuh code point: 0x3186 0x0ef6: name: Hangul_AraeA code point: 0x318D 0x0ef7: name: Hangul_AraeAE code point: 0x318E 0x0ef8: name: Hangul_J_PanSios code point: 0x11EB 0x0ef9: name: Hangul_J_KkogjiDalrinIeung code point: 0x11F0 0x0efa: name: Hangul_J_YeorinHieuh code point: 0x11F9 0x0eff: name: Korean_Won code point: 0x20A9 0x13bc: name: OE code point: 0x0152 lower: 0x13bd # oe 0x13bd: name: oe code point: 0x0153 upper: 0x13bc # OE 0x13be: name: Ydiaeresis code point: 0x0178 lower: 0x00ff # ydiaeresis 0x20ac: name: EuroSign code point: 0x20AC 0xfd01: name: 3270_Duplicate 0xfd02: name: 3270_FieldMark 0xfd03: name: 3270_Right2 0xfd04: name: 3270_Left2 0xfd05: name: 3270_BackTab 0xfd06: name: 3270_EraseEOF 0xfd07: name: 3270_EraseInput 0xfd08: name: 3270_Reset 0xfd09: name: 3270_Quit 0xfd0a: name: 3270_PA1 0xfd0b: name: 3270_PA2 0xfd0c: name: 3270_PA3 0xfd0d: name: 3270_Test 0xfd0e: name: 3270_Attn 0xfd0f: name: 3270_CursorBlink 0xfd10: name: 3270_AltCursor 0xfd11: name: 3270_KeyClick 0xfd12: name: 3270_Jump 0xfd13: name: 3270_Ident 0xfd14: name: 3270_Rule 0xfd15: name: 3270_Copy 0xfd16: name: 3270_Play 0xfd17: name: 3270_Setup 0xfd18: name: 3270_Record 0xfd19: name: 3270_ChangeScreen 0xfd1a: name: 3270_DeleteWord 0xfd1b: name: 3270_ExSelect 0xfd1c: name: 3270_CursorSelect 0xfd1d: name: 3270_PrintScreen 0xfd1e: name: 3270_Enter 0xfe01: name: ISO_Lock 0xfe02: name: ISO_Level2_Latch 0xfe03: name: ISO_Level3_Shift 0xfe04: name: ISO_Level3_Latch 0xfe05: name: ISO_Level3_Lock 0xfe06: name: ISO_Group_Latch 0xfe07: name: ISO_Group_Lock 0xfe08: name: ISO_Next_Group 0xfe09: name: ISO_Next_Group_Lock 0xfe0a: name: ISO_Prev_Group 0xfe0b: name: ISO_Prev_Group_Lock 0xfe0c: name: ISO_First_Group 0xfe0d: name: ISO_First_Group_Lock 0xfe0e: name: ISO_Last_Group 0xfe0f: name: ISO_Last_Group_Lock 0xfe11: name: ISO_Level5_Shift 0xfe12: name: ISO_Level5_Latch 0xfe13: name: ISO_Level5_Lock 0xfe20: name: ISO_Left_Tab 0xfe21: name: ISO_Move_Line_Up 0xfe22: name: ISO_Move_Line_Down 0xfe23: name: ISO_Partial_Line_Up 0xfe24: name: ISO_Partial_Line_Down 0xfe25: name: ISO_Partial_Space_Left 0xfe26: name: ISO_Partial_Space_Right 0xfe27: name: ISO_Set_Margin_Left 0xfe28: name: ISO_Set_Margin_Right 0xfe29: name: ISO_Release_Margin_Left 0xfe2a: name: ISO_Release_Margin_Right 0xfe2b: name: ISO_Release_Both_Margins 0xfe2c: name: ISO_Fast_Cursor_Left 0xfe2d: name: ISO_Fast_Cursor_Right 0xfe2e: name: ISO_Fast_Cursor_Up 0xfe2f: name: ISO_Fast_Cursor_Down 0xfe30: name: ISO_Continuous_Underline 0xfe31: name: ISO_Discontinuous_Underline 0xfe32: name: ISO_Emphasize 0xfe33: name: ISO_Center_Object 0xfe34: name: ISO_Enter 0xfe50: name: dead_grave 0xfe51: name: dead_acute 0xfe52: name: dead_circumflex 0xfe53: name: dead_tilde 0xfe54: name: dead_macron 0xfe55: name: dead_breve 0xfe56: name: dead_abovedot 0xfe57: name: dead_diaeresis 0xfe58: name: dead_abovering 0xfe59: name: dead_doubleacute 0xfe5a: name: dead_caron 0xfe5b: name: dead_cedilla 0xfe5c: name: dead_ogonek 0xfe5d: name: dead_iota 0xfe5e: name: dead_voiced_sound 0xfe5f: name: dead_semivoiced_sound 0xfe60: name: dead_belowdot 0xfe61: name: dead_hook 0xfe62: name: dead_horn 0xfe63: name: dead_stroke 0xfe64: name: dead_abovecomma 0xfe65: name: dead_abovereversedcomma 0xfe66: name: dead_doublegrave 0xfe67: name: dead_belowring 0xfe68: name: dead_belowmacron 0xfe69: name: dead_belowcircumflex 0xfe6a: name: dead_belowtilde 0xfe6b: name: dead_belowbreve 0xfe6c: name: dead_belowdiaeresis 0xfe6d: name: dead_invertedbreve 0xfe6e: name: dead_belowcomma 0xfe6f: name: dead_currency 0xfe70: name: AccessX_Enable 0xfe71: name: AccessX_Feedback_Enable 0xfe72: name: RepeatKeys_Enable 0xfe73: name: SlowKeys_Enable 0xfe74: name: BounceKeys_Enable 0xfe75: name: StickyKeys_Enable 0xfe76: name: MouseKeys_Enable 0xfe77: name: MouseKeys_Accel_Enable 0xfe78: name: Overlay1_Enable 0xfe79: name: Overlay2_Enable 0xfe7a: name: AudibleBell_Enable 0xfe80: name: dead_a 0xfe81: name: dead_A 0xfe82: name: dead_e 0xfe83: name: dead_E 0xfe84: name: dead_i 0xfe85: name: dead_I 0xfe86: name: dead_o 0xfe87: name: dead_O 0xfe88: name: dead_u 0xfe89: name: dead_U 0xfe8a: name: dead_small_schwa 0xfe8b: name: dead_capital_schwa 0xfe8c: name: dead_greek 0xfe8d: name: dead_hamza 0xfe90: name: dead_lowline 0xfe91: name: dead_aboveverticalline 0xfe92: name: dead_belowverticalline 0xfe93: name: dead_longsolidusoverlay 0xfea0: name: ch 0xfea1: name: Ch 0xfea2: name: CH 0xfea3: name: c_h 0xfea4: name: C_h 0xfea5: name: C_H 0xfed0: name: First_Virtual_Screen 0xfed1: name: Prev_Virtual_Screen 0xfed2: name: Next_Virtual_Screen 0xfed4: name: Last_Virtual_Screen 0xfed5: name: Terminate_Server 0xfee0: name: Pointer_Left 0xfee1: name: Pointer_Right 0xfee2: name: Pointer_Up 0xfee3: name: Pointer_Down 0xfee4: name: Pointer_UpLeft 0xfee5: name: Pointer_UpRight 0xfee6: name: Pointer_DownLeft 0xfee7: name: Pointer_DownRight 0xfee8: name: Pointer_Button_Dflt 0xfee9: name: Pointer_Button1 0xfeea: name: Pointer_Button2 0xfeeb: name: Pointer_Button3 0xfeec: name: Pointer_Button4 0xfeed: name: Pointer_Button5 0xfeee: name: Pointer_DblClick_Dflt 0xfeef: name: Pointer_DblClick1 0xfef0: name: Pointer_DblClick2 0xfef1: name: Pointer_DblClick3 0xfef2: name: Pointer_DblClick4 0xfef3: name: Pointer_DblClick5 0xfef4: name: Pointer_Drag_Dflt 0xfef5: name: Pointer_Drag1 0xfef6: name: Pointer_Drag2 0xfef7: name: Pointer_Drag3 0xfef8: name: Pointer_Drag4 0xfef9: name: Pointer_EnableKeys 0xfefa: name: Pointer_Accelerate 0xfefb: name: Pointer_DfltBtnNext 0xfefc: name: Pointer_DfltBtnPrev 0xfefd: name: Pointer_Drag5 0xff08: name: BackSpace code point: 0x0008 0xff09: name: Tab code point: 0x0009 0xff0a: name: Linefeed code point: 0x000A 0xff0b: name: Clear code point: 0x000B 0xff0d: name: Return code point: 0x000D 0xff13: name: Pause 0xff14: name: Scroll_Lock 0xff15: name: Sys_Req 0xff1b: name: Escape code point: 0x001B 0xff20: name: Multi_key 0xff21: name: Kanji 0xff22: name: Muhenkan 0xff23: name: Henkan_Mode 0xff24: name: Romaji 0xff25: name: Hiragana 0xff26: name: Katakana 0xff27: name: Hiragana_Katakana 0xff28: name: Zenkaku 0xff29: name: Hankaku 0xff2a: name: Zenkaku_Hankaku 0xff2b: name: Touroku 0xff2c: name: Massyo 0xff2d: name: Kana_Lock 0xff2e: name: Kana_Shift 0xff2f: name: Eisu_Shift 0xff30: name: Eisu_toggle 0xff31: name: Hangul 0xff32: name: Hangul_Start 0xff33: name: Hangul_End 0xff34: name: Hangul_Hanja 0xff35: name: Hangul_Jamo 0xff36: name: Hangul_Romaja 0xff37: name: Codeinput 0xff38: name: Hangul_Jeonja 0xff39: name: Hangul_Banja 0xff3a: name: Hangul_PreHanja 0xff3b: name: Hangul_PostHanja 0xff3c: name: SingleCandidate 0xff3d: name: MultipleCandidate 0xff3e: name: PreviousCandidate 0xff3f: name: Hangul_Special 0xff50: name: Home 0xff51: name: Left 0xff52: name: Up 0xff53: name: Right 0xff54: name: Down 0xff55: name: Prior 0xff56: name: Next 0xff57: name: End 0xff58: name: Begin 0xff60: name: Select 0xff61: name: Print 0xff62: name: Execute 0xff63: name: Insert 0xff65: name: Undo 0xff66: name: Redo 0xff67: name: Menu 0xff68: name: Find 0xff69: name: Cancel 0xff6a: name: Help 0xff6b: name: Break 0xff7e: name: Mode_switch 0xff7f: name: Num_Lock 0xff80: name: KP_Space code point: 0x0020 0xff89: name: KP_Tab code point: 0x0009 0xff8d: name: KP_Enter code point: 0x000D 0xff91: name: KP_F1 0xff92: name: KP_F2 0xff93: name: KP_F3 0xff94: name: KP_F4 0xff95: name: KP_Home 0xff96: name: KP_Left 0xff97: name: KP_Up 0xff98: name: KP_Right 0xff99: name: KP_Down 0xff9a: name: KP_Prior 0xff9b: name: KP_Next 0xff9c: name: KP_End 0xff9d: name: KP_Begin 0xff9e: name: KP_Insert 0xff9f: name: KP_Delete 0xffaa: name: KP_Multiply code point: 0x002A 0xffab: name: KP_Add code point: 0x002B 0xffac: name: KP_Separator code point: 0x002C 0xffad: name: KP_Subtract code point: 0x002D 0xffae: name: KP_Decimal code point: 0x002E 0xffaf: name: KP_Divide code point: 0x002F 0xffb0: name: KP_0 code point: 0x0030 0xffb1: name: KP_1 code point: 0x0031 0xffb2: name: KP_2 code point: 0x0032 0xffb3: name: KP_3 code point: 0x0033 0xffb4: name: KP_4 code point: 0x0034 0xffb5: name: KP_5 code point: 0x0035 0xffb6: name: KP_6 code point: 0x0036 0xffb7: name: KP_7 code point: 0x0037 0xffb8: name: KP_8 code point: 0x0038 0xffb9: name: KP_9 code point: 0x0039 0xffbd: name: KP_Equal code point: 0x003D 0xffbe: name: F1 0xffbf: name: F2 0xffc0: name: F3 0xffc1: name: F4 0xffc2: name: F5 0xffc3: name: F6 0xffc4: name: F7 0xffc5: name: F8 0xffc6: name: F9 0xffc7: name: F10 0xffc8: name: F11 0xffc9: name: F12 0xffca: name: F13 0xffcb: name: F14 0xffcc: name: F15 0xffcd: name: F16 0xffce: name: F17 0xffcf: name: F18 0xffd0: name: F19 0xffd1: name: F20 0xffd2: name: F21 0xffd3: name: F22 0xffd4: name: F23 0xffd5: name: F24 0xffd6: name: F25 0xffd7: name: F26 0xffd8: name: F27 0xffd9: name: F28 0xffda: name: F29 0xffdb: name: F30 0xffdc: name: F31 0xffdd: name: F32 0xffde: name: F33 0xffdf: name: F34 0xffe0: name: F35 0xffe1: name: Shift_L 0xffe2: name: Shift_R 0xffe3: name: Control_L 0xffe4: name: Control_R 0xffe5: name: Caps_Lock 0xffe6: name: Shift_Lock 0xffe7: name: Meta_L 0xffe8: name: Meta_R 0xffe9: name: Alt_L 0xffea: name: Alt_R 0xffeb: name: Super_L 0xffec: name: Super_R 0xffed: name: Hyper_L 0xffee: name: Hyper_R 0xfff1: name: braille_dot_1 0xfff2: name: braille_dot_2 0xfff3: name: braille_dot_3 0xfff4: name: braille_dot_4 0xfff5: name: braille_dot_5 0xfff6: name: braille_dot_6 0xfff7: name: braille_dot_7 0xfff8: name: braille_dot_8 0xfff9: name: braille_dot_9 0xfffa: name: braille_dot_10 0xffff: name: Delete code point: 0x007F 0xffffff: name: VoidSymbol 0x100012c: name: Ibreve code point: 0x012C lower: 0x100012d # ibreve 0x100012d: name: ibreve code point: 0x012D upper: 0x100012c # Ibreve 0x1000174: name: Wcircumflex code point: 0x0174 lower: 0x1000175 # wcircumflex 0x1000175: name: wcircumflex code point: 0x0175 upper: 0x1000174 # Wcircumflex 0x1000176: name: Ycircumflex code point: 0x0176 lower: 0x1000177 # ycircumflex 0x1000177: name: ycircumflex code point: 0x0177 upper: 0x1000176 # Ycircumflex 0x100018f: name: SCHWA code point: 0x018F lower: 0x1000259 # schwa 0x100019f: name: Obarred code point: 0x019F lower: 0x1000275 # obarred 0x10001a0: name: Ohorn code point: 0x01A0 lower: 0x10001a1 # ohorn 0x10001a1: name: ohorn code point: 0x01A1 upper: 0x10001a0 # Ohorn 0x10001af: name: Uhorn code point: 0x01AF lower: 0x10001b0 # uhorn 0x10001b0: name: uhorn code point: 0x01B0 upper: 0x10001af # Uhorn 0x10001b5: name: Zstroke code point: 0x01B5 lower: 0x10001b6 # zstroke 0x10001b6: name: zstroke code point: 0x01B6 upper: 0x10001b5 # Zstroke 0x10001b7: name: EZH code point: 0x01B7 lower: 0x1000292 # ezh 0x10001d1: name: Ocaron code point: 0x01D1 lower: 0x10001d2 # ocaron 0x10001d2: name: ocaron code point: 0x01D2 upper: 0x10001d1 # Ocaron 0x10001e6: name: Gcaron code point: 0x01E6 lower: 0x10001e7 # gcaron 0x10001e7: name: gcaron code point: 0x01E7 upper: 0x10001e6 # Gcaron 0x1000259: name: schwa code point: 0x0259 upper: 0x100018f # SCHWA 0x1000275: name: obarred code point: 0x0275 upper: 0x100019f # Obarred 0x1000292: name: ezh code point: 0x0292 upper: 0x10001b7 # EZH 0x1000300: name: combining_grave code point: 0x0300 0x1000301: name: combining_acute code point: 0x0301 0x1000303: name: combining_tilde code point: 0x0303 0x1000309: name: combining_hook code point: 0x0309 0x1000323: name: combining_belowdot code point: 0x0323 0x1000492: name: Cyrillic_GHE_bar code point: 0x0492 lower: 0x1000493 # Cyrillic_ghe_bar 0x1000493: name: Cyrillic_ghe_bar code point: 0x0493 upper: 0x1000492 # Cyrillic_GHE_bar 0x1000496: name: Cyrillic_ZHE_descender code point: 0x0496 lower: 0x1000497 # Cyrillic_zhe_descender 0x1000497: name: Cyrillic_zhe_descender code point: 0x0497 upper: 0x1000496 # Cyrillic_ZHE_descender 0x100049a: name: Cyrillic_KA_descender code point: 0x049A lower: 0x100049b # Cyrillic_ka_descender 0x100049b: name: Cyrillic_ka_descender code point: 0x049B upper: 0x100049a # Cyrillic_KA_descender 0x100049c: name: Cyrillic_KA_vertstroke code point: 0x049C lower: 0x100049d # Cyrillic_ka_vertstroke 0x100049d: name: Cyrillic_ka_vertstroke code point: 0x049D upper: 0x100049c # Cyrillic_KA_vertstroke 0x10004a2: name: Cyrillic_EN_descender code point: 0x04A2 lower: 0x10004a3 # Cyrillic_en_descender 0x10004a3: name: Cyrillic_en_descender code point: 0x04A3 upper: 0x10004a2 # Cyrillic_EN_descender 0x10004ae: name: Cyrillic_U_straight code point: 0x04AE lower: 0x10004af # Cyrillic_u_straight 0x10004af: name: Cyrillic_u_straight code point: 0x04AF upper: 0x10004ae # Cyrillic_U_straight 0x10004b0: name: Cyrillic_U_straight_bar code point: 0x04B0 lower: 0x10004b1 # Cyrillic_u_straight_bar 0x10004b1: name: Cyrillic_u_straight_bar code point: 0x04B1 upper: 0x10004b0 # Cyrillic_U_straight_bar 0x10004b2: name: Cyrillic_HA_descender code point: 0x04B2 lower: 0x10004b3 # Cyrillic_ha_descender 0x10004b3: name: Cyrillic_ha_descender code point: 0x04B3 upper: 0x10004b2 # Cyrillic_HA_descender 0x10004b6: name: Cyrillic_CHE_descender code point: 0x04B6 lower: 0x10004b7 # Cyrillic_che_descender 0x10004b7: name: Cyrillic_che_descender code point: 0x04B7 upper: 0x10004b6 # Cyrillic_CHE_descender 0x10004b8: name: Cyrillic_CHE_vertstroke code point: 0x04B8 lower: 0x10004b9 # Cyrillic_che_vertstroke 0x10004b9: name: Cyrillic_che_vertstroke code point: 0x04B9 upper: 0x10004b8 # Cyrillic_CHE_vertstroke 0x10004ba: name: Cyrillic_SHHA code point: 0x04BA lower: 0x10004bb # Cyrillic_shha 0x10004bb: name: Cyrillic_shha code point: 0x04BB upper: 0x10004ba # Cyrillic_SHHA 0x10004d8: name: Cyrillic_SCHWA code point: 0x04D8 lower: 0x10004d9 # Cyrillic_schwa 0x10004d9: name: Cyrillic_schwa code point: 0x04D9 upper: 0x10004d8 # Cyrillic_SCHWA 0x10004e2: name: Cyrillic_I_macron code point: 0x04E2 lower: 0x10004e3 # Cyrillic_i_macron 0x10004e3: name: Cyrillic_i_macron code point: 0x04E3 upper: 0x10004e2 # Cyrillic_I_macron 0x10004e8: name: Cyrillic_O_bar code point: 0x04E8 lower: 0x10004e9 # Cyrillic_o_bar 0x10004e9: name: Cyrillic_o_bar code point: 0x04E9 upper: 0x10004e8 # Cyrillic_O_bar 0x10004ee: name: Cyrillic_U_macron code point: 0x04EE lower: 0x10004ef # Cyrillic_u_macron 0x10004ef: name: Cyrillic_u_macron code point: 0x04EF upper: 0x10004ee # Cyrillic_U_macron 0x1000531: name: Armenian_AYB code point: 0x0531 lower: 0x1000561 # Armenian_ayb 0x1000532: name: Armenian_BEN code point: 0x0532 lower: 0x1000562 # Armenian_ben 0x1000533: name: Armenian_GIM code point: 0x0533 lower: 0x1000563 # Armenian_gim 0x1000534: name: Armenian_DA code point: 0x0534 lower: 0x1000564 # Armenian_da 0x1000535: name: Armenian_YECH code point: 0x0535 lower: 0x1000565 # Armenian_yech 0x1000536: name: Armenian_ZA code point: 0x0536 lower: 0x1000566 # Armenian_za 0x1000537: name: Armenian_E code point: 0x0537 lower: 0x1000567 # Armenian_e 0x1000538: name: Armenian_AT code point: 0x0538 lower: 0x1000568 # Armenian_at 0x1000539: name: Armenian_TO code point: 0x0539 lower: 0x1000569 # Armenian_to 0x100053a: name: Armenian_ZHE code point: 0x053A lower: 0x100056a # Armenian_zhe 0x100053b: name: Armenian_INI code point: 0x053B lower: 0x100056b # Armenian_ini 0x100053c: name: Armenian_LYUN code point: 0x053C lower: 0x100056c # Armenian_lyun 0x100053d: name: Armenian_KHE code point: 0x053D lower: 0x100056d # Armenian_khe 0x100053e: name: Armenian_TSA code point: 0x053E lower: 0x100056e # Armenian_tsa 0x100053f: name: Armenian_KEN code point: 0x053F lower: 0x100056f # Armenian_ken 0x1000540: name: Armenian_HO code point: 0x0540 lower: 0x1000570 # Armenian_ho 0x1000541: name: Armenian_DZA code point: 0x0541 lower: 0x1000571 # Armenian_dza 0x1000542: name: Armenian_GHAT code point: 0x0542 lower: 0x1000572 # Armenian_ghat 0x1000543: name: Armenian_TCHE code point: 0x0543 lower: 0x1000573 # Armenian_tche 0x1000544: name: Armenian_MEN code point: 0x0544 lower: 0x1000574 # Armenian_men 0x1000545: name: Armenian_HI code point: 0x0545 lower: 0x1000575 # Armenian_hi 0x1000546: name: Armenian_NU code point: 0x0546 lower: 0x1000576 # Armenian_nu 0x1000547: name: Armenian_SHA code point: 0x0547 lower: 0x1000577 # Armenian_sha 0x1000548: name: Armenian_VO code point: 0x0548 lower: 0x1000578 # Armenian_vo 0x1000549: name: Armenian_CHA code point: 0x0549 lower: 0x1000579 # Armenian_cha 0x100054a: name: Armenian_PE code point: 0x054A lower: 0x100057a # Armenian_pe 0x100054b: name: Armenian_JE code point: 0x054B lower: 0x100057b # Armenian_je 0x100054c: name: Armenian_RA code point: 0x054C lower: 0x100057c # Armenian_ra 0x100054d: name: Armenian_SE code point: 0x054D lower: 0x100057d # Armenian_se 0x100054e: name: Armenian_VEV code point: 0x054E lower: 0x100057e # Armenian_vev 0x100054f: name: Armenian_TYUN code point: 0x054F lower: 0x100057f # Armenian_tyun 0x1000550: name: Armenian_RE code point: 0x0550 lower: 0x1000580 # Armenian_re 0x1000551: name: Armenian_TSO code point: 0x0551 lower: 0x1000581 # Armenian_tso 0x1000552: name: Armenian_VYUN code point: 0x0552 lower: 0x1000582 # Armenian_vyun 0x1000553: name: Armenian_PYUR code point: 0x0553 lower: 0x1000583 # Armenian_pyur 0x1000554: name: Armenian_KE code point: 0x0554 lower: 0x1000584 # Armenian_ke 0x1000555: name: Armenian_O code point: 0x0555 lower: 0x1000585 # Armenian_o 0x1000556: name: Armenian_FE code point: 0x0556 lower: 0x1000586 # Armenian_fe 0x100055a: name: Armenian_apostrophe code point: 0x055A 0x100055b: name: Armenian_accent code point: 0x055B 0x100055c: name: Armenian_exclam code point: 0x055C 0x100055d: name: Armenian_separation_mark code point: 0x055D 0x100055e: name: Armenian_question code point: 0x055E 0x1000561: name: Armenian_ayb code point: 0x0561 upper: 0x1000531 # Armenian_AYB 0x1000562: name: Armenian_ben code point: 0x0562 upper: 0x1000532 # Armenian_BEN 0x1000563: name: Armenian_gim code point: 0x0563 upper: 0x1000533 # Armenian_GIM 0x1000564: name: Armenian_da code point: 0x0564 upper: 0x1000534 # Armenian_DA 0x1000565: name: Armenian_yech code point: 0x0565 upper: 0x1000535 # Armenian_YECH 0x1000566: name: Armenian_za code point: 0x0566 upper: 0x1000536 # Armenian_ZA 0x1000567: name: Armenian_e code point: 0x0567 upper: 0x1000537 # Armenian_E 0x1000568: name: Armenian_at code point: 0x0568 upper: 0x1000538 # Armenian_AT 0x1000569: name: Armenian_to code point: 0x0569 upper: 0x1000539 # Armenian_TO 0x100056a: name: Armenian_zhe code point: 0x056A upper: 0x100053a # Armenian_ZHE 0x100056b: name: Armenian_ini code point: 0x056B upper: 0x100053b # Armenian_INI 0x100056c: name: Armenian_lyun code point: 0x056C upper: 0x100053c # Armenian_LYUN 0x100056d: name: Armenian_khe code point: 0x056D upper: 0x100053d # Armenian_KHE 0x100056e: name: Armenian_tsa code point: 0x056E upper: 0x100053e # Armenian_TSA 0x100056f: name: Armenian_ken code point: 0x056F upper: 0x100053f # Armenian_KEN 0x1000570: name: Armenian_ho code point: 0x0570 upper: 0x1000540 # Armenian_HO 0x1000571: name: Armenian_dza code point: 0x0571 upper: 0x1000541 # Armenian_DZA 0x1000572: name: Armenian_ghat code point: 0x0572 upper: 0x1000542 # Armenian_GHAT 0x1000573: name: Armenian_tche code point: 0x0573 upper: 0x1000543 # Armenian_TCHE 0x1000574: name: Armenian_men code point: 0x0574 upper: 0x1000544 # Armenian_MEN 0x1000575: name: Armenian_hi code point: 0x0575 upper: 0x1000545 # Armenian_HI 0x1000576: name: Armenian_nu code point: 0x0576 upper: 0x1000546 # Armenian_NU 0x1000577: name: Armenian_sha code point: 0x0577 upper: 0x1000547 # Armenian_SHA 0x1000578: name: Armenian_vo code point: 0x0578 upper: 0x1000548 # Armenian_VO 0x1000579: name: Armenian_cha code point: 0x0579 upper: 0x1000549 # Armenian_CHA 0x100057a: name: Armenian_pe code point: 0x057A upper: 0x100054a # Armenian_PE 0x100057b: name: Armenian_je code point: 0x057B upper: 0x100054b # Armenian_JE 0x100057c: name: Armenian_ra code point: 0x057C upper: 0x100054c # Armenian_RA 0x100057d: name: Armenian_se code point: 0x057D upper: 0x100054d # Armenian_SE 0x100057e: name: Armenian_vev code point: 0x057E upper: 0x100054e # Armenian_VEV 0x100057f: name: Armenian_tyun code point: 0x057F upper: 0x100054f # Armenian_TYUN 0x1000580: name: Armenian_re code point: 0x0580 upper: 0x1000550 # Armenian_RE 0x1000581: name: Armenian_tso code point: 0x0581 upper: 0x1000551 # Armenian_TSO 0x1000582: name: Armenian_vyun code point: 0x0582 upper: 0x1000552 # Armenian_VYUN 0x1000583: name: Armenian_pyur code point: 0x0583 upper: 0x1000553 # Armenian_PYUR 0x1000584: name: Armenian_ke code point: 0x0584 upper: 0x1000554 # Armenian_KE 0x1000585: name: Armenian_o code point: 0x0585 upper: 0x1000555 # Armenian_O 0x1000586: name: Armenian_fe code point: 0x0586 upper: 0x1000556 # Armenian_FE 0x1000587: name: Armenian_ligature_ew code point: 0x0587 0x1000589: name: Armenian_full_stop code point: 0x0589 0x100058a: name: Armenian_hyphen code point: 0x058A 0x1000653: name: Arabic_madda_above code point: 0x0653 0x1000654: name: Arabic_hamza_above code point: 0x0654 0x1000655: name: Arabic_hamza_below code point: 0x0655 0x1000660: name: Arabic_0 code point: 0x0660 0x1000661: name: Arabic_1 code point: 0x0661 0x1000662: name: Arabic_2 code point: 0x0662 0x1000663: name: Arabic_3 code point: 0x0663 0x1000664: name: Arabic_4 code point: 0x0664 0x1000665: name: Arabic_5 code point: 0x0665 0x1000666: name: Arabic_6 code point: 0x0666 0x1000667: name: Arabic_7 code point: 0x0667 0x1000668: name: Arabic_8 code point: 0x0668 0x1000669: name: Arabic_9 code point: 0x0669 0x100066a: name: Arabic_percent code point: 0x066A 0x1000670: name: Arabic_superscript_alef code point: 0x0670 0x1000679: name: Arabic_tteh code point: 0x0679 0x100067e: name: Arabic_peh code point: 0x067E 0x1000686: name: Arabic_tcheh code point: 0x0686 0x1000688: name: Arabic_ddal code point: 0x0688 0x1000691: name: Arabic_rreh code point: 0x0691 0x1000698: name: Arabic_jeh code point: 0x0698 0x10006a4: name: Arabic_veh code point: 0x06A4 0x10006a9: name: Arabic_keheh code point: 0x06A9 0x10006af: name: Arabic_gaf code point: 0x06AF 0x10006ba: name: Arabic_noon_ghunna code point: 0x06BA 0x10006be: name: Arabic_heh_doachashmee code point: 0x06BE 0x10006c1: name: Arabic_heh_goal code point: 0x06C1 0x10006cc: name: Farsi_yeh code point: 0x06CC 0x10006d2: name: Arabic_yeh_baree code point: 0x06D2 0x10006d4: name: Arabic_fullstop code point: 0x06D4 0x10006f0: name: Farsi_0 code point: 0x06F0 0x10006f1: name: Farsi_1 code point: 0x06F1 0x10006f2: name: Farsi_2 code point: 0x06F2 0x10006f3: name: Farsi_3 code point: 0x06F3 0x10006f4: name: Farsi_4 code point: 0x06F4 0x10006f5: name: Farsi_5 code point: 0x06F5 0x10006f6: name: Farsi_6 code point: 0x06F6 0x10006f7: name: Farsi_7 code point: 0x06F7 0x10006f8: name: Farsi_8 code point: 0x06F8 0x10006f9: name: Farsi_9 code point: 0x06F9 0x1000d82: name: Sinh_ng code point: 0x0D82 0x1000d83: name: Sinh_h2 code point: 0x0D83 0x1000d85: name: Sinh_a code point: 0x0D85 0x1000d86: name: Sinh_aa code point: 0x0D86 0x1000d87: name: Sinh_ae code point: 0x0D87 0x1000d88: name: Sinh_aee code point: 0x0D88 0x1000d89: name: Sinh_i code point: 0x0D89 0x1000d8a: name: Sinh_ii code point: 0x0D8A 0x1000d8b: name: Sinh_u code point: 0x0D8B 0x1000d8c: name: Sinh_uu code point: 0x0D8C 0x1000d8d: name: Sinh_ri code point: 0x0D8D 0x1000d8e: name: Sinh_rii code point: 0x0D8E 0x1000d8f: name: Sinh_lu code point: 0x0D8F 0x1000d90: name: Sinh_luu code point: 0x0D90 0x1000d91: name: Sinh_e code point: 0x0D91 0x1000d92: name: Sinh_ee code point: 0x0D92 0x1000d93: name: Sinh_ai code point: 0x0D93 0x1000d94: name: Sinh_o code point: 0x0D94 0x1000d95: name: Sinh_oo code point: 0x0D95 0x1000d96: name: Sinh_au code point: 0x0D96 0x1000d9a: name: Sinh_ka code point: 0x0D9A 0x1000d9b: name: Sinh_kha code point: 0x0D9B 0x1000d9c: name: Sinh_ga code point: 0x0D9C 0x1000d9d: name: Sinh_gha code point: 0x0D9D 0x1000d9e: name: Sinh_ng2 code point: 0x0D9E 0x1000d9f: name: Sinh_nga code point: 0x0D9F 0x1000da0: name: Sinh_ca code point: 0x0DA0 0x1000da1: name: Sinh_cha code point: 0x0DA1 0x1000da2: name: Sinh_ja code point: 0x0DA2 0x1000da3: name: Sinh_jha code point: 0x0DA3 0x1000da4: name: Sinh_nya code point: 0x0DA4 0x1000da5: name: Sinh_jnya code point: 0x0DA5 0x1000da6: name: Sinh_nja code point: 0x0DA6 0x1000da7: name: Sinh_tta code point: 0x0DA7 0x1000da8: name: Sinh_ttha code point: 0x0DA8 0x1000da9: name: Sinh_dda code point: 0x0DA9 0x1000daa: name: Sinh_ddha code point: 0x0DAA 0x1000dab: name: Sinh_nna code point: 0x0DAB 0x1000dac: name: Sinh_ndda code point: 0x0DAC 0x1000dad: name: Sinh_tha code point: 0x0DAD 0x1000dae: name: Sinh_thha code point: 0x0DAE 0x1000daf: name: Sinh_dha code point: 0x0DAF 0x1000db0: name: Sinh_dhha code point: 0x0DB0 0x1000db1: name: Sinh_na code point: 0x0DB1 0x1000db3: name: Sinh_ndha code point: 0x0DB3 0x1000db4: name: Sinh_pa code point: 0x0DB4 0x1000db5: name: Sinh_pha code point: 0x0DB5 0x1000db6: name: Sinh_ba code point: 0x0DB6 0x1000db7: name: Sinh_bha code point: 0x0DB7 0x1000db8: name: Sinh_ma code point: 0x0DB8 0x1000db9: name: Sinh_mba code point: 0x0DB9 0x1000dba: name: Sinh_ya code point: 0x0DBA 0x1000dbb: name: Sinh_ra code point: 0x0DBB 0x1000dbd: name: Sinh_la code point: 0x0DBD 0x1000dc0: name: Sinh_va code point: 0x0DC0 0x1000dc1: name: Sinh_sha code point: 0x0DC1 0x1000dc2: name: Sinh_ssha code point: 0x0DC2 0x1000dc3: name: Sinh_sa code point: 0x0DC3 0x1000dc4: name: Sinh_ha code point: 0x0DC4 0x1000dc5: name: Sinh_lla code point: 0x0DC5 0x1000dc6: name: Sinh_fa code point: 0x0DC6 0x1000dca: name: Sinh_al code point: 0x0DCA 0x1000dcf: name: Sinh_aa2 code point: 0x0DCF 0x1000dd0: name: Sinh_ae2 code point: 0x0DD0 0x1000dd1: name: Sinh_aee2 code point: 0x0DD1 0x1000dd2: name: Sinh_i2 code point: 0x0DD2 0x1000dd3: name: Sinh_ii2 code point: 0x0DD3 0x1000dd4: name: Sinh_u2 code point: 0x0DD4 0x1000dd6: name: Sinh_uu2 code point: 0x0DD6 0x1000dd8: name: Sinh_ru2 code point: 0x0DD8 0x1000dd9: name: Sinh_e2 code point: 0x0DD9 0x1000dda: name: Sinh_ee2 code point: 0x0DDA 0x1000ddb: name: Sinh_ai2 code point: 0x0DDB 0x1000ddc: name: Sinh_o2 code point: 0x0DDC 0x1000ddd: name: Sinh_oo2 code point: 0x0DDD 0x1000dde: name: Sinh_au2 code point: 0x0DDE 0x1000ddf: name: Sinh_lu2 code point: 0x0DDF 0x1000df2: name: Sinh_ruu2 code point: 0x0DF2 0x1000df3: name: Sinh_luu2 code point: 0x0DF3 0x1000df4: name: Sinh_kunddaliya code point: 0x0DF4 0x10010d0: name: Georgian_an code point: 0x10D0 upper: 0x1001c90 # U1C90 0x10010d1: name: Georgian_ban code point: 0x10D1 upper: 0x1001c91 # U1C91 0x10010d2: name: Georgian_gan code point: 0x10D2 upper: 0x1001c92 # U1C92 0x10010d3: name: Georgian_don code point: 0x10D3 upper: 0x1001c93 # U1C93 0x10010d4: name: Georgian_en code point: 0x10D4 upper: 0x1001c94 # U1C94 0x10010d5: name: Georgian_vin code point: 0x10D5 upper: 0x1001c95 # U1C95 0x10010d6: name: Georgian_zen code point: 0x10D6 upper: 0x1001c96 # U1C96 0x10010d7: name: Georgian_tan code point: 0x10D7 upper: 0x1001c97 # U1C97 0x10010d8: name: Georgian_in code point: 0x10D8 upper: 0x1001c98 # U1C98 0x10010d9: name: Georgian_kan code point: 0x10D9 upper: 0x1001c99 # U1C99 0x10010da: name: Georgian_las code point: 0x10DA upper: 0x1001c9a # U1C9A 0x10010db: name: Georgian_man code point: 0x10DB upper: 0x1001c9b # U1C9B 0x10010dc: name: Georgian_nar code point: 0x10DC upper: 0x1001c9c # U1C9C 0x10010dd: name: Georgian_on code point: 0x10DD upper: 0x1001c9d # U1C9D 0x10010de: name: Georgian_par code point: 0x10DE upper: 0x1001c9e # U1C9E 0x10010df: name: Georgian_zhar code point: 0x10DF upper: 0x1001c9f # U1C9F 0x10010e0: name: Georgian_rae code point: 0x10E0 upper: 0x1001ca0 # U1CA0 0x10010e1: name: Georgian_san code point: 0x10E1 upper: 0x1001ca1 # U1CA1 0x10010e2: name: Georgian_tar code point: 0x10E2 upper: 0x1001ca2 # U1CA2 0x10010e3: name: Georgian_un code point: 0x10E3 upper: 0x1001ca3 # U1CA3 0x10010e4: name: Georgian_phar code point: 0x10E4 upper: 0x1001ca4 # U1CA4 0x10010e5: name: Georgian_khar code point: 0x10E5 upper: 0x1001ca5 # U1CA5 0x10010e6: name: Georgian_ghan code point: 0x10E6 upper: 0x1001ca6 # U1CA6 0x10010e7: name: Georgian_qar code point: 0x10E7 upper: 0x1001ca7 # U1CA7 0x10010e8: name: Georgian_shin code point: 0x10E8 upper: 0x1001ca8 # U1CA8 0x10010e9: name: Georgian_chin code point: 0x10E9 upper: 0x1001ca9 # U1CA9 0x10010ea: name: Georgian_can code point: 0x10EA upper: 0x1001caa # U1CAA 0x10010eb: name: Georgian_jil code point: 0x10EB upper: 0x1001cab # U1CAB 0x10010ec: name: Georgian_cil code point: 0x10EC upper: 0x1001cac # U1CAC 0x10010ed: name: Georgian_char code point: 0x10ED upper: 0x1001cad # U1CAD 0x10010ee: name: Georgian_xan code point: 0x10EE upper: 0x1001cae # U1CAE 0x10010ef: name: Georgian_jhan code point: 0x10EF upper: 0x1001caf # U1CAF 0x10010f0: name: Georgian_hae code point: 0x10F0 upper: 0x1001cb0 # U1CB0 0x10010f1: name: Georgian_he code point: 0x10F1 upper: 0x1001cb1 # U1CB1 0x10010f2: name: Georgian_hie code point: 0x10F2 upper: 0x1001cb2 # U1CB2 0x10010f3: name: Georgian_we code point: 0x10F3 upper: 0x1001cb3 # U1CB3 0x10010f4: name: Georgian_har code point: 0x10F4 upper: 0x1001cb4 # U1CB4 0x10010f5: name: Georgian_hoe code point: 0x10F5 upper: 0x1001cb5 # U1CB5 0x10010f6: name: Georgian_fi code point: 0x10F6 upper: 0x1001cb6 # U1CB6 0x1001e02: name: Babovedot code point: 0x1E02 lower: 0x1001e03 # babovedot 0x1001e03: name: babovedot code point: 0x1E03 upper: 0x1001e02 # Babovedot 0x1001e0a: name: Dabovedot code point: 0x1E0A lower: 0x1001e0b # dabovedot 0x1001e0b: name: dabovedot code point: 0x1E0B upper: 0x1001e0a # Dabovedot 0x1001e1e: name: Fabovedot code point: 0x1E1E lower: 0x1001e1f # fabovedot 0x1001e1f: name: fabovedot code point: 0x1E1F upper: 0x1001e1e # Fabovedot 0x1001e36: name: Lbelowdot code point: 0x1E36 lower: 0x1001e37 # lbelowdot 0x1001e37: name: lbelowdot code point: 0x1E37 upper: 0x1001e36 # Lbelowdot 0x1001e40: name: Mabovedot code point: 0x1E40 lower: 0x1001e41 # mabovedot 0x1001e41: name: mabovedot code point: 0x1E41 upper: 0x1001e40 # Mabovedot 0x1001e56: name: Pabovedot code point: 0x1E56 lower: 0x1001e57 # pabovedot 0x1001e57: name: pabovedot code point: 0x1E57 upper: 0x1001e56 # Pabovedot 0x1001e60: name: Sabovedot code point: 0x1E60 lower: 0x1001e61 # sabovedot 0x1001e61: name: sabovedot code point: 0x1E61 upper: 0x1001e60 # Sabovedot 0x1001e6a: name: Tabovedot code point: 0x1E6A lower: 0x1001e6b # tabovedot 0x1001e6b: name: tabovedot code point: 0x1E6B upper: 0x1001e6a # Tabovedot 0x1001e80: name: Wgrave code point: 0x1E80 lower: 0x1001e81 # wgrave 0x1001e81: name: wgrave code point: 0x1E81 upper: 0x1001e80 # Wgrave 0x1001e82: name: Wacute code point: 0x1E82 lower: 0x1001e83 # wacute 0x1001e83: name: wacute code point: 0x1E83 upper: 0x1001e82 # Wacute 0x1001e84: name: Wdiaeresis code point: 0x1E84 lower: 0x1001e85 # wdiaeresis 0x1001e85: name: wdiaeresis code point: 0x1E85 upper: 0x1001e84 # Wdiaeresis 0x1001e8a: name: Xabovedot code point: 0x1E8A lower: 0x1001e8b # xabovedot 0x1001e8b: name: xabovedot code point: 0x1E8B upper: 0x1001e8a # Xabovedot 0x1001ea0: name: Abelowdot code point: 0x1EA0 lower: 0x1001ea1 # abelowdot 0x1001ea1: name: abelowdot code point: 0x1EA1 upper: 0x1001ea0 # Abelowdot 0x1001ea2: name: Ahook code point: 0x1EA2 lower: 0x1001ea3 # ahook 0x1001ea3: name: ahook code point: 0x1EA3 upper: 0x1001ea2 # Ahook 0x1001ea4: name: Acircumflexacute code point: 0x1EA4 lower: 0x1001ea5 # acircumflexacute 0x1001ea5: name: acircumflexacute code point: 0x1EA5 upper: 0x1001ea4 # Acircumflexacute 0x1001ea6: name: Acircumflexgrave code point: 0x1EA6 lower: 0x1001ea7 # acircumflexgrave 0x1001ea7: name: acircumflexgrave code point: 0x1EA7 upper: 0x1001ea6 # Acircumflexgrave 0x1001ea8: name: Acircumflexhook code point: 0x1EA8 lower: 0x1001ea9 # acircumflexhook 0x1001ea9: name: acircumflexhook code point: 0x1EA9 upper: 0x1001ea8 # Acircumflexhook 0x1001eaa: name: Acircumflextilde code point: 0x1EAA lower: 0x1001eab # acircumflextilde 0x1001eab: name: acircumflextilde code point: 0x1EAB upper: 0x1001eaa # Acircumflextilde 0x1001eac: name: Acircumflexbelowdot code point: 0x1EAC lower: 0x1001ead # acircumflexbelowdot 0x1001ead: name: acircumflexbelowdot code point: 0x1EAD upper: 0x1001eac # Acircumflexbelowdot 0x1001eae: name: Abreveacute code point: 0x1EAE lower: 0x1001eaf # abreveacute 0x1001eaf: name: abreveacute code point: 0x1EAF upper: 0x1001eae # Abreveacute 0x1001eb0: name: Abrevegrave code point: 0x1EB0 lower: 0x1001eb1 # abrevegrave 0x1001eb1: name: abrevegrave code point: 0x1EB1 upper: 0x1001eb0 # Abrevegrave 0x1001eb2: name: Abrevehook code point: 0x1EB2 lower: 0x1001eb3 # abrevehook 0x1001eb3: name: abrevehook code point: 0x1EB3 upper: 0x1001eb2 # Abrevehook 0x1001eb4: name: Abrevetilde code point: 0x1EB4 lower: 0x1001eb5 # abrevetilde 0x1001eb5: name: abrevetilde code point: 0x1EB5 upper: 0x1001eb4 # Abrevetilde 0x1001eb6: name: Abrevebelowdot code point: 0x1EB6 lower: 0x1001eb7 # abrevebelowdot 0x1001eb7: name: abrevebelowdot code point: 0x1EB7 upper: 0x1001eb6 # Abrevebelowdot 0x1001eb8: name: Ebelowdot code point: 0x1EB8 lower: 0x1001eb9 # ebelowdot 0x1001eb9: name: ebelowdot code point: 0x1EB9 upper: 0x1001eb8 # Ebelowdot 0x1001eba: name: Ehook code point: 0x1EBA lower: 0x1001ebb # ehook 0x1001ebb: name: ehook code point: 0x1EBB upper: 0x1001eba # Ehook 0x1001ebc: name: Etilde code point: 0x1EBC lower: 0x1001ebd # etilde 0x1001ebd: name: etilde code point: 0x1EBD upper: 0x1001ebc # Etilde 0x1001ebe: name: Ecircumflexacute code point: 0x1EBE lower: 0x1001ebf # ecircumflexacute 0x1001ebf: name: ecircumflexacute code point: 0x1EBF upper: 0x1001ebe # Ecircumflexacute 0x1001ec0: name: Ecircumflexgrave code point: 0x1EC0 lower: 0x1001ec1 # ecircumflexgrave 0x1001ec1: name: ecircumflexgrave code point: 0x1EC1 upper: 0x1001ec0 # Ecircumflexgrave 0x1001ec2: name: Ecircumflexhook code point: 0x1EC2 lower: 0x1001ec3 # ecircumflexhook 0x1001ec3: name: ecircumflexhook code point: 0x1EC3 upper: 0x1001ec2 # Ecircumflexhook 0x1001ec4: name: Ecircumflextilde code point: 0x1EC4 lower: 0x1001ec5 # ecircumflextilde 0x1001ec5: name: ecircumflextilde code point: 0x1EC5 upper: 0x1001ec4 # Ecircumflextilde 0x1001ec6: name: Ecircumflexbelowdot code point: 0x1EC6 lower: 0x1001ec7 # ecircumflexbelowdot 0x1001ec7: name: ecircumflexbelowdot code point: 0x1EC7 upper: 0x1001ec6 # Ecircumflexbelowdot 0x1001ec8: name: Ihook code point: 0x1EC8 lower: 0x1001ec9 # ihook 0x1001ec9: name: ihook code point: 0x1EC9 upper: 0x1001ec8 # Ihook 0x1001eca: name: Ibelowdot code point: 0x1ECA lower: 0x1001ecb # ibelowdot 0x1001ecb: name: ibelowdot code point: 0x1ECB upper: 0x1001eca # Ibelowdot 0x1001ecc: name: Obelowdot code point: 0x1ECC lower: 0x1001ecd # obelowdot 0x1001ecd: name: obelowdot code point: 0x1ECD upper: 0x1001ecc # Obelowdot 0x1001ece: name: Ohook code point: 0x1ECE lower: 0x1001ecf # ohook 0x1001ecf: name: ohook code point: 0x1ECF upper: 0x1001ece # Ohook 0x1001ed0: name: Ocircumflexacute code point: 0x1ED0 lower: 0x1001ed1 # ocircumflexacute 0x1001ed1: name: ocircumflexacute code point: 0x1ED1 upper: 0x1001ed0 # Ocircumflexacute 0x1001ed2: name: Ocircumflexgrave code point: 0x1ED2 lower: 0x1001ed3 # ocircumflexgrave 0x1001ed3: name: ocircumflexgrave code point: 0x1ED3 upper: 0x1001ed2 # Ocircumflexgrave 0x1001ed4: name: Ocircumflexhook code point: 0x1ED4 lower: 0x1001ed5 # ocircumflexhook 0x1001ed5: name: ocircumflexhook code point: 0x1ED5 upper: 0x1001ed4 # Ocircumflexhook 0x1001ed6: name: Ocircumflextilde code point: 0x1ED6 lower: 0x1001ed7 # ocircumflextilde 0x1001ed7: name: ocircumflextilde code point: 0x1ED7 upper: 0x1001ed6 # Ocircumflextilde 0x1001ed8: name: Ocircumflexbelowdot code point: 0x1ED8 lower: 0x1001ed9 # ocircumflexbelowdot 0x1001ed9: name: ocircumflexbelowdot code point: 0x1ED9 upper: 0x1001ed8 # Ocircumflexbelowdot 0x1001eda: name: Ohornacute code point: 0x1EDA lower: 0x1001edb # ohornacute 0x1001edb: name: ohornacute code point: 0x1EDB upper: 0x1001eda # Ohornacute 0x1001edc: name: Ohorngrave code point: 0x1EDC lower: 0x1001edd # ohorngrave 0x1001edd: name: ohorngrave code point: 0x1EDD upper: 0x1001edc # Ohorngrave 0x1001ede: name: Ohornhook code point: 0x1EDE lower: 0x1001edf # ohornhook 0x1001edf: name: ohornhook code point: 0x1EDF upper: 0x1001ede # Ohornhook 0x1001ee0: name: Ohorntilde code point: 0x1EE0 lower: 0x1001ee1 # ohorntilde 0x1001ee1: name: ohorntilde code point: 0x1EE1 upper: 0x1001ee0 # Ohorntilde 0x1001ee2: name: Ohornbelowdot code point: 0x1EE2 lower: 0x1001ee3 # ohornbelowdot 0x1001ee3: name: ohornbelowdot code point: 0x1EE3 upper: 0x1001ee2 # Ohornbelowdot 0x1001ee4: name: Ubelowdot code point: 0x1EE4 lower: 0x1001ee5 # ubelowdot 0x1001ee5: name: ubelowdot code point: 0x1EE5 upper: 0x1001ee4 # Ubelowdot 0x1001ee6: name: Uhook code point: 0x1EE6 lower: 0x1001ee7 # uhook 0x1001ee7: name: uhook code point: 0x1EE7 upper: 0x1001ee6 # Uhook 0x1001ee8: name: Uhornacute code point: 0x1EE8 lower: 0x1001ee9 # uhornacute 0x1001ee9: name: uhornacute code point: 0x1EE9 upper: 0x1001ee8 # Uhornacute 0x1001eea: name: Uhorngrave code point: 0x1EEA lower: 0x1001eeb # uhorngrave 0x1001eeb: name: uhorngrave code point: 0x1EEB upper: 0x1001eea # Uhorngrave 0x1001eec: name: Uhornhook code point: 0x1EEC lower: 0x1001eed # uhornhook 0x1001eed: name: uhornhook code point: 0x1EED upper: 0x1001eec # Uhornhook 0x1001eee: name: Uhorntilde code point: 0x1EEE lower: 0x1001eef # uhorntilde 0x1001eef: name: uhorntilde code point: 0x1EEF upper: 0x1001eee # Uhorntilde 0x1001ef0: name: Uhornbelowdot code point: 0x1EF0 lower: 0x1001ef1 # uhornbelowdot 0x1001ef1: name: uhornbelowdot code point: 0x1EF1 upper: 0x1001ef0 # Uhornbelowdot 0x1001ef2: name: Ygrave code point: 0x1EF2 lower: 0x1001ef3 # ygrave 0x1001ef3: name: ygrave code point: 0x1EF3 upper: 0x1001ef2 # Ygrave 0x1001ef4: name: Ybelowdot code point: 0x1EF4 lower: 0x1001ef5 # ybelowdot 0x1001ef5: name: ybelowdot code point: 0x1EF5 upper: 0x1001ef4 # Ybelowdot 0x1001ef6: name: Yhook code point: 0x1EF6 lower: 0x1001ef7 # yhook 0x1001ef7: name: yhook code point: 0x1EF7 upper: 0x1001ef6 # Yhook 0x1001ef8: name: Ytilde code point: 0x1EF8 lower: 0x1001ef9 # ytilde 0x1001ef9: name: ytilde code point: 0x1EF9 upper: 0x1001ef8 # Ytilde 0x1002070: name: zerosuperior code point: 0x2070 0x1002074: name: foursuperior code point: 0x2074 0x1002075: name: fivesuperior code point: 0x2075 0x1002076: name: sixsuperior code point: 0x2076 0x1002077: name: sevensuperior code point: 0x2077 0x1002078: name: eightsuperior code point: 0x2078 0x1002079: name: ninesuperior code point: 0x2079 0x1002080: name: zerosubscript code point: 0x2080 0x1002081: name: onesubscript code point: 0x2081 0x1002082: name: twosubscript code point: 0x2082 0x1002083: name: threesubscript code point: 0x2083 0x1002084: name: foursubscript code point: 0x2084 0x1002085: name: fivesubscript code point: 0x2085 0x1002086: name: sixsubscript code point: 0x2086 0x1002087: name: sevensubscript code point: 0x2087 0x1002088: name: eightsubscript code point: 0x2088 0x1002089: name: ninesubscript code point: 0x2089 0x10020a0: name: EcuSign code point: 0x20A0 0x10020a1: name: ColonSign code point: 0x20A1 0x10020a2: name: CruzeiroSign code point: 0x20A2 0x10020a3: name: FFrancSign code point: 0x20A3 0x10020a4: name: LiraSign code point: 0x20A4 0x10020a5: name: MillSign code point: 0x20A5 0x10020a6: name: NairaSign code point: 0x20A6 0x10020a7: name: PesetaSign code point: 0x20A7 0x10020a8: name: RupeeSign code point: 0x20A8 0x10020a9: name: WonSign code point: 0x20A9 0x10020aa: name: NewSheqelSign code point: 0x20AA 0x10020ab: name: DongSign code point: 0x20AB 0x1002202: name: partdifferential code point: 0x2202 0x1002205: name: emptyset code point: 0x2205 0x1002208: name: elementof code point: 0x2208 0x1002209: name: notelementof code point: 0x2209 0x100220b: name: containsas code point: 0x220B 0x100221a: name: squareroot code point: 0x221A 0x100221b: name: cuberoot code point: 0x221B 0x100221c: name: fourthroot code point: 0x221C 0x100222c: name: dintegral code point: 0x222C 0x100222d: name: tintegral code point: 0x222D 0x1002235: name: because code point: 0x2235 0x1002247: name: notapproxeq code point: 0x2247 0x1002248: name: approxeq code point: 0x2248 0x1002262: name: notidentical code point: 0x2262 0x1002263: name: stricteq code point: 0x2263 0x1002800: name: braille_blank code point: 0x2800 0x1002801: name: braille_dots_1 code point: 0x2801 0x1002802: name: braille_dots_2 code point: 0x2802 0x1002803: name: braille_dots_12 code point: 0x2803 0x1002804: name: braille_dots_3 code point: 0x2804 0x1002805: name: braille_dots_13 code point: 0x2805 0x1002806: name: braille_dots_23 code point: 0x2806 0x1002807: name: braille_dots_123 code point: 0x2807 0x1002808: name: braille_dots_4 code point: 0x2808 0x1002809: name: braille_dots_14 code point: 0x2809 0x100280a: name: braille_dots_24 code point: 0x280A 0x100280b: name: braille_dots_124 code point: 0x280B 0x100280c: name: braille_dots_34 code point: 0x280C 0x100280d: name: braille_dots_134 code point: 0x280D 0x100280e: name: braille_dots_234 code point: 0x280E 0x100280f: name: braille_dots_1234 code point: 0x280F 0x1002810: name: braille_dots_5 code point: 0x2810 0x1002811: name: braille_dots_15 code point: 0x2811 0x1002812: name: braille_dots_25 code point: 0x2812 0x1002813: name: braille_dots_125 code point: 0x2813 0x1002814: name: braille_dots_35 code point: 0x2814 0x1002815: name: braille_dots_135 code point: 0x2815 0x1002816: name: braille_dots_235 code point: 0x2816 0x1002817: name: braille_dots_1235 code point: 0x2817 0x1002818: name: braille_dots_45 code point: 0x2818 0x1002819: name: braille_dots_145 code point: 0x2819 0x100281a: name: braille_dots_245 code point: 0x281A 0x100281b: name: braille_dots_1245 code point: 0x281B 0x100281c: name: braille_dots_345 code point: 0x281C 0x100281d: name: braille_dots_1345 code point: 0x281D 0x100281e: name: braille_dots_2345 code point: 0x281E 0x100281f: name: braille_dots_12345 code point: 0x281F 0x1002820: name: braille_dots_6 code point: 0x2820 0x1002821: name: braille_dots_16 code point: 0x2821 0x1002822: name: braille_dots_26 code point: 0x2822 0x1002823: name: braille_dots_126 code point: 0x2823 0x1002824: name: braille_dots_36 code point: 0x2824 0x1002825: name: braille_dots_136 code point: 0x2825 0x1002826: name: braille_dots_236 code point: 0x2826 0x1002827: name: braille_dots_1236 code point: 0x2827 0x1002828: name: braille_dots_46 code point: 0x2828 0x1002829: name: braille_dots_146 code point: 0x2829 0x100282a: name: braille_dots_246 code point: 0x282A 0x100282b: name: braille_dots_1246 code point: 0x282B 0x100282c: name: braille_dots_346 code point: 0x282C 0x100282d: name: braille_dots_1346 code point: 0x282D 0x100282e: name: braille_dots_2346 code point: 0x282E 0x100282f: name: braille_dots_12346 code point: 0x282F 0x1002830: name: braille_dots_56 code point: 0x2830 0x1002831: name: braille_dots_156 code point: 0x2831 0x1002832: name: braille_dots_256 code point: 0x2832 0x1002833: name: braille_dots_1256 code point: 0x2833 0x1002834: name: braille_dots_356 code point: 0x2834 0x1002835: name: braille_dots_1356 code point: 0x2835 0x1002836: name: braille_dots_2356 code point: 0x2836 0x1002837: name: braille_dots_12356 code point: 0x2837 0x1002838: name: braille_dots_456 code point: 0x2838 0x1002839: name: braille_dots_1456 code point: 0x2839 0x100283a: name: braille_dots_2456 code point: 0x283A 0x100283b: name: braille_dots_12456 code point: 0x283B 0x100283c: name: braille_dots_3456 code point: 0x283C 0x100283d: name: braille_dots_13456 code point: 0x283D 0x100283e: name: braille_dots_23456 code point: 0x283E 0x100283f: name: braille_dots_123456 code point: 0x283F 0x1002840: name: braille_dots_7 code point: 0x2840 0x1002841: name: braille_dots_17 code point: 0x2841 0x1002842: name: braille_dots_27 code point: 0x2842 0x1002843: name: braille_dots_127 code point: 0x2843 0x1002844: name: braille_dots_37 code point: 0x2844 0x1002845: name: braille_dots_137 code point: 0x2845 0x1002846: name: braille_dots_237 code point: 0x2846 0x1002847: name: braille_dots_1237 code point: 0x2847 0x1002848: name: braille_dots_47 code point: 0x2848 0x1002849: name: braille_dots_147 code point: 0x2849 0x100284a: name: braille_dots_247 code point: 0x284A 0x100284b: name: braille_dots_1247 code point: 0x284B 0x100284c: name: braille_dots_347 code point: 0x284C 0x100284d: name: braille_dots_1347 code point: 0x284D 0x100284e: name: braille_dots_2347 code point: 0x284E 0x100284f: name: braille_dots_12347 code point: 0x284F 0x1002850: name: braille_dots_57 code point: 0x2850 0x1002851: name: braille_dots_157 code point: 0x2851 0x1002852: name: braille_dots_257 code point: 0x2852 0x1002853: name: braille_dots_1257 code point: 0x2853 0x1002854: name: braille_dots_357 code point: 0x2854 0x1002855: name: braille_dots_1357 code point: 0x2855 0x1002856: name: braille_dots_2357 code point: 0x2856 0x1002857: name: braille_dots_12357 code point: 0x2857 0x1002858: name: braille_dots_457 code point: 0x2858 0x1002859: name: braille_dots_1457 code point: 0x2859 0x100285a: name: braille_dots_2457 code point: 0x285A 0x100285b: name: braille_dots_12457 code point: 0x285B 0x100285c: name: braille_dots_3457 code point: 0x285C 0x100285d: name: braille_dots_13457 code point: 0x285D 0x100285e: name: braille_dots_23457 code point: 0x285E 0x100285f: name: braille_dots_123457 code point: 0x285F 0x1002860: name: braille_dots_67 code point: 0x2860 0x1002861: name: braille_dots_167 code point: 0x2861 0x1002862: name: braille_dots_267 code point: 0x2862 0x1002863: name: braille_dots_1267 code point: 0x2863 0x1002864: name: braille_dots_367 code point: 0x2864 0x1002865: name: braille_dots_1367 code point: 0x2865 0x1002866: name: braille_dots_2367 code point: 0x2866 0x1002867: name: braille_dots_12367 code point: 0x2867 0x1002868: name: braille_dots_467 code point: 0x2868 0x1002869: name: braille_dots_1467 code point: 0x2869 0x100286a: name: braille_dots_2467 code point: 0x286A 0x100286b: name: braille_dots_12467 code point: 0x286B 0x100286c: name: braille_dots_3467 code point: 0x286C 0x100286d: name: braille_dots_13467 code point: 0x286D 0x100286e: name: braille_dots_23467 code point: 0x286E 0x100286f: name: braille_dots_123467 code point: 0x286F 0x1002870: name: braille_dots_567 code point: 0x2870 0x1002871: name: braille_dots_1567 code point: 0x2871 0x1002872: name: braille_dots_2567 code point: 0x2872 0x1002873: name: braille_dots_12567 code point: 0x2873 0x1002874: name: braille_dots_3567 code point: 0x2874 0x1002875: name: braille_dots_13567 code point: 0x2875 0x1002876: name: braille_dots_23567 code point: 0x2876 0x1002877: name: braille_dots_123567 code point: 0x2877 0x1002878: name: braille_dots_4567 code point: 0x2878 0x1002879: name: braille_dots_14567 code point: 0x2879 0x100287a: name: braille_dots_24567 code point: 0x287A 0x100287b: name: braille_dots_124567 code point: 0x287B 0x100287c: name: braille_dots_34567 code point: 0x287C 0x100287d: name: braille_dots_134567 code point: 0x287D 0x100287e: name: braille_dots_234567 code point: 0x287E 0x100287f: name: braille_dots_1234567 code point: 0x287F 0x1002880: name: braille_dots_8 code point: 0x2880 0x1002881: name: braille_dots_18 code point: 0x2881 0x1002882: name: braille_dots_28 code point: 0x2882 0x1002883: name: braille_dots_128 code point: 0x2883 0x1002884: name: braille_dots_38 code point: 0x2884 0x1002885: name: braille_dots_138 code point: 0x2885 0x1002886: name: braille_dots_238 code point: 0x2886 0x1002887: name: braille_dots_1238 code point: 0x2887 0x1002888: name: braille_dots_48 code point: 0x2888 0x1002889: name: braille_dots_148 code point: 0x2889 0x100288a: name: braille_dots_248 code point: 0x288A 0x100288b: name: braille_dots_1248 code point: 0x288B 0x100288c: name: braille_dots_348 code point: 0x288C 0x100288d: name: braille_dots_1348 code point: 0x288D 0x100288e: name: braille_dots_2348 code point: 0x288E 0x100288f: name: braille_dots_12348 code point: 0x288F 0x1002890: name: braille_dots_58 code point: 0x2890 0x1002891: name: braille_dots_158 code point: 0x2891 0x1002892: name: braille_dots_258 code point: 0x2892 0x1002893: name: braille_dots_1258 code point: 0x2893 0x1002894: name: braille_dots_358 code point: 0x2894 0x1002895: name: braille_dots_1358 code point: 0x2895 0x1002896: name: braille_dots_2358 code point: 0x2896 0x1002897: name: braille_dots_12358 code point: 0x2897 0x1002898: name: braille_dots_458 code point: 0x2898 0x1002899: name: braille_dots_1458 code point: 0x2899 0x100289a: name: braille_dots_2458 code point: 0x289A 0x100289b: name: braille_dots_12458 code point: 0x289B 0x100289c: name: braille_dots_3458 code point: 0x289C 0x100289d: name: braille_dots_13458 code point: 0x289D 0x100289e: name: braille_dots_23458 code point: 0x289E 0x100289f: name: braille_dots_123458 code point: 0x289F 0x10028a0: name: braille_dots_68 code point: 0x28A0 0x10028a1: name: braille_dots_168 code point: 0x28A1 0x10028a2: name: braille_dots_268 code point: 0x28A2 0x10028a3: name: braille_dots_1268 code point: 0x28A3 0x10028a4: name: braille_dots_368 code point: 0x28A4 0x10028a5: name: braille_dots_1368 code point: 0x28A5 0x10028a6: name: braille_dots_2368 code point: 0x28A6 0x10028a7: name: braille_dots_12368 code point: 0x28A7 0x10028a8: name: braille_dots_468 code point: 0x28A8 0x10028a9: name: braille_dots_1468 code point: 0x28A9 0x10028aa: name: braille_dots_2468 code point: 0x28AA 0x10028ab: name: braille_dots_12468 code point: 0x28AB 0x10028ac: name: braille_dots_3468 code point: 0x28AC 0x10028ad: name: braille_dots_13468 code point: 0x28AD 0x10028ae: name: braille_dots_23468 code point: 0x28AE 0x10028af: name: braille_dots_123468 code point: 0x28AF 0x10028b0: name: braille_dots_568 code point: 0x28B0 0x10028b1: name: braille_dots_1568 code point: 0x28B1 0x10028b2: name: braille_dots_2568 code point: 0x28B2 0x10028b3: name: braille_dots_12568 code point: 0x28B3 0x10028b4: name: braille_dots_3568 code point: 0x28B4 0x10028b5: name: braille_dots_13568 code point: 0x28B5 0x10028b6: name: braille_dots_23568 code point: 0x28B6 0x10028b7: name: braille_dots_123568 code point: 0x28B7 0x10028b8: name: braille_dots_4568 code point: 0x28B8 0x10028b9: name: braille_dots_14568 code point: 0x28B9 0x10028ba: name: braille_dots_24568 code point: 0x28BA 0x10028bb: name: braille_dots_124568 code point: 0x28BB 0x10028bc: name: braille_dots_34568 code point: 0x28BC 0x10028bd: name: braille_dots_134568 code point: 0x28BD 0x10028be: name: braille_dots_234568 code point: 0x28BE 0x10028bf: name: braille_dots_1234568 code point: 0x28BF 0x10028c0: name: braille_dots_78 code point: 0x28C0 0x10028c1: name: braille_dots_178 code point: 0x28C1 0x10028c2: name: braille_dots_278 code point: 0x28C2 0x10028c3: name: braille_dots_1278 code point: 0x28C3 0x10028c4: name: braille_dots_378 code point: 0x28C4 0x10028c5: name: braille_dots_1378 code point: 0x28C5 0x10028c6: name: braille_dots_2378 code point: 0x28C6 0x10028c7: name: braille_dots_12378 code point: 0x28C7 0x10028c8: name: braille_dots_478 code point: 0x28C8 0x10028c9: name: braille_dots_1478 code point: 0x28C9 0x10028ca: name: braille_dots_2478 code point: 0x28CA 0x10028cb: name: braille_dots_12478 code point: 0x28CB 0x10028cc: name: braille_dots_3478 code point: 0x28CC 0x10028cd: name: braille_dots_13478 code point: 0x28CD 0x10028ce: name: braille_dots_23478 code point: 0x28CE 0x10028cf: name: braille_dots_123478 code point: 0x28CF 0x10028d0: name: braille_dots_578 code point: 0x28D0 0x10028d1: name: braille_dots_1578 code point: 0x28D1 0x10028d2: name: braille_dots_2578 code point: 0x28D2 0x10028d3: name: braille_dots_12578 code point: 0x28D3 0x10028d4: name: braille_dots_3578 code point: 0x28D4 0x10028d5: name: braille_dots_13578 code point: 0x28D5 0x10028d6: name: braille_dots_23578 code point: 0x28D6 0x10028d7: name: braille_dots_123578 code point: 0x28D7 0x10028d8: name: braille_dots_4578 code point: 0x28D8 0x10028d9: name: braille_dots_14578 code point: 0x28D9 0x10028da: name: braille_dots_24578 code point: 0x28DA 0x10028db: name: braille_dots_124578 code point: 0x28DB 0x10028dc: name: braille_dots_34578 code point: 0x28DC 0x10028dd: name: braille_dots_134578 code point: 0x28DD 0x10028de: name: braille_dots_234578 code point: 0x28DE 0x10028df: name: braille_dots_1234578 code point: 0x28DF 0x10028e0: name: braille_dots_678 code point: 0x28E0 0x10028e1: name: braille_dots_1678 code point: 0x28E1 0x10028e2: name: braille_dots_2678 code point: 0x28E2 0x10028e3: name: braille_dots_12678 code point: 0x28E3 0x10028e4: name: braille_dots_3678 code point: 0x28E4 0x10028e5: name: braille_dots_13678 code point: 0x28E5 0x10028e6: name: braille_dots_23678 code point: 0x28E6 0x10028e7: name: braille_dots_123678 code point: 0x28E7 0x10028e8: name: braille_dots_4678 code point: 0x28E8 0x10028e9: name: braille_dots_14678 code point: 0x28E9 0x10028ea: name: braille_dots_24678 code point: 0x28EA 0x10028eb: name: braille_dots_124678 code point: 0x28EB 0x10028ec: name: braille_dots_34678 code point: 0x28EC 0x10028ed: name: braille_dots_134678 code point: 0x28ED 0x10028ee: name: braille_dots_234678 code point: 0x28EE 0x10028ef: name: braille_dots_1234678 code point: 0x28EF 0x10028f0: name: braille_dots_5678 code point: 0x28F0 0x10028f1: name: braille_dots_15678 code point: 0x28F1 0x10028f2: name: braille_dots_25678 code point: 0x28F2 0x10028f3: name: braille_dots_125678 code point: 0x28F3 0x10028f4: name: braille_dots_35678 code point: 0x28F4 0x10028f5: name: braille_dots_135678 code point: 0x28F5 0x10028f6: name: braille_dots_235678 code point: 0x28F6 0x10028f7: name: braille_dots_1235678 code point: 0x28F7 0x10028f8: name: braille_dots_45678 code point: 0x28F8 0x10028f9: name: braille_dots_145678 code point: 0x28F9 0x10028fa: name: braille_dots_245678 code point: 0x28FA 0x10028fb: name: braille_dots_1245678 code point: 0x28FB 0x10028fc: name: braille_dots_345678 code point: 0x28FC 0x10028fd: name: braille_dots_1345678 code point: 0x28FD 0x10028fe: name: braille_dots_2345678 code point: 0x28FE 0x10028ff: name: braille_dots_12345678 code point: 0x28FF 0x100000a8: name: hpmute_acute 0x100000a9: name: hpmute_grave 0x100000aa: name: hpmute_asciicircum 0x100000ab: name: hpmute_diaeresis 0x100000ac: name: hpmute_asciitilde 0x100000af: name: hplira 0x100000be: name: hpguilder 0x100000ee: name: hpYdiaeresis 0x100000f6: name: hplongminus 0x100000fc: name: hpblock 0x1000fe22: name: Ddiaeresis 0x1000fe27: name: Dacute_accent 0x1000fe2c: name: Dcedilla_accent 0x1000fe5e: name: Dcircumflex_accent 0x1000fe60: name: Dgrave_accent 0x1000fe7e: name: Dtilde 0x1000feb0: name: Dring_accent 0x1000ff00: name: DRemove 0x1000ff48: name: hpModelock1 0x1000ff49: name: hpModelock2 0x1000ff6c: name: hpReset 0x1000ff6d: name: hpSystem 0x1000ff6e: name: hpUser 0x1000ff6f: name: hpClearLine 0x1000ff70: name: hpInsertLine 0x1000ff71: name: hpDeleteLine 0x1000ff72: name: hpInsertChar 0x1000ff73: name: hpDeleteChar 0x1000ff74: name: hpBackTab 0x1000ff75: name: hpKP_BackTab 0x1000ff76: name: Ext16bit_L 0x1000ff77: name: Ext16bit_R 0x1004ff02: name: osfCopy 0x1004ff03: name: osfCut 0x1004ff04: name: osfPaste 0x1004ff07: name: osfBackTab 0x1004ff08: name: osfBackSpace 0x1004ff0b: name: osfClear 0x1004ff1b: name: osfEscape 0x1004ff31: name: osfAddMode 0x1004ff32: name: osfPrimaryPaste 0x1004ff33: name: osfQuickPaste 0x1004ff40: name: osfPageLeft 0x1004ff41: name: osfPageUp 0x1004ff42: name: osfPageDown 0x1004ff43: name: osfPageRight 0x1004ff44: name: osfActivate 0x1004ff45: name: osfMenuBar 0x1004ff51: name: osfLeft 0x1004ff52: name: osfUp 0x1004ff53: name: osfRight 0x1004ff54: name: osfDown 0x1004ff57: name: osfEndLine 0x1004ff58: name: osfBeginLine 0x1004ff59: name: osfEndData 0x1004ff5a: name: osfBeginData 0x1004ff5b: name: osfPrevMenu 0x1004ff5c: name: osfNextMenu 0x1004ff5d: name: osfPrevField 0x1004ff5e: name: osfNextField 0x1004ff60: name: osfSelect 0x1004ff63: name: osfInsert 0x1004ff65: name: osfUndo 0x1004ff67: name: osfMenu 0x1004ff69: name: osfCancel 0x1004ff6a: name: osfHelp 0x1004ff71: name: osfSelectAll 0x1004ff72: name: osfDeselectAll 0x1004ff73: name: osfReselect 0x1004ff74: name: osfExtend 0x1004ff78: name: osfRestore 0x1004ffff: name: osfDelete 0x1005ff00: name: SunFA_Grave 0x1005ff01: name: SunFA_Circum 0x1005ff02: name: SunFA_Tilde 0x1005ff03: name: SunFA_Acute 0x1005ff04: name: SunFA_Diaeresis 0x1005ff05: name: SunFA_Cedilla 0x1005ff10: name: SunF36 0x1005ff11: name: SunF37 0x1005ff60: name: SunSys_Req 0x1005ff70: name: SunProps 0x1005ff71: name: SunFront 0x1005ff72: name: SunCopy 0x1005ff73: name: SunOpen 0x1005ff74: name: SunPaste 0x1005ff75: name: SunCut 0x1005ff76: name: SunPowerSwitch 0x1005ff77: name: SunAudioLowerVolume 0x1005ff78: name: SunAudioMute 0x1005ff79: name: SunAudioRaiseVolume 0x1005ff7a: name: SunVideoDegauss 0x1005ff7b: name: SunVideoLowerBrightness 0x1005ff7c: name: SunVideoRaiseBrightness 0x1005ff7d: name: SunPowerSwitchShift 0x100810f4: name: XF86BrightnessAuto 0x100810f5: name: XF86DisplayOff 0x10081160: name: XF86OK 0x10081162: name: XF86GoTo 0x10081166: name: XF86Info 0x10081168: name: XF86VendorLogo 0x1008116a: name: XF86MediaSelectProgramGuide 0x1008116e: name: XF86MediaSelectHome 0x10081170: name: XF86MediaLanguageMenu 0x10081171: name: XF86MediaTitleMenu 0x10081175: name: XF86AudioChannelMode 0x10081177: name: XF86AspectRatio 0x10081178: name: XF86MediaSelectPC 0x10081179: name: XF86MediaSelectTV 0x1008117a: name: XF86MediaSelectCable 0x1008117b: name: XF86MediaSelectVCR 0x1008117c: name: XF86MediaSelectVCRPlus 0x1008117d: name: XF86MediaSelectSatellite 0x10081180: name: XF86MediaSelectTape 0x10081181: name: XF86MediaSelectRadio 0x10081182: name: XF86MediaSelectTuner 0x10081183: name: XF86MediaPlayer 0x10081184: name: XF86MediaSelectTeletext 0x10081185: name: XF86DVD 0x10081186: name: XF86MediaSelectAuxiliary 0x10081188: name: XF86Audio 0x10081192: name: XF86ChannelUp 0x10081193: name: XF86ChannelDown 0x10081199: name: XF86MediaPlaySlow 0x1008119b: name: XF86Break 0x1008119d: name: XF86NumberEntryMode 0x100811a0: name: XF86VideoPhone 0x100811a4: name: XF86ZoomReset 0x100811a6: name: XF86Editor 0x100811a8: name: XF86GraphicsEditor 0x100811a9: name: XF86Presentation 0x100811aa: name: XF86Database 0x100811ac: name: XF86Voicemail 0x100811ad: name: XF86Addressbook 0x100811af: name: XF86DisplayToggle 0x100811b0: name: XF86SpellCheck 0x100811b6: name: XF86ContextMenu 0x100811b7: name: XF86MediaRepeat 0x100811b8: name: XF8610ChannelsUp 0x100811b9: name: XF8610ChannelsDown 0x100811ba: name: XF86Images 0x100811bc: name: XF86NotificationCenter 0x100811bd: name: XF86PickupPhone 0x100811be: name: XF86HangupPhone 0x100811d0: name: XF86Fn 0x100811d1: name: XF86Fn_Esc 0x100811e5: name: XF86FnRightShift 0x10081200: name: XF86Numeric0 0x10081201: name: XF86Numeric1 0x10081202: name: XF86Numeric2 0x10081203: name: XF86Numeric3 0x10081204: name: XF86Numeric4 0x10081205: name: XF86Numeric5 0x10081206: name: XF86Numeric6 0x10081207: name: XF86Numeric7 0x10081208: name: XF86Numeric8 0x10081209: name: XF86Numeric9 0x1008120a: name: XF86NumericStar 0x1008120b: name: XF86NumericPound 0x1008120c: name: XF86NumericA 0x1008120d: name: XF86NumericB 0x1008120e: name: XF86NumericC 0x1008120f: name: XF86NumericD 0x10081210: name: XF86CameraFocus 0x10081211: name: XF86WPSButton 0x10081215: name: XF86CameraZoomIn 0x10081216: name: XF86CameraZoomOut 0x10081217: name: XF86CameraUp 0x10081218: name: XF86CameraDown 0x10081219: name: XF86CameraLeft 0x1008121a: name: XF86CameraRight 0x1008121b: name: XF86AttendantOn 0x1008121c: name: XF86AttendantOff 0x1008121d: name: XF86AttendantToggle 0x1008121e: name: XF86LightsToggle 0x10081230: name: XF86ALSToggle 0x10081232: name: XF86RefreshRateToggle 0x10081240: name: XF86Buttonconfig 0x10081241: name: XF86Taskmanager 0x10081242: name: XF86Journal 0x10081243: name: XF86ControlPanel 0x10081244: name: XF86AppSelect 0x10081245: name: XF86Screensaver 0x10081246: name: XF86VoiceCommand 0x10081247: name: XF86Assistant 0x10081249: name: XF86EmojiPicker 0x1008124a: name: XF86Dictate 0x1008124b: name: XF86CameraAccessEnable 0x1008124c: name: XF86CameraAccessDisable 0x1008124d: name: XF86CameraAccessToggle 0x1008124e: name: XF86Accessibility 0x1008124f: name: XF86DoNotDisturb 0x10081250: name: XF86BrightnessMin 0x10081251: name: XF86BrightnessMax 0x10081260: name: XF86KbdInputAssistPrev 0x10081261: name: XF86KbdInputAssistNext 0x10081262: name: XF86KbdInputAssistPrevgroup 0x10081263: name: XF86KbdInputAssistNextgroup 0x10081264: name: XF86KbdInputAssistAccept 0x10081265: name: XF86KbdInputAssistCancel 0x10081266: name: XF86RightUp 0x10081267: name: XF86RightDown 0x10081268: name: XF86LeftUp 0x10081269: name: XF86LeftDown 0x1008126a: name: XF86RootMenu 0x1008126b: name: XF86MediaTopMenu 0x1008126c: name: XF86Numeric11 0x1008126d: name: XF86Numeric12 0x1008126e: name: XF86AudioDesc 0x1008126f: name: XF863DMode 0x10081270: name: XF86NextFavorite 0x10081271: name: XF86StopRecord 0x10081272: name: XF86PauseRecord 0x10081273: name: XF86VOD 0x10081274: name: XF86Unmute 0x10081275: name: XF86FastReverse 0x10081276: name: XF86SlowReverse 0x10081277: name: XF86Data 0x10081278: name: XF86OnScreenKeyboard 0x10081279: name: XF86PrivacyScreenToggle 0x1008127a: name: XF86SelectiveScreenshot 0x1008127b: name: XF86NextElement 0x1008127c: name: XF86PreviousElement 0x1008127d: name: XF86AutopilotEngageToggle 0x1008127e: name: XF86MarkWaypoint 0x1008127f: name: XF86Sos 0x10081280: name: XF86NavChart 0x10081281: name: XF86FishingChart 0x10081282: name: XF86SingleRangeRadar 0x10081283: name: XF86DualRangeRadar 0x10081284: name: XF86RadarOverlay 0x10081285: name: XF86TraditionalSonar 0x10081286: name: XF86ClearvuSonar 0x10081287: name: XF86SidevuSonar 0x10081288: name: XF86NavInfo 0x10081290: name: XF86Macro1 0x10081291: name: XF86Macro2 0x10081292: name: XF86Macro3 0x10081293: name: XF86Macro4 0x10081294: name: XF86Macro5 0x10081295: name: XF86Macro6 0x10081296: name: XF86Macro7 0x10081297: name: XF86Macro8 0x10081298: name: XF86Macro9 0x10081299: name: XF86Macro10 0x1008129a: name: XF86Macro11 0x1008129b: name: XF86Macro12 0x1008129c: name: XF86Macro13 0x1008129d: name: XF86Macro14 0x1008129e: name: XF86Macro15 0x1008129f: name: XF86Macro16 0x100812a0: name: XF86Macro17 0x100812a1: name: XF86Macro18 0x100812a2: name: XF86Macro19 0x100812a3: name: XF86Macro20 0x100812a4: name: XF86Macro21 0x100812a5: name: XF86Macro22 0x100812a6: name: XF86Macro23 0x100812a7: name: XF86Macro24 0x100812a8: name: XF86Macro25 0x100812a9: name: XF86Macro26 0x100812aa: name: XF86Macro27 0x100812ab: name: XF86Macro28 0x100812ac: name: XF86Macro29 0x100812ad: name: XF86Macro30 0x100812b0: name: XF86MacroRecordStart 0x100812b1: name: XF86MacroRecordStop 0x100812b2: name: XF86MacroPresetCycle 0x100812b3: name: XF86MacroPreset1 0x100812b4: name: XF86MacroPreset2 0x100812b5: name: XF86MacroPreset3 0x100812b8: name: XF86KbdLcdMenu1 0x100812b9: name: XF86KbdLcdMenu2 0x100812ba: name: XF86KbdLcdMenu3 0x100812bb: name: XF86KbdLcdMenu4 0x100812bc: name: XF86KbdLcdMenu5 0x1008fe01: name: XF86Switch_VT_1 0x1008fe02: name: XF86Switch_VT_2 0x1008fe03: name: XF86Switch_VT_3 0x1008fe04: name: XF86Switch_VT_4 0x1008fe05: name: XF86Switch_VT_5 0x1008fe06: name: XF86Switch_VT_6 0x1008fe07: name: XF86Switch_VT_7 0x1008fe08: name: XF86Switch_VT_8 0x1008fe09: name: XF86Switch_VT_9 0x1008fe0a: name: XF86Switch_VT_10 0x1008fe0b: name: XF86Switch_VT_11 0x1008fe0c: name: XF86Switch_VT_12 0x1008fe20: name: XF86Ungrab 0x1008fe21: name: XF86ClearGrab 0x1008fe22: name: XF86Next_VMode 0x1008fe23: name: XF86Prev_VMode 0x1008fe24: name: XF86LogWindowTree 0x1008fe25: name: XF86LogGrabInfo 0x1008ff01: name: XF86ModeLock 0x1008ff02: name: XF86MonBrightnessUp 0x1008ff03: name: XF86MonBrightnessDown 0x1008ff04: name: XF86KbdLightOnOff 0x1008ff05: name: XF86KbdBrightnessUp 0x1008ff06: name: XF86KbdBrightnessDown 0x1008ff07: name: XF86MonBrightnessCycle 0x1008ff10: name: XF86Standby 0x1008ff11: name: XF86AudioLowerVolume 0x1008ff12: name: XF86AudioMute 0x1008ff13: name: XF86AudioRaiseVolume 0x1008ff14: name: XF86AudioPlay 0x1008ff15: name: XF86AudioStop 0x1008ff16: name: XF86AudioPrev 0x1008ff17: name: XF86AudioNext 0x1008ff18: name: XF86HomePage 0x1008ff19: name: XF86Mail 0x1008ff1a: name: XF86Start 0x1008ff1b: name: XF86Search 0x1008ff1c: name: XF86AudioRecord 0x1008ff1d: name: XF86Calculator 0x1008ff1e: name: XF86Memo 0x1008ff1f: name: XF86ToDoList 0x1008ff20: name: XF86Calendar 0x1008ff21: name: XF86PowerDown 0x1008ff22: name: XF86ContrastAdjust 0x1008ff23: name: XF86RockerUp 0x1008ff24: name: XF86RockerDown 0x1008ff25: name: XF86RockerEnter 0x1008ff26: name: XF86Back 0x1008ff27: name: XF86Forward 0x1008ff28: name: XF86Stop 0x1008ff29: name: XF86Refresh 0x1008ff2a: name: XF86PowerOff 0x1008ff2b: name: XF86WakeUp 0x1008ff2c: name: XF86Eject 0x1008ff2d: name: XF86ScreenSaver 0x1008ff2e: name: XF86WWW 0x1008ff2f: name: XF86Sleep 0x1008ff30: name: XF86Favorites 0x1008ff31: name: XF86AudioPause 0x1008ff32: name: XF86AudioMedia 0x1008ff33: name: XF86MyComputer 0x1008ff34: name: XF86VendorHome 0x1008ff35: name: XF86LightBulb 0x1008ff36: name: XF86Shop 0x1008ff37: name: XF86History 0x1008ff38: name: XF86OpenURL 0x1008ff39: name: XF86AddFavorite 0x1008ff3a: name: XF86HotLinks 0x1008ff3b: name: XF86BrightnessAdjust 0x1008ff3c: name: XF86Finance 0x1008ff3d: name: XF86Community 0x1008ff3e: name: XF86AudioRewind 0x1008ff3f: name: XF86BackForward 0x1008ff40: name: XF86Launch0 0x1008ff41: name: XF86Launch1 0x1008ff42: name: XF86Launch2 0x1008ff43: name: XF86Launch3 0x1008ff44: name: XF86Launch4 0x1008ff45: name: XF86Launch5 0x1008ff46: name: XF86Launch6 0x1008ff47: name: XF86Launch7 0x1008ff48: name: XF86Launch8 0x1008ff49: name: XF86Launch9 0x1008ff4a: name: XF86LaunchA 0x1008ff4b: name: XF86LaunchB 0x1008ff4c: name: XF86LaunchC 0x1008ff4d: name: XF86LaunchD 0x1008ff4e: name: XF86LaunchE 0x1008ff4f: name: XF86LaunchF 0x1008ff50: name: XF86ApplicationLeft 0x1008ff51: name: XF86ApplicationRight 0x1008ff52: name: XF86Book 0x1008ff53: name: XF86CD 0x1008ff54: name: XF86Calculater 0x1008ff55: name: XF86Clear 0x1008ff56: name: XF86Close 0x1008ff57: name: XF86Copy 0x1008ff58: name: XF86Cut 0x1008ff59: name: XF86Display 0x1008ff5a: name: XF86DOS 0x1008ff5b: name: XF86Documents 0x1008ff5c: name: XF86Excel 0x1008ff5d: name: XF86Explorer 0x1008ff5e: name: XF86Game 0x1008ff5f: name: XF86Go 0x1008ff60: name: XF86iTouch 0x1008ff61: name: XF86LogOff 0x1008ff62: name: XF86Market 0x1008ff63: name: XF86Meeting 0x1008ff65: name: XF86MenuKB 0x1008ff66: name: XF86MenuPB 0x1008ff67: name: XF86MySites 0x1008ff68: name: XF86New 0x1008ff69: name: XF86News 0x1008ff6a: name: XF86OfficeHome 0x1008ff6b: name: XF86Open 0x1008ff6c: name: XF86Option 0x1008ff6d: name: XF86Paste 0x1008ff6e: name: XF86Phone 0x1008ff70: name: XF86Q 0x1008ff72: name: XF86Reply 0x1008ff73: name: XF86Reload 0x1008ff74: name: XF86RotateWindows 0x1008ff75: name: XF86RotationPB 0x1008ff76: name: XF86RotationKB 0x1008ff77: name: XF86Save 0x1008ff78: name: XF86ScrollUp 0x1008ff79: name: XF86ScrollDown 0x1008ff7a: name: XF86ScrollClick 0x1008ff7b: name: XF86Send 0x1008ff7c: name: XF86Spell 0x1008ff7d: name: XF86SplitScreen 0x1008ff7e: name: XF86Support 0x1008ff7f: name: XF86TaskPane 0x1008ff80: name: XF86Terminal 0x1008ff81: name: XF86Tools 0x1008ff82: name: XF86Travel 0x1008ff84: name: XF86UserPB 0x1008ff85: name: XF86User1KB 0x1008ff86: name: XF86User2KB 0x1008ff87: name: XF86Video 0x1008ff88: name: XF86WheelButton 0x1008ff89: name: XF86Word 0x1008ff8a: name: XF86Xfer 0x1008ff8b: name: XF86ZoomIn 0x1008ff8c: name: XF86ZoomOut 0x1008ff8d: name: XF86Away 0x1008ff8e: name: XF86Messenger 0x1008ff8f: name: XF86WebCam 0x1008ff90: name: XF86MailForward 0x1008ff91: name: XF86Pictures 0x1008ff92: name: XF86Music 0x1008ff93: name: XF86Battery 0x1008ff94: name: XF86Bluetooth 0x1008ff95: name: XF86WLAN 0x1008ff96: name: XF86UWB 0x1008ff97: name: XF86AudioForward 0x1008ff98: name: XF86AudioRepeat 0x1008ff99: name: XF86AudioRandomPlay 0x1008ff9a: name: XF86Subtitle 0x1008ff9b: name: XF86AudioCycleTrack 0x1008ff9c: name: XF86CycleAngle 0x1008ff9d: name: XF86FrameBack 0x1008ff9e: name: XF86FrameForward 0x1008ff9f: name: XF86Time 0x1008ffa0: name: XF86Select 0x1008ffa1: name: XF86View 0x1008ffa2: name: XF86TopMenu 0x1008ffa3: name: XF86Red 0x1008ffa4: name: XF86Green 0x1008ffa5: name: XF86Yellow 0x1008ffa6: name: XF86Blue 0x1008ffa7: name: XF86Suspend 0x1008ffa8: name: XF86Hibernate 0x1008ffa9: name: XF86TouchpadToggle 0x1008ffb0: name: XF86TouchpadOn 0x1008ffb1: name: XF86TouchpadOff 0x1008ffb2: name: XF86AudioMicMute 0x1008ffb3: name: XF86Keyboard 0x1008ffb4: name: XF86WWAN 0x1008ffb5: name: XF86RFKill 0x1008ffb6: name: XF86AudioPreset 0x1008ffb7: name: XF86RotationLockToggle 0x1008ffb8: name: XF86FullScreen xkbcommon-libxkbcommon-54ee7ac/doc/000077500000000000000000000000001510033435100174305ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/doc/Doxyfile.in000066400000000000000000000040251510033435100215440ustar00rootroot00000000000000PROJECT_NAME = @PACKAGE_NAME@ PROJECT_NUMBER = @PACKAGE_VERSION@ PROJECT_BRIEF = Library implementing the XKB specification for parsing \ keyboard descriptions and handling keyboard state OUTPUT_DIRECTORY = @OUTPUT_DIRECTORY@ SITEMAP_URL = https://xkbcommon.org/doc/@PACKAGE_VERSION@/ BRIEF_MEMBER_DESC = NO JAVADOC_AUTOBRIEF = YES OPTIMIZE_OUTPUT_FOR_C = YES EXTENSION_MAPPING = no_extension=md \ txt=md SORT_MEMBER_DOCS = NO QUIET = $(DOXYGEN_QUIET) WARN_IF_UNDOCUMENTED = NO WARN_AS_ERROR = $(DOXYGEN_WARN_AS_ERROR) INPUT = @INPUT@ FILE_PATTERNS = *.c \ *.h # These are included in other file but we do not want them as standalone EXCLUDE = LICENSE NEWS.md meson_options.txt RECURSIVE = YES EXAMPLE_PATH = test USE_MDFILE_AS_MAINPAGE = README.md VERBATIM_HEADERS = NO MARKDOWN_ID_STYLE = GITHUB ALPHABETICAL_INDEX = NO IGNORE_PREFIX = xkb_ \ XKB_ \ rxkb_ \ RXKB_ DISABLE_INDEX = NO GENERATE_TREEVIEW = NO FULL_SIDEBAR = NO HTML_EXTRA_STYLESHEET = doc/doxygen-extra.css HTML_COLORSTYLE = TOGGLE TIMESTAMP = NO ENUM_VALUES_PER_LINE = 1 SEARCHENGINE = YES GENERATE_LATEX = NO HAVE_DOT = YES DOTFILE_DIRS = doc/diagrams DOT_IMAGE_FORMAT = svg # Workaround HTML tags not supported by Doxygen ALIASES += figure="@htmlonly[block]
@endhtmlonly" ALIASES += endfigure="@htmlonly[block]
@endhtmlonly" ALIASES += figcaption="@htmlonly[block]
@endhtmlonly" ALIASES += endfigcaption="@htmlonly[block]
@endhtmlonly" ALIASES += rawHtml="@htmlonly@endhtmlonly" xkbcommon-libxkbcommon-54ee7ac/doc/compatibility.md000066400000000000000000000523431510033435100226320ustar00rootroot00000000000000# XKB Compatibility {#xkbcommon-compatibility} @tableofcontents{html:2} This page presents the differences between the [XKB 1.0 specification][XKB Protocol] implemented in current X servers and its implementation in libxkbcommon. xkbcommon has *removed* support for some parts of the specification which introduced unnecessary complications. Many of these removals were in fact not implemented, or half-implemented at best, as well as being totally unused in the standard keyboard layout database, [xkeyboard-config]. On the other hand, xkbcommon has notable additions that lift hard-coded limitation of the [X11 Protocol]. @todo This page is work in progress. It aims to be exhaustive. Please [report any issue](https://github.com/xkbcommon/libxkbcommon/issues). [X11 Protocol]: https://www.x.org/releases/current/doc/xproto/x11protocol.html#Keyboards [XKB Protocol]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config ## Keymap support {#keymap-support} ### General features
Keymap features compatibility table
Feature X11 xkbcommon (v1 format) xkbcommon (v2 format)
Wayland support
❌️ No support Wayland support requires the XWayland compatibility layer.
✅ Full support libxkbcommon is the *reference* implementation of the keyboard keymap handling (parsing/serializing, state) for Wayland.
User configuration
❌️ No support Layout database path is *hard-coded* in xserver. `xkbcomp` enable path configuration, but `setxkbmap` support is incomplete.
✅ Full support Multiple layout database path can be used simultaneously, enabling user-space configuration. See @ref user-configuration "" for further information.
Keycode override with aliases
❌️ No support Keycodes have always priority over aliases.
✅ Full support (since 1.12) Keycodes and aliases share the same namespace.
Extended keycodes
❌️ No support Limited to **8**-bit keycodes.
✅ Full support Support all Linux keycodes using **32**-bit keycodes.
Extended key names
❌️ No support Limited to **4**-character names.
✅ Full support Support any key names of any length.
Extended number of layouts
❌️ No support Limited to **4** layouts.
❌️ No support Limited to **4** layouts.
✅ Full support (since 1.11) Enable up to **32** layouts when using `::XKB_KEYMAP_FORMAT_TEXT_V2`.
Unified modifiers
❌️ No support Clear separation between *real* (i.e. core) and *virtual* modifiers.
✅ Full support Real and virtual modifiers have been collapsed into the same namespace, with a “significant” flag that largely parallels the core/virtual split. Real modifiers are predefined modifiers with fixed encoding and considered merely as a X11 compatibility feature.
Extended modifiers
❌️ No support Limited to up to **8** *independent* modifiers.
✅ Full support Enable up to **32** *independent* modifiers.
Canonical virtual modifiers
❌️ No support Virtual modifiers can only mapped to *real* modifiers (8 bits).
⚠️ Partial support Only if using explicit mapping: e.g. `virtual_modifiers M = 0x100;` if `M` has the modifier index 8.
✅ Full support Virtual modifiers that are not mapped either *explicitly* (using e.g. `virtual_modifiers M = …`) or *implicitly* (using `modifier_map` and `virtualModifier`) [automatically](@ref auto-modifier-encoding) use to their [canonical mapping](@ref canonical-modifier-def).
Multiple keysyms per level
❌️ Parsing only Ignored: fallback to `NoSymbol`.
✅ Full support @todo rationale
Multiple actions per level
❌️ No support Parse error.
⚠️ Parsing & handling, no serialization Currently limited to 1 action for each action type “group” and “modifier”. @since 1.8: Enable multiple actions per level (parsing, serializing & handling). @since 1.11: Serialize to `VoidAction()` for compatibility with X11.
⚠️ Partial support Currently limited to 1 action for each action type “group” and “modifier”. @since 1.11
Geometry @anchor geometry-support ✅ Full support
⚠️ Parsing only Rational: - There were very few geometry definitions available in [xkeyboard-config], and while xkbcommon was responsible for parsing this insanely complex format, it never actually did anything with it. - Hopefully someone will develop a companion library which supports keyboard geometries in a more useful format, e.g. SVG.
Radio groups ✅ Full support
❌️ No support Unused in [xkeyboard-config] layouts.
Overlays ✅ Full support
❌️ No support Unused in [xkeyboard-config] layouts.
[Key behaviors] ✅ Full support
❌️ No support Used to implement radio groups and overlays, and to deal with things like keys that physically lock; Unused in [xkeyboard-config] layouts.
[Indicator behaviors] ✅ Full support
⚠️ Partial support E.g. LED-controls-key behavior (X11’s `IM_LEDDrivesKB` flag enabled) is not supported. The only supported LED behavior is *key-controls-LED*. Unused in [xkeyboard-config] layouts.
[Key behaviors]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Key_Behavior [Indicator behaviors]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#:~:text=IM_LEDDrivesKB ### Key actions {#compatibility-key-actions}
Key actions compatibility table
Type Action X11 xkbcommon (v1 format) xkbcommon (v2 format)
Ineffectual `NoAction()` ✅ Full support ✅ Full support
`VoidAction()` ❌️ No support ⚠️ Parsing only (since 1.10) ✅ Full support (since 1.11)
Modifiers `SetModifiers()`
⚠️ Partial support - `unlockOnPress` parameter is not supported.
⚠️ Partial support - `unlockOnPress` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`.
✅ Full support - `unlockOnPress` parameter (since 1.11). See @ref set-mods-action "its documentation" for further details.
`LatchModifiers()`
⚠️ Partial support - `latchOnPress` parameter is not supported. - `unLockOnPress` parameter is not supported.
⚠️ Partial support - `latchOnPress` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`. - `unLockOnPress` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`.
✅ Full support - `latchOnPress` parameter (since 1.11). See @ref latch-mods-action "its documentation" for further details. - `unLockOnPress` parameter (since 1.11). See @ref latch-mods-action "its documentation" for further details.
`LockModifiers()`
⚠️ Partial support - `unlockOnPress` parameter is not supported.
⚠️ Partial support - `unlockOnPress` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`.
✅ Full support - `unlockOnPress` parameter (since 1.11). See @ref lock-mods-action "its documentation" for further details.
Groups `SetGroup()` ✅ Full support ✅ Full support
`LatchGroup()` ✅ Full support ✅ Full support
`LockGroup()`
⚠️ Partial support - `lockOnRelease` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`.
⚠️ Partial support - `lockOnRelease` parameter is not supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2`.
✅ Full support - `lockOnRelease` (since 1.11). See @ref lock-group-action "its documentation" for further details.
Legacy action `MovePointer()` ✅ Full support ⚠️ Parsing and serializing only, no API support
`PointerButton()` ✅ Full support ⚠️ Parsing and serializing only, no API support
`LockPointerButton()` ✅ Full support ⚠️ Parsing and serializing only, no API support
`SetPointerDefault()` ✅ Full support ⚠️ Parsing and serializing only, no API support
`SetControls()` ✅ Full support ⚠️ Parsing and serializing only, no API support
`LockControls()` ✅ Full support ⚠️ Parsing and serializing only, no API support
`TerminateServer()` ✅ Full support ⚠️ Parsing and serializing only, no API support
`SwitchScreen()` ✅ Full support ⚠️ Parsing and serializing only, no API support
`Private()` ✅ Full support ⚠️ Parsing and serializing only, no API support
Unsupported legacy action `RedirectKey()` ✅ Full support ❌️ Parsing only
`ISOLock()` ✅ Full support ❌️ Parsing only
`DeviceButton()` ✅ Full support ❌️ Parsing only
`LockDeviceButton()` ✅ Full support ❌️ Parsing only
`DeviceValuator()` ✅ Full support ❌️ Parsing only
`MessageAction()` ✅ Full support ❌️ Parsing only
### Keymap text format
Keymap text format compatibility table
Feature X11 (xkbcomp) xkbcommon (v1 format) xkbcommon (v2 format)
Optional keymap components ❌️ All components are mandatory
✅ Full support (since 1.9) Keymap components are no longer mandatory, e.g. a keymap without a `xkb_types` section is legal.
Strong type check ❌️ Weak type check
⚠️ Stronger type check (WIP) Floating-point numbers cannot be used where an integer is expected.
`replace` merge mode in include statements ❌️ No support
✅ Full support (since 1.9) Supported using the prefix `^`, in addition to the standard *merge* `|` and *override* `+` modes.
Keysym as strings ❌️ No support
✅ Full support (since 1.9) Keysyms can be written as their corresponding string, e.g. `udiaeresis` can be written `"ü"`. A string with multiple Unicode code points denotes a list of the corresponding keysyms. An empty string denotes the keysym `NoSymbol`.
Unicode escape sequence ❌️ No support
✅ Full support (since 1.9) `\u{NNNN}`. See @ref keymap-string-literal "string literal" for further information.
Extended `GroupN` constants
❌️ No support Only `Group1`..`Group8` are supported, although the resulting group must be in the range 1..4.
❌️ No support Only `Group1`..`Group4` are supported. Use `::XKB_KEYMAP_FORMAT_TEXT_V2` in order to support further groups.
✅ Full support (since 1.11) The pattern `Group` can be used for any valid group index ``.
Extended `LevelN` constants
❌️ No support Only `Level1`..`Level8` are supported.
✅ Full support (since 1.11) Since 1.11, the pattern `Level` can be used for any valid level index ``. Before 1.11, only `Level1`..`Level8` were supported.
Extended include ❌️ No support
✅ Full support (since 1.11) Enable *absolute* paths and *`%`-expansion*. See @ref keymap-include-percent-expansion "" for further details.
Include predefined maps ✅ Full support
❌️ No support The modern approach is to use [RMLVO].
Exponent syntax for floating-point numbers ✅ Full support
❌️ No support @todo syntax description
`alternate` merge mode ✅ Full support
⚠️ Parsing, fallback to default merge mode `alternate` was used in `xkb_keycodes` type sections and meant that if a new keycode name conflicts with an old one, consider it as a keycode *alias*.
Multiple group definition in symbols section ✅ Full support
⚠️ Supported, except in the [RMLVO] API Since 1.8, only 1 group per symbol section is supported in the [RMLVO] API, to avoid unintuitive results. Multiple groups per symbol section is supported when parsing a [KcCGST] keymap.
### API
API compatibility table
Feature X11 xkbcommon (v1 format) xkbcommon (v2 format)
Full Unicode support ❌️ Incomplete
✅ Full support Full support of simple case mappings for `xkb_keysym_to_lower()` and `xkb_keysym_to_upper()`.
[KcCGST] @anchor KcCGST-support ✅ Full support
⚠️ Partial support (since 1.10) - [KcCGST] is considered an implementation detail, use [RMLVO] instead. - Use `xkb_component_names::xkb_components_names_from_rules()` for debugging purposes.
XKM file format ✅ Full support
❌️ No support Obsolete legacy file format tied to X11 ecosystem.
[KcCGST]: @ref KcCGST-intro [RMLVO]: @ref RMLVO-intro ## Rules support {#rules-support}
API compatibility table
Feature X11 xkbcommon (v1 format) xkbcommon (v2 format)
`! include` statement ❌️ No support
✅ Full support See @ref rules-include-expansion "rules include statement" for further details.
`replace` merge mode ❌️ No support
✅ Full support (since 1.9) Support the merge mode *replace* via the prefix `^`, in addition to the standard *merge* `|` and *override* `+` modes.
Extended layout indices ❌️ No support
✅ Full support (since 1.8) - *single*: matches a single layout; `layout[single]` is the same as without explicit index: `layout`. - *first*: matches the first layout/variant, no matter how many layouts are in the RMLVO configuration. Acts as both `layout` and `layout[1]`. - *later*: matches all but the first layout. This is an index range. Acts as `layout[2]` .. `layout[MAX_LAYOUT]`, where `MAX_LAYOUT` is currently 4. - *any*: matches layout at any position. This is an index range. - the `:all` qualifier: it applies the qualified item to all layouts. See @ref rules-extended-layout-indices "extended layout indices" for further details.
`:all` qualifier ❌️ No support
✅ Full support (since 1.8) the `:all` qualifier: it applies the qualified item to all layouts. See @ref rules-all-qualifier ":all qualifier" for further details.
Extended wild cards ❌️ No support
✅ Full support (since 1.9) - `` matches *empty* value; - `` matches *non-empty* value in *every* context. - `` matches *optionally empty* value in *every* context, contrary to the legacy `*` wild card which does not match empty values for layout and variant. See @ref rules-wildcard-def "rules wildcards" for further information.
## Keyboard layout registry {#registry-support}
Keyboard layout registry support
Feature X11 xkbcommon
XML format ❌️ No support
✅ Full support @todo rationale
## Compose support {#compose-support} Relative to the standard implementation in libX11 (described in the Compose(5) man-page):
Compose support
Feature X11 (`libX11`) xkbcommon
`[!] MODIFIER` syntax ✅ Full support
⚠️ Parsing only Syntax: `[([!] ([~] MODIFIER)...) | None] ` If the modifier list is preceded by `!` it must match exactly. MODIFIER may be one of `Ctrl`, `Lock`, `Caps`, `Shift`, `Alt` or `Meta`. Each modifier may be preceded by a `~` character to indicate that the modifier must not be present. If `None` is specified, no modifier may be present. @todo removal rationale
Modifier keysyms in sequences ✅ Full support
⚠️ Parsed, but key events are ignored Modifiers should not be used in Compose sequences. Use keymap’s features or a keysym with more appropriate semantics.
Interactions with Braille keysyms ✅ Full support
❌️ No support @todo feature description, removal rationale
xkbcommon-libxkbcommon-54ee7ac/doc/cool-uris.yaml000066400000000000000000000037601510033435100222360ustar00rootroot00000000000000# WARNING: This file is autogenerated by: scripts/ensure-stable-doc-urls.py # Do not edit manually. __optional__: - doxygen_crawl.html - meson_options.html annotated.html: [] classes.html: [] debugging.html: [] deprecated.html: [] dir_63ce773eee1f9b680e6e312b48cc99ca.html: [] dir_891596f32582d3133e8915e72908625f.html: [] dir_d44c64559bbebec7f509842c48db8b23.html: [] dir_e68e8157741866f444e17edd764ebbae.html: [] doxygen_crawl.html: [] error-index.html: [] files.html: [] functions.html: [] functions_func.html: [] functions_type.html: [] functions_vars.html: [] globals.html: [] globals_defs.html: [] globals_enum.html: [] globals_eval.html: [] globals_func.html: [] globals_type.html: [] graph_legend.html: [] group__components.html: [] group__compose.html: [] group__context.html: [] group__include-path.html: [] group__keymap.html: [] group__keysyms.html: [] group__logging.html: [] group__registry.html: [] group__state.html: [] group__x11.html: [] index.html: [] keymap-text-format-v1-v2.html: - keymap-text-format-v1.html - md_doc_keymap_format_text_v1.html md_doc_2quick-guide.html: - md_doc_quick_guide.html meson_options.html: [] pages.html: [] rule-file-format.html: - md_doc_rules_format.html structrxkb__context.html: [] structrxkb__iso3166__code.html: [] structrxkb__iso639__code.html: [] structrxkb__layout.html: [] structrxkb__model.html: [] structrxkb__option.html: [] structrxkb__option__group.html: [] structxkb__compose__state.html: [] structxkb__compose__table.html: [] structxkb__compose__table__entry.html: [] structxkb__compose__table__iterator.html: [] structxkb__context.html: [] structxkb__keymap.html: [] structxkb__rule__names.html: [] structxkb__state.html: [] todo.html: [] topics.html: - modules.html user-configuration.html: - md_doc_user_configuration.html xkb-intro.html: [] xkbcommon-compatibility.html: - md_doc_compat.html xkbcommon-compose_8h.html: [] xkbcommon-keysyms_8h.html: [] xkbcommon-names_8h.html: [] xkbcommon-x11_8h.html: [] xkbcommon_8h.html: [] xkbregistry_8h.html: [] xkbcommon-libxkbcommon-54ee7ac/doc/debugging.md000066400000000000000000000057121510033435100217120ustar00rootroot00000000000000# Debugging {#debugging} ## Available tools xkbcommon provides multiple tools for debugging. Please consult the manual pages `man xkbcli` for the complete documentation of each tool. @note These tools may not be installed by default; please ensure you have the `libxkbcommon-tools` package installed. ### Basic tools - Interactive: - `xkbcli interactive` to test your current configuration by detecting the session type. - `xkbcli interactive-x11` to test your current configuration in an *X11* session. - `xkbcli interactive-wayland` to test your current configuration in a *Wayland* session. You may want to use the flag `--enable-compose` if your layouts use dead keys. - `xkbcli how-to-type`: to find the key combinations to type in order to get a specific character or keysym. ### Advanced tools - `xkbcli interactive-evdev`: to test a configuration without affecting your current configuration. This requires access to the `/dev/input/event*` devices, you may need to add your user to the `input` group or run as root. - `xkbcli compile-keymap`: to check the resulting compiled keymap for some configuration. - `xkbcli compile-compose`: to check the resulting Compose file. ## Testing a custom configuration {#testing-custom-config} @note An erroneous XKB configuration may make your keyboard unusable. Therefore it is advised to try custom configurations safely with the following workflow: 1. Create a directory for the custom configuration, e.g. `~/xkb-test`. Note that in order to test it safely, it should *not* be one of the locations that [xkbcommon searches][user-configuration locations]. 2. Create the relevant sub-directories and files, e.g. `~/xkb-test/symbols/my-layout`. 3. Test if your changes *compile* successfully: ```bash xkbcli compile-keymap --include ~/xkb-test --include-defaults --test --layout my-layout ``` @note The order of the `--include*` arguments is important here. If it does not compile, you may add the flag `--verbose` for additional information. 4. Test if it *behaves* correctly. Note that you may need to add your user to the `input` group or run as root. ```bash xkbcli interactive-evdev --include ~/xkb-test --include-defaults --enable-compose --layout my-layout ``` 5. Repeat steps 3 and 4 with your *full* keyboard configuration, i.e. all your model, layouts and options. 6. If everything works as expected, it is time to test in real conditions: - Wayland: , move `~/xkb-test` to one of the [user-configuration locations], restart your session, update the keyboard configuration using your usual UI and enjoy your XKB customization! - X11: Unfortunately Xorg does not support alternative paths, so the next best option is to use the venerable `xkbcomp` tool. ```bash xkbcli compile-keymap --include ~/xkb-test --include-defaults --layout my-layout \ | xkbcomp - $DISPLAY ``` Happy hacking! [user-configuration locations]: @ref user-config-locations xkbcommon-libxkbcommon-54ee7ac/doc/diagrams/000077500000000000000000000000001510033435100212175ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/doc/diagrams/xkb-configuration.dot000066400000000000000000000054171510033435100253670ustar00rootroot00000000000000digraph { node [shape=box] subgraph process { RMLVO [ label=<End user configuration
RMLVO: Rules, Model, Layout, Variant, Options>, penwidth=3, href="@ref RMLVO-intro", ]; RMLVO_resolution [ label=<RMLVO resolution
Determine KcCGST using the specified rules file:
match the given model, layout, variant and options fields>, style=rounded, color=blue, href="@ref rmlvo-resolution" ]; KcCGST [ label=<Layout database configuration
KcCGST: Keycodes, Compat, Geometry, Symbols, Types>, penwidth=3, href="@ref KcCGST-intro" ]; KcCGST_resolution [ label=<KcCGST resolution
Construct the keymap from its components>, style=rounded, color=blue ]; Keymap [ label=<Display server configuration
Complete keymap>, penwidth=3, href="@ref keymap-intro" ]; } database [shape=none, label=<
Layout Database
Rules files
Keycodes files
Compat files
(Geometry files)
Symbols files
Types files
>]; { rank = same; KcCGST; database } edge [ color=blue, arrowhead=normal, style=bold ] { rankdir="TB"; RMLVO -> RMLVO_resolution -> KcCGST -> KcCGST_resolution -> Keymap } edge [ color=dimgrey, arrowhead=vee, style=solid ] RMLVO:e -> database:rules:e [constraint=false]; KcCGST:e -> database:keycodes:w [constraint=false]; KcCGST:e -> database:compat:w [constraint=false]; KcCGST:e -> database:symbols:w [constraint=false]; KcCGST:e -> database:types:w [constraint=false]; database:rules:w -> RMLVO_resolution:e [constraint=false]; database:keycodes:e -> KcCGST_resolution [constraint=false]; database:compat:e -> KcCGST_resolution [constraint=false]; database:symbols:e -> KcCGST_resolution [constraint=false]; database:types:e -> KcCGST_resolution [constraint=false]; } xkbcommon-libxkbcommon-54ee7ac/doc/diagrams/xkb-keymap-components.dot000066400000000000000000000035021510033435100261620ustar00rootroot00000000000000digraph { node [shape=box] database [shape=none, label=<
Layout Database
Rules files
Keycodes files
Compat files
(Geometry files)
Symbols files
Key types files
>]; server [ label=<Server>, style=rounded ]; client [ label=<Client>, style=rounded ]; { rank="same"; database; server; client } database:keycodes -> server [ label=<xkb_keycodes section>, labelhref="@ref the-xkb_keycodes-section" ]; database:compat -> server [ label=<xkb_compat section>, labelhref="@ref the-xkb_compat-section" ]; database:symbols -> server [ label=<xkb_symbols section>, labelhref="@ref the-xkb_symbols-section" ]; database:types -> server [ label=<xkb_types section>, labelhref="@ref the-xkb_types-section" ]; server:n -> database:rules [ label=, labelhref="@ref RMLVO-intro", labeltooltip="Rules, Model, Layout, Variant, Options" ]; server -> client [ label=xkb_keymap block =
xkb_keycodes +
xkb_compat +
xkb_symbols +
xkb_types>, labelhref="@ref the-xkb_keymap-block" ]; } xkbcommon-libxkbcommon-54ee7ac/doc/diagrams/xkb-types-explanation.dot000066400000000000000000000055541510033435100262060ustar00rootroot00000000000000digraph { active_modifiers [ label="Active modifiers", href="@ref xkb_state::xkb_state_mod_index_is_active" ]; modifiers_filter [ shape=box, label=<Filter modifiers
Keep only meaningful modifiers for the key type>, style=rounded ]; filtered_modifiers [label="Filtered modifiers"]; level_match [ shape=box, label=<Lookup modifiers combination
Find the shift level
matching exactly the modifiers,
defaulting to the base level>, style=rounded ]; shift_level [ label="Shift level", href="@ref level-def" ]; consume_modifiers [ shape=box, label=<Consume modifiers>, style=rounded ]; consumed_modifiers [ label="Consumed modifiers", href="@ref consumed-modifiers" ]; symbols_table_lookup [ shape=box, label=<Symbols table lookup>, style=rounded ]; symbols_table [ shape=box, label=<Symbols table>, href="@ref key-symbols-table", penwidth=2 ]; keysym_pre_transformation [ label="Raw keysym" ]; keysyms_transformations [ shape=box, label=<Keysyms transformations>, href="@ref keysym-transformations", style=rounded ]; keysym_post_transformation [ label="Final keysym" ]; key_type [shape=none, label=<
Key type
modifiers
map
preserve
>]; { rank="same"; key_type; filtered_modifiers } { rank="same"; level_match; consume_modifiers } { rank="same"; symbols_table_lookup; symbols_table } active_modifiers -> modifiers_filter; key_type:modifiers -> modifiers_filter // [ // label=<xkb_compat section>, // labelhref="@ref the-xkb_compat-section" // ]; //active_modifiers -> filtered_modifiers [label=""]; modifiers_filter -> filtered_modifiers; filtered_modifiers -> level_match; key_type:map -> level_match; level_match -> shift_level; shift_level -> symbols_table_lookup; symbols_table -> symbols_table_lookup; symbols_table_lookup -> keysym_pre_transformation; keysym_pre_transformation -> keysyms_transformations; keysyms_transformations -> keysym_post_transformation; filtered_modifiers -> consume_modifiers; key_type:preserve -> consume_modifiers; consume_modifiers -> consumed_modifiers; consumed_modifiers -> keysyms_transformations; } xkbcommon-libxkbcommon-54ee7ac/doc/doxygen-extra.css000066400000000000000000000045741510033435100227520ustar00rootroot00000000000000html.dark-mode { --page-background-color: #000410; --fragment-background-color: #192027; } div#top, div.header, div.contents { margin-left: auto; margin-right: auto; max-width: 960px; } .footer { display: none; } dl.todo dt::before { content: '🚧 '; } dl.note dd { margin-inline-start: revert; } span.todo::before { content: '🚧 '; } /* Append external links with a distinctive icon */ a[href^="http://"]::after, a[href^="https://"]::after { content: ""; width: 11px; height: 11px; margin-left: 4px; background-color: var(--page-link-color); /* Bootstrap icon: https://icons.getbootstrap.com/icons/box-arrow-up-right/ */ mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='currentColor' class='bi bi-box-arrow-up-right' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8.636 3.5a.5.5 0 0 0-.5-.5H1.5A1.5 1.5 0 0 0 0 4.5v10A1.5 1.5 0 0 0 1.5 16h10a1.5 1.5 0 0 0 1.5-1.5V7.864a.5.5 0 0 0-1 0V14.5a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h6.636a.5.5 0 0 0 .5-.5z'/%3E%3Cpath fill-rule='evenodd' d='M16 .5a.5.5 0 0 0-.5-.5h-5a.5.5 0 0 0 0 1h3.793L6.146 9.146a.5.5 0 1 0 .708.708L15 1.707V5.5a.5.5 0 0 0 1 0v-5z'/%3E%3C/svg%3E"); mask-position: center; mask-repeat: no-repeat; mask-size: contain; display: inline-block; } code { padding: .2em .4em; margin: 0; vertical-align: baseline; font-family: var(--font-family-monospace); font-size: 85%; white-space: break-spaces; background-color: var(--fragment-background-color); color: var(--fragment-foreground-color); border-radius: 6px; } /******************************************************************************* * Error index ******************************************************************************/ div.example-container { display: flex; flex-flow: row wrap; justify-content: space-between; gap: 1em; } div.example { flex-grow: 1; overflow-x: auto; margin-top: 1em; } div.example-inner { height: 100%; display: flex; flex-direction: column; } div.example-title { padding: 0 0 1em 0; font-style: italic; } div.example table code { /* Allow to keep 2 examples side by side */ font-size: 0.72rem; } div.example figure { margin: 0; } figcaption { font-style: italic; } figcaption p { margin: 0; } xkbcommon-libxkbcommon-54ee7ac/doc/faq.md000066400000000000000000000176311510033435100205310ustar00rootroot00000000000000# Frequently Asked Question (FAQ) {#faq} @tableofcontents{html:2} ## XKB ### What is XKB? See: [Introduction to XKB](./introduction-to-xkb.md). ### What does … mean? See: [terminology](./keymap-text-format-v1-v2.md#terminology). ## Keyboard layout ### Where are the keyboard layouts defined? The xkbcommon project does not provide keyboard layouts. See the [xkeyboard-config] project for further information. ### Why do my keyboard shortcuts not work properly? - 🚧 TODO: Setups with multiple layout and/or non-Latin keyboard layouts may have some issues. - 🚧 TODO: [#420] [#420]: https://github.com/xkbcommon/libxkbcommon/issues/420 ### Why does my key combination to switch between layouts not work? See [this issue][#420]. ### Why does my keyboard layout not work as expected? There could be many reasons!
There is an issue with your keyboard layout database
libxkbcommon may not be able to load your configuration due to an issue (file not found, syntax error, unsupported keysym, etc.). Please use our [debugging tools] to get further information. Note that the xkbcommon project does not provide keyboard layouts. See the [xkeyboard-config] project for further information.
Diacritics/accents do not work
This is most probably an issue with your *Compose* configuration. If you customized it, do not forget to restart your session before trying it. Please use our [debugging tools] with the option `--enable-compose` to get further information.
The application you use does not handle the keyboard properly
Please use our [debugging tools] to ensure that it is specific to the application.
Your keyboard layout uses features not supported by libxkbcommon
See: [compatibility](./compatibility.md)
None of the previous
If none of the previous is conclusive, then this may an issue with libxkbcommon. Please use our [debugging tools] to provide the maximum information (setup, log, expected/got results) and file a [bug report]!
[debugging tools]: ./debugging.md [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config [bug report]: https://github.com/xkbcommon/libxkbcommon/issues/new ### How do I customize my layout? This project does not provide any keyboard layout database: - If you want to modify only your *local* keyboard configuration, see: [User-configuration](./user-configuration.md). - If you want to modify the standard keyboard layout database, please first try it *locally* (see our [debugging tools]) and then file an issue or a merge request at the [xkeyboard-config] project. See also the [keymap text format][text format] documentation for the syntax. [text format]: ./keymap-text-format-v1-v2.md ### How do I test my custom layout without installing it? Use our [debugging tools]. ### How do I swap some keys? 🚧 TODO ### How do I break a latch before triggering another latch or lock? Consider the following use cases: 1. If `Caps_Lock` is on the second level of some key, and `Shift` is latched, pressing the key locks `Caps` while also breaking the `Shift` latch, ensuring that the next character is properly uppercase. 2. On the German E1 layout, `ISO_Level5_Latch` is on the third level of ``. So if a level 3 latch (typically on ``) is used to access it, the level 5 must break the previous level 3 latch, else both latches would be active: the effective level would be 7 instead of the intended 5. Both uses cases can be implemented using the following features: - explicit action; - multiple actions per level; - `VoidAction()`: to break latches. Patch that fixes the first use case: ```diff --- old +++ new key { [ISO_Level2_Latch, Caps_Lock], + [LatchMods(modifiers=Shift,latchToLock,clearLocks), + {VoidAction(), LockMods(modifiers=Lock)}], type=\"ALPHABETIC\" }; ``` ## Legacy X tools replacement ### xmodmap
`xmodmap -pm`
There is no strict equivalent. Since 1.10 `xkbcli compile-keymap` has the option `--modmaps` to print the modifiers maps from a keymap, but it does not print keysyms. In order to get the output for the current keymap, use it with `xkbcli dump-keymap-*`:
Automatic session type detection
```bash xkbcli dump-keymap | xkbcli compile-keymap --modmaps ```
Wayland session
```bash xkbcli dump-keymap-wayland | xkbcli compile-keymap --modmaps ```
X11 session / XWayland
```bash xkbcli dump-keymap-x11 | xkbcli compile-keymap --modmaps ```
`xmodmap -e "…"`
`xmodmap /path/to/file`
No equivalent: `xkbcli` does not modify the display server keymap.
### setxkbmap
`setxkbmap -print -layout …`
Since 1.9 one can use the `--kccgst` option: ```bash xkbcli compile-keymap --kccgst --layout … ```
`setxkbmap -query`
No equivalent: `xkbcli` only query *raw* keymaps and has no access to the original [RMLVO] settings.
`setxkbmap -layout …`
No equivalent: `xkbcli` does not modify the display server keymap. One must use the tools *specific* to each display server in order order to achieve it. If you use a custom layout, please have a look at @ref user-configuration "", which enables making custom layouts *discoverable* by keyboard configuration GUI.
### xkbcomp
`xkbcomp -xkb /path/to/keymap/file -`
```bash xkbcli compile-keymap --keymap /path/to/keymap/file ```
`xkbcomp -xkb $DISPLAY -`
Automatic session type detection
```bash xkbcli dump-keymap ```
Wayland session
```bash xkbcli dump-keymap-wayland ```
X11 session
```bash xkbcli dump-keymap-x11 ```
`xkbcomp - $DISPLAY`
`xkbcomp /path/to/keymap/file $DISPLAY`
No equivalent: `xkbcli` does not modify the display server keymap. One must use the tools *specific* to each display server in order order to achieve it. Please have a look at @ref user-configuration "", which enables making custom layouts *discoverable* by keyboard configuration GUI.
### xev
`xev -event keyboard`
Automatic session type detection
```bash xkbcli interactive ```
Wayland session
```bash xkbcli interactive-wayland ```
X11 session
```bash xkbcli interactive-x11 ```
## API ### Modifiers #### How to get the virtual modifier encoding? The [virtual modifiers] encoding, (also: mappings to [real modifiers] in X11 jargon) is an implementation detail. However, some applications may require it in order to interface with legacy code. ##### libxkbcommon ≥ 1.10 Use the dedicated functions `xkb_keymap::xkb_keymap_mod_get_mask()` (since 1.10) and `xkb_keymap::xkb_keymap_mod_get_mask2()` (since 1.11). ##### libxkbcommon ≤ 1.9 Use the following snippet: ```c // Find the real modifier mapping of the virtual modifier `LevelThree` #include #include const xkb_mod_index_t levelThree_idx = xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_LEVEL3); const xkb_mod_mask_t levelThree = UINT32_C(1) << levelThree_idx; struct xkb_state* state = xkb_state_new(keymap); assert(state); // Please handle error properly xkb_state_update_mask(state, levelThree, 0, 0, 0, 0, 0); const xkb_mod_mask_t levelThree_mapping = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); xkb_state_unref(state); ``` [virtual modifiers]: @ref virtual-modifier-def [real modifiers]: @ref real-modifier-def [RMLVO]: @ref RMLVO-intro #### How to get the keys that trigger modifiers? There is no dedicated API, since the use cases are too diverse or niche. Nevertheless, the following snippet provide a minimal example to achieve it. @snippet "test/modifiers.c" xkb_keymap_mod_get_codes xkbcommon-libxkbcommon-54ee7ac/doc/introduction-to-xkb.md000066400000000000000000000204271510033435100237020ustar00rootroot00000000000000# Introduction to XKB {#xkb-intro} __XKB__ stands for “X Keyboard Extension”. It may refer to either: - a [protocol](@ref xkb-the-protocol) - a [keyboard layout configuration](@ref xkb-the-config) - a [text format](@ref xkb-the-text-format) ## XKB the protocol {#xkb-the-protocol} A __protocol__ for the [X Windows System], that extends the core protocol. _xkbcommon’s_ API is somehow derived from this API, but has been substantially reworked to function as a library instead of a protocol, and exposes fewer internal details to clients. _xkbcommon_ does not depend on a particular windows system; for instance it is used by the [Wayland] protocol. _xkbcommon_ provides the [xkbcommon-x11] module to interface a client with an X server using the XKB protocol. Relevant links: - [The X Window System Protocol][X Protocol] - [The X Keyboard Extension: Protocol Specification][XKB Protocol] - [xkbcommon-x11] ## XKB the keyboard keymap configuration {#xkb-the-config} In order to use [the protocol](@ref xkb-the-protocol), one must first load a [complete keymap]. The keymap usually comes from the OS _layout database_, which is commonly [xkeyboard-config]. Since keymaps may have definitions in common, the database actually stores their basic components separately to allow maximum composability and coherence. A recipe to compose a keymap from its components is called a _keymap configuration_. In XKB, there are several ways to define a keymap configuration. They all aim to produce a [complete keymap]. The following diagram presents an overview. Then they are presented hereinafter, ordered from end user to low-level implementation. @dotfile xkb-configuration "XKB keymap configurations"
RMLVO: Rules, Model, Layout, Variant, Options @anchor RMLVO-intro
This is the configuration the end user usually faces in the UI. The idea is to expose high level concepts such as [keyboard model] and [keyboard layout] to the user, then to _map_ them to the corresponding set of low-level configuration files (see [KcCGST]). @note The RMLVO configurations actually available to the end user is managed by the `xkbregistry`. It uses an XML file, the _registry_, which exposes and documents the set of RMLVO settings in the layout database. The RMLVO configuration consists of the following components:
Rules @anchor config-rules-def
The rules define the _mapping_ from high to low level components. The rules _component_ is the file containing the set of rules to use. It is usually implicit and set by the system. See the [rules file format](doc/rules-format.md) for further details.
Model @anchor config-model-def
The name of the model of the keyboard hardware in use. It may depend on: - The _location_ and _language_ of the user, because languages may require [specific keys][language input keys] for their input methods, such as the _muhenkan_ key on Japanese keyboard and the _Hanja_ key for Korean keyboards. The keyboard are usually classified by the [standard][keyboard standard] it is based on, e.g. ANSI, ISO, JIS, ABNT. - The keyboard _vendor:_ keyboard may have a set of keys that are not standard, or may be specific to an OS.
Layout @anchor config-layout-def
The identifier of the general layout to use. It usually refers to a country or a language.
Variant @anchor config-variant-def
Any minor variants on the general layout. It may be national variants
Options @anchor config-options-def
Set of extra options to customize the standard layouts. Examples: switch modifiers keys, location of the compose key, etc.
KcCGST: Keycodes, Compat, Geometry, Symbols, Types @anchor KcCGST-intro
This is the low-level configuration of XKB and how the files are actually organized in the _layout database_. It is not really intuitive or straight-forward for the uninitiated. @note _xkbcommon_ [does not offer an API for KcCGST](@ref KcCGST-support): it is considered an implementation detail. Instead, [RMLVO] is the preferred way for the user to configure XKB. The KcCGST configuration consists of the following components:
Key codes @anchor config-keycodes-def
A translation of the raw [key codes] from the keyboard into symbolic names.
Compatibility @anchor config-compat-def
A specification of what internal actions modifiers and various special-purpose keys produce.
Geometry @anchor config-geometry-def
A description of the physical layout of a keyboard. @attention This legacy feature is [not supported](@ref geometry-support) by _xkbcommon_.
Key symbols @anchor config-symbols-def
A translation of symbolic key codes into actual [key symbols] \(keysyms).
Key types @anchor config-types-def
Types describe how a pressed key is affected by active [modifiers] such as Shift, Control, Alt, etc.
Complete Keymap @anchor keymap-intro
A complete keymap is a _self-contained_ text file with all the [KcCGST] components needed to configure a keyboard. This is the result of the _resolution_ of the [RMLVO] and [KcCGST] configurations. This is also the format used by X11 and Wayland when prompted to _serialize_ the keymap in use. @note This is a low-level configuration. [RMLVO] is the preferred way for the end user to configure XKB, but some _power users_ may need it for _avanced_ configurations. See the [XKB text format] for further details.
@note Layout making use of dead keys require a [Compose](@ref compose) file. The same applies when if using a [Compose key]. [key codes]: @ref keycode-def [key symbols]: @ref keysym-def [levels]: @ref level-def [modifiers]: @ref modifier-def [RMLVO]: @ref RMLVO-intro [KcCGST]: @ref KcCGST-intro [complete keymap]: @ref keymap-intro [Compose key]: https://en.wikipedia.org/wiki/Compose_key [XKB text format]: @ref xkb-the-text-format ## XKB the text format {#xkb-the-text-format} A __text format__ to define keyboard keymaps. XKB 1.0 is the specification implemented in current X servers. The format supported by _xkbcommon_ is very close to XKB 1.0, with some removals and additions. See the [compatibility] page for further details. The format supported by _xkbcommon_ is documented at the page “[The XKB keymap text format, V1][keymap-text-format-v1-v2]”. The documentation of the _original_ XKB 1.0 format is much more scarce than for the protocol. Some priceless resources are: - [Ivan Pascal's XKB documentation][ivan-pascal] - [An Unreliable Guide to XKB Configuration][unreliable-guide] - [ArchWiki XKB page][arch-wiki] [X Windows System]: https://en.wikipedia.org/wiki/X_Window_System [X Protocol]: https://www.x.org/releases/current/doc/xproto/x11protocol.html#Keyboards [XKB Protocol]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html [xkbcommon-x11]: @ref x11-overview [Wayland]: https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_keyboard [compatibility]: @ref xkbcommon-compatibility [keymap-text-format-v1-v2]: doc/keymap-text-format-v1-v2.md [ivan-pascal]: https://web.archive.org/web/20190724015820/http://pascal.tsu.ru/en/xkb/ [unreliable-guide]: https://www.charvolant.org/doug/xkb/html/index.html [arch-wiki]: https://wiki.archlinux.org/index.php/X_keyboard_extension [keyboard model]: https://en.wikipedia.org/wiki/Computer_keyboard [keymap]: https://en.wikipedia.org/wiki/Keyboard_layout [keyboard layout]: https://en.wikipedia.org/wiki/Keyboard_layout [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config [keyboard standard]: https://en.wikipedia.org/wiki/Computer_keyboard#Types_and_standards [language input keys]: https://en.wikipedia.org/wiki/Language_input_keys @todo Explain how to configure XKB, with examples xkbcommon-libxkbcommon-54ee7ac/doc/introspection.md000066400000000000000000000076661510033435100226710ustar00rootroot00000000000000# Recipes for the introspection tool ## Installation > [!IMPORTANT] > The tools are not yet public, so it is required to build libxkbcommon > locally and run them with e.g. `meson devenv -C …`. The Python dependencies ares: - `PyYAML` - `rdflib` - `tqdm` (optional) ## File paths ### XKB directories > [!TIP] > It is advised to always use *explicit* XKB directories, denoted `XKB_ROOT` in the > following sections. This avoids any conflict with e.g. personal settings. ### Keymap files File paths are resolved following these rules: - `-` corresponds to the standard input `stdin`. - If using `--section`: target section must be present in the file. - Absolute paths: - If using `--resolve` with `--type`: file types must match. - Relative paths: - They are resolved relative to the provided XKB directories, unless *not* using `--resolve` nor `--type`. In the former case: - `--type`: file types must match. ## Resolve paths Answers to: - What file does this include resolves to? - Where is the file corresponding to a registry entry? ```bash # TYPE is a KcCGST component # FILE is a file name # SECTION is a section name in FILE # Default section introspection --include XKB_ROOT --resolve --type TYPE FILE # Specific section introspection --include XKB_ROOT --resolve --type TYPE --section SECTION FILE ``` ## List sections The default output format is YAML, which is handy for analyzing a single file. ```bash # Specific file (absolute path) introspection --include XKB_ROOT --yaml FILE # Specific file (relative path) introspection --include XKB_ROOT --yaml --type TYPE FILE # Specific file (absolute path) and its transitive dependencies introspection --include XKB_ROOT --yaml --recursive FILE # Keymap from RMLVO xkbcli compile-keymap --kccgst --layout LAYOUT | introspection --include XKB_ROOT --yaml # XKB tree introspection-query tree XKB_ROOT -- --yaml --recursive # XKB tree for a specific type introspection-query tree XKB_ROOT --type TYPE -- --yaml --recursive ``` ## Draw graphs This section uses the [DOT] output format. [DOT]: https://en.wikipedia.org/wiki/DOT_(graph_description_language) > [!NOTE] > DOT is a basic format. Usual conversions: > - SVG: `… | dot -Tsvg:cairo > OUTPUT.svg` > - PDF: `… | dot -Tpdf:cairo > OUTPUT.pdf` ```bash # Specific file (absolute path) introspection --include XKB_ROOT --dot FILE # Specific file (relative path) introspection --include XKB_ROOT --dot --type TYPE FILE # Specific file (absolute path) and its transitive dependencies introspection --include XKB_ROOT --dot --recursive FILE # Keymap from RMLVO xkbcli compile-keymap --kccgst --layout LAYOUT | introspection --include XKB_ROOT --dot # XKB tree introspection-query tree XKB_ROOT -- --dot --recursive # XKB tree for a specific type introspection-query tree XKB_ROOT --type TYPE -- --dot --recursive ``` ## Query This section uses the [RDF Turtle] output format and the [SPARQL] query language. [RDF Turtle]: https://www.w3.org/TR/turtle/ [SPARQL]: https://www.w3.org/TR/sparql11-query/ ### List dependencies ```bash # Get data about the XKB directories introspection-query tree XKB_ROOT -- --rdf --recursive > /tmp/tree.ttl # Query direct dependencies introspection-query deps --include XKB_ROOT --type TYPE --file FILE --section SECTION /tmp/tree.ttl # Query all dependencies introspection-query deps --include XKB_ROOT --type TYPE --file FILE --section SECTION --transitive /tmp/tree.ttl ``` ### List unused files/sections ```bash # Get data about the XKB directories introspection-query tree XKB_ROOT -- --rdf --recursive > /tmp/tree.ttl # Analyze a ruleset RULES=evdev; introspection-query rules --rules $RULES --rdf --output /tmp/$RULES.ttl XKB_ROOT # Get the unused items for a specific ruleset RULES=evdev; cat /tmp/tree.ttl /tmp/$RULES.ttl | introspection-query use --include XKB_ROOT --unused - # Get the unused items for multiple rulesets cat /tmp/tree.ttl /tmp/base.ttl /tmp/evdev.ttl | introspection-query use --include XKB_ROOT --unused - ``` xkbcommon-libxkbcommon-54ee7ac/doc/keymap-text-format-v1-v2.md000066400000000000000000004110731510033435100243670ustar00rootroot00000000000000# The XKB keymap text format, V1 and V2 {#keymap-text-format-v1-v2} This document describes the following [keymap] formats, as implemented by libxkbcommon:
`::XKB_KEYMAP_FORMAT_TEXT_V1` @anchor keymap-text-format-v1
The classic XKB text format, as generated by `xkbcomp -xkb`. See @ref xkbcommon-compatibility "" for further information.
`::XKB_KEYMAP_FORMAT_TEXT_V2` @anchor keymap-text-format-v2
Xkbcommon extensions of the classic XKB text format, **incompatible with X11**. See @ref xkbcommon-compatibility "" for further information.
@see For an overview of the role of this format, please see “@ref xkb-the-config ""”. @see For examples of keymaps in this format, please see “@ref user-configuration ""”. For further examples see [xkeyboard-config], the standard database of keyboard configuration data. @note Due to the complexity of the format, this document is still is construction. Some additional resources are: @note - [Ivan Pascal’s XKB documentation][ivan-pascal] - [An Unreliable Guide to XKB Configuration][unreliable-guide] - [The X Keyboard Extension: Protocol Specification][XKB Protocol] - [How to enhance XKB configuration][xkeyboard-config doc] - [ArchWiki XKB page][arch-wiki] [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config [ivan-pascal]: https://web.archive.org/web/20190724015820/http://pascal.tsu.ru/en/xkb/ [unreliable-guide]: https://www.charvolant.org/doug/xkb/html/index.html [XKB Protocol]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html [X11 Core Protocol]: https://www.x.org/releases/current/doc/xproto/x11protocol.html [xkeyboard-config doc]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/master/docs/README.enhancing [arch-wiki]: https://wiki.archlinux.org/index.php/X_keyboard_extension @tableofcontents{html:2} [terminology]: @ref terminology [introduction]: @ref introduction-to-the-xkb-text-format [xkb_keymap]: @ref the-xkb_keymap-block [xkb_keycodes]: @ref the-xkb_keycodes-section [xkb_types]: @ref the-xkb_types-section [xkb_compat]: @ref the-xkb_compat-section [xkb_symbols]: @ref the-xkb_symbols-section [virtual modifier statements]:@ref virtual-modifier-statements [actions]: @ref key-actions ## Terminology {#terminology}
Keycode
Code that identifies a physical key on a keyboard. - _Raw_ keycodes are the numeric identifiers used as input in XKB. They are the result of the low-level processing of the data that keyboards send to a computer. For instance `36` may represent the return key. - _XKB_ keycodes are _symbolic_ names assigned to raw keycodes in order to facilitate their mapping to symbols. For instance the keycode for the return key is the abbreviation `RTRN`. See [xkb_keycodes] for further details.
Symbols
A _keysym_ (short for “key symbol”) is a numeric encoding of a symbol on the cap of a key. Some keysyms have a canonical name for convenience. The complete list of canonical names is defined in `xkbcommon/xkbcommon-keysyms.h`. Common types of keysyms are: - A _character:_ e.g. `a` and `A` for Latin scripts, `alpha` “α” and `ALPHA` “Α” for Greek, etc. - A _dead key:_ e.g. `dead_grave` and `dead_diaeresis`, corresponding respectively to the [grave accent](https://en.wikipedia.org/wiki/Grave_accent) and the [diaeresis](https://en.wikipedia.org/wiki/Diaeresis_%28diacritic%29) diacritics. A [dead key](https://en.wikipedia.org/wiki/Dead_key) is a special kind of key that does not generate a character by itself, but modifies the character generated by the key struck(s) immediately after. - A [modifier]⁠: e.g. `Shift_L`, `Control_R`, `Caps_Lock`. See hereinafter. - A _system action:_ e.g. the arrow `Left`, `Pause`, `Escape`, `F1`. @sa [xkb_symbols] for further details on binding keysyms to keycodes. @sa [Keysym syntax][@ref keysym-syntax]
Modifier
A _modifier key_ is a key that modifies the effect of other keys: e.g. Shift, Control, Caps Lock, etc. The state of a modifier key (active/inactive) is encoded as a _modifier index_ (or modifier bit or simply modifier) and has an associated _unique name_. For historical reasons, modifiers are divided in two categories:
Real modifiers
They are the 8 _predefined_ (AKA *core*, *X11*) modifiers (see [usual modifiers] hereinafter). Real modifiers ensure backward compatibility: indeed they are the actual bits used to compute the [levels][level] and are communicated via the API of xkbcommon. Some are generic modifiers (`Mod[1-5]`) that do not have a conventional interpretation and are the motivation of the introduction of [virtual modifiers].
Virtual modifiers
They are the modifiers that are _not_ predefined.
Each modifier has an associated [encoding][modifier encoding]. In keymaps compatible with X11, the encoding can be interpreted as a _mapping_ to one or multiple _real_ modifier. Real modifiers map to themselves: they are [canonical modifiers][canonical modifier]. See the “@ref modifiers-encoding ""” section for further information. The following table lists the usual modifiers present in the [standard keyboard configuration][xkeyboard-config]. Note that this is provided for information only, as it may change depending on the user configuration. | Modifier | Type | Usual mapping | Comment | | ------------ | ------- | ----------------- | --------------------------- | | `Shift` | Real | `Shift` (fixed) | The usual [Shift] | | `Lock` | Real | `Lock` (fixed) | The usual [Caps Lock][Lock] | | `Control` | Real | `Control` (fixed) | The usual [Control] | | `Mod1` | Real | `Mod1` (fixed) | Not conventional | | `Mod2` | Real | `Mod2` (fixed) | Not conventional | | `Mod3` | Real | `Mod3` (fixed) | Not conventional | | `Mod4` | Real | `Mod4` (fixed) | Not conventional | | `Mod5` | Real | `Mod5` (fixed) | Not conventional | | `Alt` | Virtual | `Mod1` | The usual [Alt] | | `Meta` | Virtual | `Mod1` | The legacy [Meta] key | | `NumLock` | Virtual | `Mod2` | The usual [NumLock] | | `Super` | Virtual | `Mod4` | The usual [Super]/GUI | | `LevelThree` | Virtual | `Mod5` | [ISO][ISO9995] level 3, aka [AltGr] | | `LevelFive` | Virtual | `Mod3` | [ISO][ISO9995] level 5 | [usual modifiers]: @ref usual-modifiers [Shift]: https://en.wikipedia.org/wiki/Control_key [Lock]: https://en.wikipedia.org/wiki/Caps_Lock [Control]: https://en.wikipedia.org/wiki/Control_key [Alt]: https://en.wikipedia.org/wiki/Alt_key [AltGr]: https://en.wikipedia.org/wiki/AltGr_key [NumLock]: https://en.wikipedia.org/wiki/Num_Lock [Meta]: https://en.wikipedia.org/wiki/Meta_key [Super]: https://en.wikipedia.org/wiki/Super_key_(keyboard_button) A modifier key can report its state in one of the following 3 ways:
Depressed
Active while depressed; e.g. the usual Shift.
Latched
Activated when pressed and deactivated after the next non-modifier key press.
Locked
Activated when pressed and deactivated when pressed again; e.g. the usual Caps Lock.
See [modifiers declaration and binding] for further details.
[depressed]: @ref depressed-mod-def [latched]: @ref latched-mod-def [locked]: @ref locked-mod-def
Shift Level
A key may produce different results depending of the active modifiers: e.g. for a Latin script, pressing the key A produces “a” and holding Shift while pressing A produces “A”. This various results are organized in an ordered list; the _index_ of each entry is called a shift level or simply level. By convention the lowest level is the result when no modifier is active. Example for the key `A` on a latin script keyboard: | Level | Description | Keysym | Active key modifiers | |-------|--------------------------------|--------|----------------------| | 1 | Lower case letters | `a` | None | | 2 | Upper case letters. | `A` | `Shift` | | 3 | Alternative lower case letters | `ae` | `AltGr` | | 4 | Alternative upper case letters | `AE` | `Shift` + `AltGr` | A key shift level is the logical _state_ of a key corresponding to the current shift level it used. Key shift levels are derived from the modifiers states, but not necessarily in the same way for all keys. For example, for Latin script the Caps Lock modifier selects the level 2 for alphabetic keys such as `A` but has no effect on a numeric key. There are groups of keys with the same characteristics: letters, punctuation, numeric keypad, etc. The meaning of their levels is identical and thus can be shared: this generalization is called a _key type_ (see hereinafter).
Key type
A key type defines the levels available for a key and how to derive the active level from the modifiers states. Examples: - `ONE_LEVEL`: the key has only one level, i.e. it is not affected by any modifiers. Example: the modifiers themselves. - [`TWO_LEVEL`][TWO_LEVEL]: the key has two levels: - Level 1: default level, active when the `Shift` modifier is _not_ active. - Level 2: level activated with the `Shift` modifier. - [`FOUR_LEVEL`][FOUR_LEVEL]: see the example in the previous section. See [xkb_types] for further details.
Layout
A mapping of keycodes to symbols, actions and key types. A user who deals with multiple languages may need two or more different layouts: e.g. a layout for Arabic and another one for English. In this context, layouts are called _groups_ in XKB, as defined in the [standard ISO/IEC 9995][ISO9995]. Layouts are ordered and identified by their index. Example: - Layout 1: Arabic - Layout 2: English
Key Action
In XKB world, a key action defines the effect a key has on the state of the keyboard or the state of the display server. Examples: - Change the state of a modifier. - Change the active group. - Move the mouse pointer. See the section “[Key actions][actions]” for further details.
Indicator
A keyboard indicator is a mean to report a specific aspect of the keyboard state.
Physical indicator
Typically a labelled LED on the keyboard, e.g. “Caps Lock” and “Num Lock”.
Logical indicator
A customizable derived state of the keyboard. Its changes creates events that can be monitored. There are two categories: - _Real_ indicators are those associated to a physical indicator. For example, the “Caps Lock” logical modifier controls the corresponding physical LED. Because indicators are customizable, if one misses a “Num Lock” LED, one could define instead the “Caps Lock” _indicator_ to activate its LED when the “Num Lock” _modifier_ is active. - _Virtual_ indicators are not associated to a physical indicator. Their effect is only visible for programs monitoring them. Note that the meanings of _real_ and _virtual_ is slightly different than the one used for [modifier].
See: [xkb_keycodes][indicator name] to define indicators and [xkb_compat][indicator effect] to define their effects.
Keymap
The _complete_ definition of the mapping of raw keycodes to symbols and actions. It fully defines the behavior of a keyboard. Depending of the context, a keymap may refer to: - the software object defined and managed by libxkbcommon; - the text configuration used to create this software object. See @ref keymap-components-intro and [xkb_keymap] for further details.
Keyboard configuration database @anchor database-def
A database that provides the [keymap components](@ref keymap-components-intro). \*nix OSs uses the _standard_ database [xkeyboard-config]. One may extend this database with _custom_ layouts: see “@ref user-configuration ""” for further details.
[keycode]: @ref keycode-def [keysym]: @ref keysym-def [keysyms]: @ref keysym-def [modifier]: @ref modifier-def [modifiers]: @ref modifier-def [real modifier]: @ref real-modifier-def [real modifiers]: @ref real-modifier-def [virtual modifier]: @ref virtual-modifier-def [virtual modifiers]: @ref virtual-modifier-def [level]: @ref level-def [shift level]: @ref level-def [level index]: @ref level-index-def [key type]: @ref key-type-def [key types]: @ref key-type-def [layout]: @ref layout-def [action]: @ref key-action-def [indicator]: @ref indicator-def [keymap]: @ref keymap-def [database]: @ref database-def [ISO9995]: https://en.wikipedia.org/wiki/ISO/IEC_9995 ## Introduction to the XKB text format The XKB text format uses a syntax similar to the [C programming language][C]. Note that the similarity with C stops here: the XKB text format is only a _configuration_ format and is not intended for programming. The XKB text format is used to configure a _keyboard keymap_, which is introduced in “@ref xkb-the-config ""”. It has the following two main use cases, illustrated in the [diagram hereinafter](@ref xkb-keymap-components-diagram): - __Server:__ Load a keymap from the keymap configuration database, then handle input events by updating the keyboard state. The keymap is assembled from an [RMLVO configuration][RMLVO] and its corresponding [KcCGST components][KcCGST] files. @see xkb_keymap::xkb_keymap_new_from_names2 @see [xkeyboard-config] for the implementation of the *standard* keymap configuration database. @see “@ref user-configuration ""” to add a *custom* layout or option. - __Client:__ Load the active keymap from the server, then handle update events sent by the server. The [complete keymap] is directly available in a _self-contained_ file. @see xkb_keymap::xkb_keymap_new_from_string @anchor xkb-keymap-components-diagram @dotfile xkb-keymap-components "XKB text format use cases" [C]: https://en.wikipedia.org/wiki/C_(programming_language)#Syntax [RMLVO]: @ref RMLVO-intro [KcCGST]: @ref KcCGST-intro [complete keymap]: @ref keymap-intro ### XKB file There are two kinds of files for the XKB text format:
Keymap file @anchor keymap-file-def
A file with the _complete_ description of the [keymap] object. It is the kind of file that the server sends to the client (see the [diagram](@ref xkb-keymap-components-diagram) above). Its top-level structure consists of the [xkb_keymap] block.
Keymap _component_ file @anchor keymap-component-file-def
A file with the description of a _particular_ [KcCGST component][KcCGST]. It is the kind of file that the server uses to assemble a [keymap file]. Its top-level structure consists of a _single type_ of [keymap sections]. A component file may contain multiple such sections.
[keymap file]: @ref keymap-file-def [keymap component file]: @ref keymap-component-file-def [keymap sections]: @ref keymap-section-def [section]: @ref keymap-section-def [keymap components]: @ref keymap-component-def ### Keymap components {#keymap-components-intro} [Keymap components][keymap components] are described with [keymap sections]. They are grouped in [keymap component files][keymap component file] to form a [keyboard configuration database][database].
Keymap _component_ @anchor keymap-component-def
A part of the keymap _object_. The set of keymap components is referred as [KcCGST]. They are presented in the [table hereinafter][keymap components table].
Keymap _section_ @anchor keymap-section-def
A part of the keymap _text configuration_ dedicated to one of the [keymap components][keymap components table].
Component _folder_
A folder in the [keymap configuration database][database], dedicated to files with partial definitions of the same keymap section.
[keymap components table]: @ref keymap-components-table @anchor keymap-components-table
Keymap components
[Component](@ref keymap-component-def) [Section][section] in a [keymap][xkb_keymap] Folder in a keymap configuration database Description
Key codes [xkb_keycodes] `keycodes` A translation of the raw [key codes][keycode] from the keyboard into symbolic names.
Compatibility [xkb_compat] `compat` A specification of what internal actions modifiers and various special-purpose keys produce.
(Geometry) xkb_geometry `geometry` A description of the physical layout of a keyboard. @attention This legacy feature is [not supported](@ref geometry-support) by _xkbcommon_.
Key symbols [xkb_symbols] `symbols` A translation of symbolic [key codes][keycode] into actual [key symbols][keysyms] (keysyms).
Key types [xkb_types] `types` Types describe how a pressed key is affected by active [modifiers] such as Shift, Control, Alt, etc.
### Comments Comments are introduced following either `//` or `#` until the end of the line. ### Literals
String literal @anchor keymap-string-literal
A string is surrounded by double quotes: “"”. The following _escape sequences_ are supported: | Escape sequence | Meaning | | ------------------ | -------------------------------------------------------- | | `\\` | Backslash “`\`” | | `\"` | Double quote “`"`” | | `\b` | Backspace | | `\e` | Escape | | `\f` | Form feed | | `\n` | Line feed (newline) | | `\r` | Carriage return | | `\t` | Horizontal tabulation | | `\v` | Vertical tabulation | | `\` + octal number | Corresponding ASCII character: `\1` → `SOH`, `\42` → `"`. Up to **4** octal digits `0‥7` are parsed. The result must fit into a byte. | | `\u{` + hexadecimal number + `}` | `\u{NNNN}` produce the corresponding [Unicode code point] `U+NNNN`, encoded in [UTF-8]. Supported code points are in the range `U+0001‥U+10FFFF`. | [Unicode code point]: https://en.wikipedia.org/wiki/Unicode#Codespace_and_code_points [UTF-8]: https://en.wikipedia.org/wiki/UTF-8 @note The string _encoding_ is unspecified and not validated, but for best results, stick to ASCII. @since \<1.9.0: Octal escape sequences accept up to **3** digits. @since 1.9.0: Octal escape sequences accept up to **4** digits. Added \\" and `\u{NNNN}` escape sequences.
Number literal
A number can be written in three forms: - _decimal integer:_ `1`, `123`, etc. - _decimal floating-point number:_ `1.23`, etc. - _hexadecimal integer:_ prefixed with `0x`: `0x123`, `0xff`, `0xAB`, etc.
### Keysyms {#keysym-syntax} [Keysyms][keysym] may be written in multiple ways:
Name
Keysym names are defined in `xkbcommon/xkbcommon-keysyms.h`; remove the `XKB_KEY_` prefix to get the name. Example: the keysym `0xffbe = XKB_KEY_F1` has the name `F1`.
Unicode
The *Unicode* syntax `Unnnn` denotes a keysym whose corresponding character is the Unicode code point `U+nnnn`, where `nnnn` is an hexadecimal number in the range `0x100 .. 0x10ffff`. The resulting keysym value is `0x01000000 + nnnn`. Example: `U1F3BA` has value `0x0101F3BA` and corresponds to the code point `U+1F3BA`: ‘🎺’ (TRUMPET).
String literal
A keysym or list of keysyms can be written as a *string literal*, with the following semantics: 1. The string must be encoded in UTF-8. 2. If the encoding is invalid, it raises a syntax error. 3. If the string expands to 0 Unicode code point, the resulting keysym is `NoSymbol`. 4. If the string expands to 1 Unicode code point, the resulting keysym is the output of `xkb_utf32_to_keysym`. 5. Otherwise the string expands to a list `{ ... }` with each Unicode code point converted via `xkb_utf32_to_keysym`. @note This is only possible where multiple keysyms is valid, e.g. in the @ref key-multiple-symbols-per-level "key symbols". Examples:
Keysym string Keysym name Keysym value
`""` `NoSymbol` `0x0000`
`"a"` `a` `0x0061`
`"ü"` `udiaeresis` `0x00dc`
`"🎺"` `U1F3BA` `0x0101F3BA`
`"g̃"` `{g, combining_tilde}` `{0x0101F3BA, 0x01000303}`
@sa @ref keysyms-string "Keysym strings" @since 1.9.0
Numeric value
A keysym can be written directly with its *numeric* value: e.g. `0x61` is `a`. This syntax is mostly useful in the following use cases: - the corresponding keysym has no associated name nor is in the Unicode range; - the corresponding keysym has/had a name but it is not supported in all the ecosystem; - keymap serialization by tools. @note Digits `0 .. 9` have a special treatment because they are interpreted as names, not values. E.g. `1` is the keysym with name `1` and value `0x31`. @note The previous special case does not apply to integers values in range `0 .. 9` that are written with *2+* characters: e.g. `01` and `0x1` are both interpreted as the *unnamed* keysym with value `0x01`, not the keysym named `1` and with value `0x31`. @warning Do not use this syntax to *manually* write keymap files unless there is no other option: it is the least human-friendly syntax.
### Keywords The following table presents the keywords used in the format. They are _case-sensitive_. | Keyword | Use | | ----------------------- | ------------------------------ | | `action` | Action of an [interpret statement](@ref interpret-action) | | `alias` | [Keycode alias](@ref keycode-alias) | | `alphanumeric_keys` | [Section flag](@ref section-flag-alphanum) | | `alternate_group` | [Section flag](@ref section-flag-alt-group) | | `alternate` | Merge mode qualifier for [include] statements | | `augment` | Merge mode qualifier for [include] statements | | `default` | [Section flag](@ref section-flag-default) | | `function_keys` | [Section flag](@ref section-flag-function) | | `group` | TODO | | `hidden` | [Section flag](@ref section-flag-hidden) | | `include` | [Include statement][include] | | `indicator` | Indicator statement in either the [keycode section](@ref indicator-name) or the [compatibility section](@ref indicator-effect) | | `interpret` | [Interpret statement][interpret] | | `key` | [Key statement](@ref key-statement) | | `keypad_keys` | [Section flag](@ref section-flag-keypad) | | `keys` | Legacy [geometry element][xkb_geometry] | | `logo` | Legacy [geometry element][xkb_geometry] | | `mod_map` | Alias of `modifier_map` | | `modifier_keys` | [Section flag](@ref section-flag-modifier) | | `modmap` | Alias of `modifier_map` | | `modifier_map` | [Real modifier bindings](@ref modmap-statement) | | `outline` | Legacy [geometry element][xkb_geometry] | | `overlay` | Legacy [geometry element][xkb_geometry] | | `override` | Merge mode qualifier for [include] statements | | `partial` | [Section flag](@ref section-flag-partial) | | `replace` | Merge mode qualifier for [include] statements | | `row` | Legacy [geometry element][xkb_geometry] | | `section` | Legacy [geometry element][xkb_geometry] | | `shape` | Legacy [geometry element][xkb_geometry] | | `solid` | Legacy [geometry element][xkb_geometry] | | `text` | Legacy [geometry element][xkb_geometry] | | `type` | [Key type statement](@ref key-type-statement) | | `virtual_modifiers` | [Virtual modifiers mappings](@ref virtual-modifier-statements) | | `virtual` | Flag for the [indicator statement](@ref indicator-name) | | `xkb_compat_map` | Alias of `xkb_compatibility_map` | | `xkb_compat` | Alias of `xkb_compatibility_map` | | `xkb_compatibility_map` | Declare a [compatibility section][xkb_compat] | | `xkb_compatibility` | Alias of `xkb_compatibility_map` | | `xkb_geometry` | Declare a [geometry section][xkb_geometry] | | `xkb_keycodes` | Declare a [keycodes section][xkb_keycodes] | | `xkb_keymap` | Declare a [keymap block][xkb_keymap] | | `xkb_layout` | Declare a legacy [layout compound section][xkb_layout] | | `xkb_semantics` | Declare a legacy [semantics compound section][xkb_semantics] | | `xkb_symbols` | Declare a [symbols section][xkb_symbols] | | `xkb_types` | Declare a [key types section ][xkb_types] | [include]: @ref xkb-include [interpret]: @ref interpret-statements [interpretations]: @ref interpret-statements [xkb_geometry]: @ref the-xkb_geometry-section [xkb_layout]: @ref legacy-layout-section [xkb_semantics]: @ref legacy-semantics-section ### Built-in settings There are many built-in settings; they are explained in the following relevant sections. These settings are _case-insensitive_, e.g. the following strings denote the same key word: `SETMODS`, `SetMods`, `setMods` and `setmods`. ### Merge modes {#merge-mode-def} Each statement has a **merge mode** property that defines how to handle *conflicts* with previous statements. This property can be set explicitly by prefixing the statement with one of the merge modes presented hereinafter.
@anchor merge-mode-augment augment
If two declarations conflict, update the properties which are *explicitly* defined in the *new* declaration, *only* if they were *implicit* in the *old* declaration. ```c key { [a , NoSymbol , ae ] }; augment key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; // Result key { [a , Greek_ALPHA, ae , AE] }; ```
@anchor merge-mode-override override
If two declarations conflict, update only the properties which are *explicitly* defined in the *new* declaration. @note @anchor merge-mode-default Override is the *default* merge mode. ```c key { [a , NoSymbol , ae ] }; // Explicit merge mode override key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; // Result key { [Greek_alpha, Greek_ALPHA, ae , AE] }; ``` ```c key { [a , NoSymbol , ae ] }; // Implicit merge mode is override key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; // Result key { [Greek_alpha, Greek_ALPHA, ae , AE] }; ```
@anchor merge-mode-replace replace
If two declarations conflict, ignore the old declaration and use the new one. ```c key { [a , NoSymbol , ae ] }; replace key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; // Result key { [Greek_alpha, Greek_ALPHA, NoSymbol, AE] }; ```
@anchor merge-mode-alternate alternate
Legacy merge mode for keycodes. Its purpose is to allow to assign the same key name to multiple key codes, which is not allowed otherwise. This is unfortunately poorly documented and not used in xkeyboard-config. The xkblib specification implies that this was part of the overlay functionality, which is currently not supported by libxkbcommon. @warning This merge mode is not supported by libxkbcommon and is ignored.
[default merge mode]: @ref merge-mode-default ### The include mechanism {#xkb-include} #### Syntax Statements of the form: ```c // Implicit section name: use the default map include "" // Explicit section name include "()" ``` will merge data from another [section] of the *same type*, possibly located in another file. Note that the statement does not have a trailing semicolon. If no section name is provided, the [default map] is looked up. [default map]: @ref default-map-def The path is usually relative to its corresponding directory in a XKB configuration: e.g. given the configuration directory ``, files of section type `xkb_symbols` are looked up in `/symbols`. Since 1.11, the paths can also be absolute or use **%-expansion**: @anchor keymap-include-percent-expansion
`%%`
A literal %.
\%H
The value of the `$HOME` environment variable.
\%S
The *main* system-installed XKB directory of the corresponding [component] \(usually `/usr/share/X11/xkb/`). This enables e.g. to override a system file using @ref user-configuration "" with the exact *same name*: ```c // File: ~/.config/xkb/symbols/de xkb_symbols "basic" { // Include the system file /usr/share/X11/xkb. // // Note that it is not be possible to use `include "de(basic)"` because // it would create an include *loop*. include "%S/de(basic)" // Override the system file entries key { [z, Z] }; key { [y, Y] }; } ```
\%E
The *extra* system-wide XKB directory of the corresponding [component] \(usually `/etc/xkb/`).
[component]: @ref keymap-components-table @warning Absolute paths and `%`-expansion are supported by libxkbcommon but not by the legacy X11 tools. The `include` keyword uses the *default* [merge mode]. The following keywords can be used instead to use the corresponding *explicit* [merge modes][]: - [`augment`][augment] - [`override`][override] - [`replace`][replace] [merge mode]: @ref merge-mode-def [merge modes]: @ref merge-mode-def [augment]: @ref merge-mode-augment [override]: @ref merge-mode-override [replace]: @ref merge-mode-replace *Multiple files* can be included using the same statement. They are separated using one of the following [merge mode] prefixes: - ‘|’ selects the [augment] merge mode. - ‘+’ selects the [override] merge mode (default). - ‘^’ selects the [replace] merge mode. The following example illustrates the complete syntax: ```c // Default merge mode, 1 file with an implicit section name include "" // Augment merge mode, 1 file with an implicit section name augment "()" // Absolute path and %-expansion include "/usr/share/X11/xkb/symbols/pc" include "%S/pc" // Override merge mode, 2 files: a first file with an implicit section name merged // using the augment mode with a second file with an explicit section name override "|() ``` #### Processing @important Since xkbcommon 1.9.0 the included files are processed in *isolation* and are not affected by the parent file (e.g. defaults), except for the virtual modifiers indices. @important Since xkbcommon 1.9.0 local merge modes are *not* propagated outside the section scope, i.e. an included file does not leaks its local merge modes to its parent. The statement is processed as follow: 1. Set PARENT as the current [section] containing the include statement. 2. Set INCLUDED_MERGE_MODE to the merge mode corresponding to the keyword. 3. Initialize an empty [section] as INCLUDED. 4. Select the first file as the current file to process. 5. Set CURRENT_MERGE_MODE to the merge mode corresponding to the current file merge mode *prefix*. 6. The current file path is searched sequentially in the [XKB configuration path list]: - If a section name is provided, select the first *exact match* of file + section. - If no section name is provided, select the first *explicit* [default map] in matched files, else if no exact match was found in the path list, then fallback to the first *implicit* [default map] as a weak match. Then if no match is found, raise an error; else go to the next step. 7. The current file is processed and results in the CURRENT [section]. 8. The INCLUDED [section] is merged with the CURRENT [section] using the merge mode CURRENT_MERGE_MODE. 9. If they are more files, select the next file as the current file and go to step 5). Else go to step 10). 10. Once all files have been processed, merge PARENT with INCLUDED using the merge mode INCLUDED_MERGE_MODE. [XKB configuration path list]: @ref xkb_context::xkb_context_include_path_append() #### Example: include path list Let’s illustrate using the following [XKB configuration path list][]: 1. `/home//.config/xkb`: user configuration directory (see @ref user-configuration ""). 2. `/usr/share/X11/xkb`: system directory. The relevant directory structure is: - `/home//.config/xkb` - `symbols` - `es` - `my_own_file` - `/usr/share/X11/xkb` - `symbols` - `es` - `it` Then the following file: ```c xkb_symbols { include "it" // Exists only in system directory include "my_own_file" // Exists only in user directory include "es" // Exists in both user and system directory }; ``` is equivalent to: ```c xkb_symbols { include "/usr/share/X11/xkb/symbols/it" include "/home//.config/xkb/symbols/my_own_file" include "/home//.config/xkb/symbols/es" }; ``` #### Example: simple include Given the following files: - `symbols/A` ```c xkb_symbols { key
{ [a, A, ae, AE] }; include "B(S2)" }; ``` - `symbols/B` ```c // This section is not used (does not match) xkb_symbols "S1" { key { [b, B] }; }; // This section will be included (match the included section name) xkb_symbols "S2" { key { [Greek_alpha, Greek_ALPHA] }; key { [Greek_beta , Greek_BETA ] }; }; ``` the resulting section in `A` will be: ```c xkb_symbols { // Key overridden: mix of old + new key { [Greek_alpha, Greek_ALPHA, ae, AE] }; // New key key { [Greek_beta , Greek_BETA ] }; }; ``` #### Example: merge modes Given the same file `symbols/B` of the previous example, the following section:
Input Output
```c xkb_symbols { key { [a, A, ae, AE] }; augment "B(S2)" }; ``` ```c xkb_symbols { // Key unchanged key { [a, A, ae, AE] }; // New key key { [Greek_beta , Greek_BETA] }; }; ```
```c xkb_symbols { key { [a, A, ae, AE] }; replace "B(S2)" }; ``` ```c xkb_symbols { // Key replaced key { Greek_alpha, Greek_ALPHA] }; // New key key { [Greek_beta , Greek_BETA ] }; }; ```
```c xkb_symbols { key { [a, A, ae, AE] }; // Two files merged together with the merge mode // augment, then the result is merged this the // statement above using the override merge mode include "B(S1)|B(S2)" }; ``` ```c xkb_symbols { // Key overridden: mix of old + new key { [Greek_alpha, Greek_ALPHA, ae, AE] }; // New key; "B(2)" had no effect with the // merge mode augment "|" key { [b, B] }; }; ```
## The “xkb_keymap” block {#the-xkb_keymap-block} A [keymap file] consists of a single top-level `xkb_keymap` block, under which are nested the following sections:
[xkb_keycodes]
A translation of the hardware/evdev scancodes from the keyboard into XKB symbolic keycodes.
[xkb_types]
A specification of the modifier mask, target level and preserved modifiers various modifiers combination produce.
[xkb_compat]
A specification of what actions various special-purpose keys produce.
[xkb_symbols]
A translation of symbolic key codes into actual symbols and actions.
Overview of a keymap file: ```c xkb_keymap { xkb_keycodes "XXX" { // ... } xkb_types "XXX" { // ... }; xkb_compatibility "XXX" { // ... }; xkb_symbols "XXX" { // ... }; }; ``` @since 1.9.0 All the component are optional. @remark The XKB file format historically supported the following compound section types:
- `xkb_semantics`: @anchor legacy-semantics-section *must* contain a [xkb_compat] section and *can* contain a [xkb_types] section. - `xkb_layout`: @anchor legacy-layout-section *must* contain [xkb_keycodes], [xkb_types] and [xkb_symbols] sections and *can* contain [xkb_geometry] section. - `xkb_keymap`: *must* contain [xkb_keycodes], [xkb_compat], [xkb_types] and [xkb_symbols] sections and *can* contain [xkb_geometry] section.
Since such distinction is purely semantic and would have niche use cases lost to history, these compound sections are treated equally as `xkb_keymap` in libxkbcommon. ## Section flags {#section-flags-def} A section can have various **flags** applied to it, separated by whitespaces: partial alphanumeric_keys xkb_symbols "basic" { ... } ### Generic flags The possible flags are:
partial@anchor section-flag-partial
Indicates that the map doesn’t cover a complete keyboard.
default@anchor section-flag-default
@anchor default-map-def Marks the symbol map as the *explicit* **default map** in the file. If no map is marked as a default, the first map in the file is the *implicit* default. Only **one** section can be marked as the default in each file.
hidden@anchor section-flag-hidden
Variant that can only be used internally.
### Symbols flags Additionally, `xkb_symbols` may also have the following flags:
alphanumeric_keys@anchor section-flag-alphanum
Indicates that the map contains alphanumeric keys.
modifier_keys@anchor section-flag-modifier
Indicates that the map contains modifier keys: Control, Shift, Alt, Meta, etc.
keypad_keys@anchor section-flag-keypad
Indicates that the map contains keypad keys.
function_keys@anchor section-flag-function
Indicates that the map contains function keys: F1, F2, etc.
alternate_group@anchor section-flag-alt-group
Indicates that the map contains keys for an alternate group.
If no `*_keys` flags are supplied, then the symbols section is assumed to cover a complete keyboard. At present, except for `default` (see: [default map]), none of the flags affect key processing in libxkbcommon, and only serve as *metadata*. ## The “xkb_keycodes” section {#the-xkb_keycodes-section} This is the simplest [section] type, and is the first one to be compiled. The purpose of this is mostly to map between the hardware/evdev scancodes and XKB [keycodes][keycode]. Each key is given a name by which it can be referred to later, e.g. in the symbols section. ### Keycode statements Statements of the form: = 49; = 10; The above would let 49 and 10 be valid keycodes in the keymap, and assign them the names `TLDE` and `AE01` respectively. The format `` is always used to refer to a key by name. The naming convention `` is based on the [standard ISO/IEC 9995-1][ISO9995-1]. It denotes the position of the key in the keyboard grid. It means: the main alphanumeric section (`A`), row `E` and column `01`. The following figure illustrates the grid on a staggered standard US QWERTY keyboard. `` corresponds to the key `1`. ``` \ 99 \ 00 \ 01 \ 02 \ 03 \ 04 \ 05… \ \ \ \ \ \ \ ----------------------------------------- E \ \ ^ \ 1 \ 2 \ 3 \ 4 \ 5… ------------------------------------------ D \ Tab \ Q \ W \ E \ R \ T… ------------------------------------------- C \Caps \ A \ S \ D \ F \ G… -------------------------------------------- B \Shift \ Z \ X \ C \ V \ B… --------------------------------------------- A \Ctrl\GUI \Alt \Space… ---------------------------------------------- ``` [ISO9995-1]: https://en.wikipedia.org/wiki/ISO/IEC_9995#ISO/IEC_9995-1 In the common case this just maps to the evdev scancodes from `/usr/include/linux/input.h`, e.g. the following definitions: #define KEY_GRAVE 41 #define KEY_1 2 correspond to the ones above. Similar definitions appear in the xf86-input-keyboard driver. Note that in all current keymaps there’s a constant offset of 8 (for historical reasons). Note that contrary to xkbcommon, the X11 protocol supports keycodes only up to `255`. Therefore, when interfacing with X11, keymaps and applications using keycodes beyond `255` should expect warnings. If there’s a conflict, like the same name given to different keycodes, or same keycode given different names, it is resolved according to the [merge mode] which applies to the definitions. ### Alias statements {#keycode-alias} Statements of the form: alias
= ; Allows to refer to a previously defined key (here ``) by another name (here ``). Conflicts are handled similarly to keycode statements. ### LED name statements {#indicator-name} [indicator name]: @ref indicator-name Statements of the form: indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; Assigns a name to the keyboard LED (AKA [indicator]) with the given index. The LED may be referred by this name later in the compat section and by the user. @todo `virtual` flag ## The “xkb_types” section {#the-xkb_types-section} This [section] is the second to be processed, after `xkb_keycodes`. However, it is completely independent and could have been the first to be processed (it does not refer to specific keys as specified in the `xkb_keycodes` section). This section defines [key types], which, given a key and a keyboard state (i.e. modifier state and group), determine the [shift level] to be used in translating the key to [keysyms]. These types are assigned to each group in each key, in the `xkb_symbols` section. Key types are called this way because, in a way, they really describe the “type” of the key (or more correctly, a specific group of the key). For example, an ordinary keymap will provide a type called `KEYPAD`, which consists of two levels, with the second level being chosen according to the state of the Num Lock (or Shift) modifiers. Another example is a type called `ONE_LEVEL`, which is usually assigned to keys such as Escape; these have just one level and are not affected by the modifier state. Yet more common examples are [`TWO_LEVEL`][TWO_LEVEL] (with Shift choosing the second level), [`ALPHABETIC`][ALPHABETIC] (where Caps Lock may also choose the second level), etc. ### How key types work Key types define a _mapping_ between the [modifiers] and [shift levels]. Key types have four parameters:
@ref key-type-level-name "Shift level names"
Declare [shift levels]. Mainly for documentation.
@ref key-type-modifiers "Modifiers filter"
Declare what modifiers should be taken into account in the mapping.
@ref key-type-map "Modifiers mapping"
Lookup table to translate modifiers combinations into shift levels.
@ref key-type-preserve "Modifiers preservation"
Tweak the computation of [consumed modifiers].
[consumed modifiers]: @ref consumed-modifiers [shift levels]: @ref level-def Key types are used to compute: - the [shift level][]: see xkb_state::xkb_state_key_get_level(). - the [consumed modifiers][]: see xkb_state::xkb_state_key_get_consumed_mods() and xkb_state::xkb_state_key_get_consumed_mods2(). The following diagram presents an overview of theses computations: @anchor xkb-types-explanation-diagram @dotfile xkb-types-explanation "Use of key types to compute shift level and consumed modifiers" ### Type definitions {#key-type-statement} Statements of the form: type "FOUR_LEVEL" { ... } The above would create a new type named [`FOUR_LEVEL`][FOUR_LEVEL]. The body of the definition may include statements of the following forms: #### “level_name” statements {#key-type-level-name} level_name[Level1] = "Base"; Mandatory for each level in the type. Gives each level in this type a descriptive name. It isn’t used for anything. Note: A level may be specified as Level\[1-8\] or just a number (can be more than 8). #### “modifiers” statement {#key-type-modifiers} modifiers = Shift+Lock+LevelThree; Mandatory, should be specified only once. A mask of real and virtual [modifiers]. These are the only modifiers being considered when matching the modifier state against the type. The other modifiers, whether active or not, are masked out in the calculation. #### “map” entry statements {#key-type-map} map[Shift+LevelThree] = Level4; Should have at least as many mappings as there are levels in the type. If the active modifiers, masked with the type’s modifiers (as stated above), match (i.e. equal) the modifiers inside the `map[]` statement, then the level in the right hand side is chosen. For example, in the above, if in the current keyboard state the `Shift` and `LevelThree` modifiers are active, while the `Lock` modifier is not, then the keysym(s) in the 4th level of the group will be returned to the user. #### “preserve” statements {#key-type-preserve} map[Shift+Lock+LevelThree] = Level5; preserve[Shift+Lock+LevelThree] = Lock; When a key type is used for keysym translation, its modifiers are said to be [consumed](@ref consumed-modifiers) in this translation. For example, in a simple US keymap, the “G” key is assigned an ordinary [`ALPHABETIC`][ALPHABETIC] key type, whose modifiers are `Shift` and `Lock`; then for the “G” key, these two modifiers are consumed by the translation. This information is relevant for applications which further process the modifiers, since by then the consumed modifiers have already “done their part” and should be masked out. However, sometimes even if a modifier had already affected the key translation through the type, it should *not* be reported as consumed, for various reasons. In this case, a `preserve[]` statement can be used to augment the map entry. The modifiers inside the square brackets should match one of the `map[]` statements in the type (if there is no matching map entry, one mapping to Level1 is implicitly added). The right hand side should consists of modifiers from the type’s modifiers; these modifiers are then “preserved” and not reported as consumed. @attention Consuming a *locked* modifier does *not* unlock it and it can be consumed again in further keysym translations. @note Remember that @ref keysym-transformations may affect the resulting keysym when some modifiers are not [consumed](@ref consumed-modifiers). @remark `preserve` statements may be used to tweak keyboard shorcuts. @remark@figure @figcaption Example of use of `preserve` to tweak `Control` shortcuts. Note it would require further work in order to support other modifiers. @endfigcaption ```c xkb_types { // ... type "TWO_LEVEL_PLUS_CONTROL" { modifiers = Shift + Control; map[None] = Level1; map[Shift] = Level2; map[Control] = Level3; map[Control+Shift] = Level4; // Using preserve will make Control not consumed and allow // applications to detect keyboard shortcuts with alternative // keysyms in levels 3 and 4 rather than the levels 1 and 2. preserve[Control] = Control; preserve[Control+Shift] = Control; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Tweaked Control"; level_name[Level4] = "Tweaked Control + Shift"; }; }; xkb_symbols { // ... // The following key would produce Greek keysym on Base and Shift levels, // but will produce the corresponding ASCII Latin keysyms when using Control. key { type[Group1]="TWO_LEVEL_PLUS_CONTROL", [Greek_alpha, Greek_ALPHA, a, A] }; }; ``` @endfigure ### Key types examples {#key-type-examples} #### Definitions examples @note The convention is that `Lock` affect only “alphabetic” types. For such types, `Lock` “cancels” `Shift` by default, i.e. `Shift+Lock` has the same result as neither modifier. “semi-alphabetic” types have an asymmetry: their first two levels are alphabetic while the next are not. ##### Two levels The following examples compare two basic types with *two levels*: [`TWO_LEVEL`][TWO_LEVEL] and [`ALPHABETIC`][ALPHABETIC]. They differ on their handling of the `Lock` modifier. See the [next section](@ref key-type-mappings-examples) for an illustration with concrete layouts. [TWO_LEVEL]: @ref TWO_LEVEL [ALPHABETIC]: @ref ALPHABETIC
`TWO_LEVEL` @anchor TWO_LEVEL
@figure@figcaption Definition code ([source][two-type-src]) @endfigcaption ```c type "TWO_LEVEL" { // Only care about Shift; Lock will be filter out modifiers = Shift; // Define mapping map[None] = Level1; // No modifier -> level 1 map[Shift] = Level2; // Exactly Shift -> level 2 // (no map entry with Lock) // Define level names level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ------------------ | -------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | (none) | Yes | 1           | | `Shift + Lock` | `Shift` | Yes | 2 | @endfigure
`ALPHABETIC` @anchor ALPHABETIC
@figure@figcaption Definition code ([source][alphabetic-type-src]) @endfigcaption ```c type "ALPHABETIC" { // Only care about Shift and Lock modifiers = Shift + Lock; // Define mapping map[None] = Level1; // No modifier -> level 1 map[Shift] = Level2; // Exactly Shift -> level 2 map[Lock] = Level2; // Exactly Lock -> level 2 // Define level names level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ------------------ | -------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | `Lock` | Yes | 2           | | `Shift + Lock` | `Shift + Lock` | No | 1 | @endfigure
##### Four levels The following examples compare basic types with *four levels*: [`FOUR_LEVEL`][FOUR_LEVEL], [`FOUR_LEVEL_SEMIALPHABETIC`][FOUR_LEVEL_SEMIALPHABETIC] and [`FOUR_LEVEL_ALPHABETIC`][FOUR_LEVEL_ALPHABETIC]. They differ on their handling of the `Lock` modifier. See the [next section](@ref key-type-mappings-examples) for an illustration with concrete layouts. [FOUR_LEVEL]: @ref FOUR_LEVEL [FOUR_LEVEL_SEMIALPHABETIC]: @ref FOUR_LEVEL_SEMIALPHABETIC [FOUR_LEVEL_ALPHABETIC]: @ref FOUR_LEVEL_ALPHABETIC
`FOUR_LEVEL` @anchor FOUR_LEVEL
@figure@figcaption Definition code ([source][four-level-src]) @endfigcaption ```c type "FOUR_LEVEL" { modifiers = Shift + LevelThree; map[None] = Level1; map[Shift] = Level2; // (no map entry with Lock) // (no map entry with Lock) map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; // (no map entry with Lock) // (no map entry with Lock) // (no preserve entry with Lock) // (no preserve entry with Lock) level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "AltGr"; level_name[Level4] = "Shift AltGr"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ----------------------- | -------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | (none) | Yes | 1           | | `Shift+Lock` | `Shift` | Yes | 2 | | `LevelThree` | `LevelThree` | Yes | 3 | | `LevelThree+Shift` | `LevelThree+Shift` | Yes | 4 | | `LevelThree+Lock` | `LevelThree` | Yes | 3 | | `LevelThree+Shift+Lock` | `LevelThree+Shift` | Yes | 4 | @endfigure
`FOUR_LEVEL_SEMIALPHABETIC` @anchor FOUR_LEVEL_SEMIALPHABETIC
@figure@figcaption Definition code ([source][four-level-semialphabetic-src]) @endfigcaption ```c type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift + Lock + LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[Shift+Lock] = Level1; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Shift+Lock+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Shift+Lock+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "AltGr"; level_name[Level4] = "Shift AltGr"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ----------------------- | ----------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | `Lock` | Yes | 2           | | `Shift+Lock` | `Shift+Lock` | Yes | 1 | | `LevelThree` | `LevelThree` | Yes | 3 | | `LevelThree+Shift` | `LevelThree+Shift` | Yes | 4 | | `LevelThree+Lock` | `LevelThree+Lock` | Yes | 3 | | `LevelThree+Shift+Lock` | `LevelThree+Shift+Lock` | Yes | 4 | @endfigure
`FOUR_LEVEL_ALPHABETIC` @anchor FOUR_LEVEL_ALPHABETIC
@figure@figcaption Definition code ([source][four-level-alphabetic-src]) @endfigcaption ```c type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift + Lock + LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[Shift+Lock] = Level1; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Shift+Lock+LevelThree] = Level3; // (no preserve entry with Lock) // (no preserve entry with Lock) level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "AltGr"; level_name[Level4] = "Shift AltGr"; }; ``` @endfigure @figure@figcaption Mapping test @endfigcaption | *Active* modifiers | *Filtered* modifiers | Match? | Shift level | | ----------------------- | ----------------------- | ------ | ----------- | | (none) | (none) | Yes | 1 | | `Shift` | `Shift` | Yes | 2 | | `Lock` | `Lock` | Yes | 2           | | `Shift+Lock` | `Shift+Lock` | Yes | 1 | | `LevelThree` | `LevelThree` | Yes | 3 | | `LevelThree+Shift` | `LevelThree+Shift` | Yes | 4 | | `LevelThree+Lock` | `LevelThree+Lock` | Yes | 4 | | `LevelThree+Shift+Lock` | `LevelThree+Shift+Lock` | Yes | 3 | @endfigure
[two-type-src]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/022c3ca1db12e505cbd5ce8bf19c432d6a70c7e5/types/basic#L14 [alphabetic-type-src]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/022c3ca1db12e505cbd5ce8bf19c432d6a70c7e5/types/basic#L21 [four-level-src]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/022c3ca1db12e505cbd5ce8bf19c432d6a70c7e5/types/extra#L8 [four-level-alphabetic-src]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/022c3ca1db12e505cbd5ce8bf19c432d6a70c7e5/types/extra#L20 [four-level-semialphabetic-src]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/022c3ca1db12e505cbd5ce8bf19c432d6a70c7e5/types/extra#L36 #### Examples with standard keyboard layouts {#key-type-mappings-examples}
See the detailed table of mappings The following table compares the mappings of various key types for the modifiers `Shift`, `Lock` and `LevelThree`, using the standard layouts [`us`][us-layout] (US English) and [`es`][es-layout] (Spanish). [us-layout]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/022c3ca1db12e505cbd5ce8bf19c432d6a70c7e5/symbols/us#L3 [es-layout]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config/-/blob/022c3ca1db12e505cbd5ce8bf19c432d6a70c7e5/symbols/es#L3 | Key | Layout | Key type | Active modifiers | Level | Keysym | Comment | | ------ | ------ | ------------------------------- | ------------------------------- | ----- | ------------ | ----------- | | `AE01` | [`us`][us-layout] | [`TWO_LEVEL`][TWO_LEVEL] | (none) | 1 | `1` | | | ^ | ^ | ^ | `Shift` | 2 | `exclam` | | | ^ | ^ | ^ | `Lock` | 1 | `1` | `Lock` filtered out | | ^ | ^ | ^ | `Shift` + `Lock` | 2 | `exclam` | `Lock` filtered out | | ^ | ^ | ^ | `LevelThree` | 1 | `1` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` | 2 | `exclam` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Lock` | 1 | `1` | Modifiers `LevelThree` and `Lock` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 2 | `exclam` | Modifiers `LevelThree` and `Lock` filtered out | | ^ | [`es`][es-layout] | [`FOUR_LEVEL`][FOUR_LEVEL] | (none) | 1 | `1` | | | ^ | ^ | ^ | `Shift` | 2 | `exclam` | | | ^ | ^ | ^ | `Lock` | 1 | `1` | `Lock` filtered out | | ^ | ^ | ^ | `Shift` + `Lock` | 2 | `exclam` | `Lock` filtered out | | ^ | ^ | ^ | `LevelThree` | 3 | `bar` | | | ^ | ^ | ^ | `LevelThree` + `Shift` | 4 | `exclamdown` | | | ^ | ^ | ^ | `LevelThree` + `Lock` | 3 | `bar` | `Lock` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 4 | `exclamdown` | `Lock` filtered out | | `AD01` | [`us`][us-layout] | [`ALPHABETIC`][ALPHABETIC] | (none) | 1 | `q` | | | ^ | ^ | ^ | `Shift` | 2 | `Q` | | | ^ | ^ | ^ | `Lock` | 2 | `Q` | | | ^ | ^ | ^ | `Shift` + `Lock` | 1 | `q` | `Lock` cancelled by `Shift` | | ^ | ^ | ^ | `LevelThree` | 1 | `q` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` | 1 | `q` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Lock` | 2 | `Q` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 1 | `q` | `LevelThree` filtered out, `Lock` cancelled by `Shift` | | ^ | [`es`][es-layout] | [`FOUR_LEVEL_SEMIALPHABETIC`][FOUR_LEVEL_SEMIALPHABETIC] | (none) | 1 | `q` | | | ^ | ^ | ^ | `Shift` | 2 | `Q` | | | ^ | ^ | ^ | `Lock` | 2 | `Q` | | | ^ | ^ | ^ | `Shift` + `Lock` | 1 | `q` | `Lock` cancelled by `Shift` | | ^ | ^ | ^ | `LevelThree` | 3 | `at` | | | ^ | ^ | ^ | `LevelThree` + `Shift` | 4 | `Greek_OMEGA`| | | ^ | ^ | ^ | `LevelThree` + `Lock` | 3 | `at` | `Lock` does not affect `LevelThree` combos | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 4 | `Greek_OMEGA`| `Lock` does not affect `LevelThree` combos | | `AD05` | [`us`][us-layout] | [`ALPHABETIC`][ALPHABETIC] | (none) | 1 | `t` | | | ^ | ^ | ^ | `Shift` | 2 | `T` | | | ^ | ^ | ^ | `Lock` | 2 | `T` | | | ^ | ^ | ^ | `Shift` + `Lock` | 1 | `t` | `Lock` cancelled by `Shift` | | ^ | ^ | ^ | `LevelThree` | 1 | `t` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` | 1 | `t` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Lock` | 2 | `T` | `LevelThree` filtered out | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 1 | `t` | `LevelThree` filtered out, `Lock` cancelled by `Shift` | | ^ | [`es`][es-layout] | [`FOUR_LEVEL_ALPHABETIC`][FOUR_LEVEL_ALPHABETIC] | (none) | 1 | `t` | | | ^ | ^ | ^ | `Shift` | 2 | `T` | | | ^ | ^ | ^ | `Lock` | 2 | `T` | | | ^ | ^ | ^ | `Shift` + `Lock` | 1 | `t` | `Lock` cancelled by `Shift` | | ^ | ^ | ^ | `LevelThree` | 3 | `tslash` | | | ^ | ^ | ^ | `LevelThree` + `Shift` | 4 | `Tslash` | | | ^ | ^ | ^ | `LevelThree` + `Lock` | 4 | `Tslash` | | | ^ | ^ | ^ | `LevelThree` + `Shift` + `Lock` | 3 | `tslash` | `Lock` cancelled by `Shift` |
## The “xkb_compat” section {#the-xkb_compat-section} This [section] is the third to be processed, after `xkb_keycodes` and `xkb_types`. ### Interpret statements {#interpret-statements} Statements of the form: interpret Num_Lock+Any { ... } interpret Shift_Lock+AnyOf(Shift+Lock) { ... } The [xkb_symbols] section (see below) allows the keymap author to perform, among other things, the following things for each key: - Bind a sequence of [actions], like `SetMods` or `LockGroup`, to the key. Actions, like symbols, are specified for each level of each group in the key separately. - Add a [virtual modifier] to the key’s virtual modifier mapping (`vmodmap`). - Specify whether the key should repeat or not. However, doing this for each key (or level) is tedious and inflexible. Interpret’s are a mechanism to apply these settings to a bunch of keys/levels at once. @anchor interpret-mechanism Each interpret specifies a condition by which it attaches to certain levels. The condition consists of two parts: - A [keysym]. If the level has a different (or more than one) keysym, the match fails. Leaving out the keysym is equivalent to using the special value `Any` or the `NoSymbol` keysym, which always matches successfully. - A [modifier] predicate. The predicate consists of: - A __mask__ of _real_ modifiers: a `+`-separated list of modifiers or the special value `all`, which denotes all the modifiers. The modifiers are matched against the key’s modifier map (`modmap`). - A __matching operation__, that is one of the following: * `AnyOfOrNone` – The modmap must either be empty or include at least one of the specified modifiers. * `AnyOf` – The modmap must include at least one of the specified modifiers. * `Any` – Alias for `AnyOf(all)`. * `NoneOf` – The modmap must not include any of the specified modifiers. * `AllOf` – The modmap must include all of the specified modifiers (but may include others as well). * `Exactly` – The modmap must be exactly the same as the specified modifiers. Leaving out the predicate is equivalent to using `AnyOfOrNone(all)`. Leaving out just the matching condition is equivalent to using `Exactly`. An interpret may also include `useModMapMods = level1;` – see below. If a [level] fulfils the conditions of several interprets, only the most specific one is used: - A specific keysym will always match before a generic `NoSymbol` condition. - If the keysyms are the same, the interpret with the more specific matching operation is used. The above list is sorted from least to most specific. - If both the keysyms and the matching operations are the same (but the modifiers are different), the first interpret is used. As described above, once an interpret “attaches” to a level, it can bind an action to that level, add one virtual modifier to the key’s vmodmap, or set the key’s repeat setting. You should note the following: - The key repeat is a property of the entire key; it is not level-specific. In order to avoid confusion, it is only inspected for the first level of the first group; the interpret’s repeat setting is ignored when applied to other levels. - If one of the above fields was set directly for a key in `xkb_symbols`, the explicit setting takes precedence over the interpret. The body of the statement may include statements of the following forms (all of which are optional): #### “useModMapMods” statement useModMapMods = level1; When set to `level1`, the interpret will only match keysyms which are on the first level of the first group of the keys. This can be useful in conjunction with e.g. a [`virtualModifier`](@ref interpret-virtualModifier) statement, because `virtualModifier` is an attribute of the key rather than a specific level. Note: the other possible value is `any` and is the default value. See [virtual modifier map] for further information. #### “virtualModifier” statement {#interpret-virtualModifier} virtualModifier = NumLock; Add this virtual modifier to the key’s `vmodmap`. The given virtual modifier must be declared at the top level of the file with a `virtual_modifiers` statement, e.g.: virtual_modifiers NumLock; See [virtual modifier map] for further information. #### “repeat” statement {#interpret-repeat} repeat = True; Set whether the key should repeat or not. Must be a boolean value. #### “action” statement {#interpret-action} action = LockMods(modifiers=NumLock); Bind this action to the matching levels. See [key actions][actions] for the list of available key actions. Since 1.9.0, it is also possible to assign a sequence of actions, mirroring the feature used in the [key statement](@ref key-multiple-symbols-per-level). action = {SetMods(modifiers=NumLock),SetGroup(group=2)}; ### LED map statements {#indicator-effect} [indicator effect]: @ref indicator-effect Statements of the form: indicator "Shift Lock" { ... } This statement specifies the behavior and binding of the LED (AKA [indicator]) with the given name (“Shift Lock” above). The name should have been declared previously in the `xkb_keycodes` section (see [LED name][indicator name] statement), and given an index there. If it wasn’t, it is created with the next free index. The body of the statement describes the conditions of the keyboard state which will cause the LED to be lit. It may include the following statements: #### “modifiers” statement modifiers = ScrollLock; If the given [modifiers] are in the required state (see below), the LED is lit. #### “whichModState” statement whichModState = Latched+Locked; Can be any combination of: * `base`, `latched`, `locked`, `effective` * `any` (i.e. all of the above) * `none` (i.e. none of the above) * `compat` (legacy value, treated as effective) This will cause the respective portion of the modifier state (see `struct xkb_state`) to be matched against the modifiers given in the `modifiers` statement. Here’s a simple example: indicator "Num Lock" { modifiers = NumLock; whichModState = Locked; }; Whenever the NumLock modifier is locked, the Num Lock LED will light up. #### “groups” statement groups = All - group1; If the given groups are in the required state (see below), the LED is lit. #### “whichGroupState” statement whichGroupState = Effective; Can be any combination of: * `base`, `latched`, `locked`, `effective` * `any` (i.e. all of the above) * `none` (i.e. none of the above) This will cause the respective portion of the group state (see `struct xkb_state`) to be matched against the groups given in the `groups` statement. Note: the above conditions are disjunctive, i.e. if any of them are satisfied the LED is lit. ### Set default values One may change the default values of the following statements: - `interpret`: use `interpret.FIELD = VALUE;` - `indicator`: use `indicator.FIELD = VALUE;` - actions: use `ACTION_NAME.FIELD = VALUE;`. E.g. `setMods.clearLocks= True;`. ## The “xkb_symbols” section {#the-xkb_symbols-section} This [section] is the fourth to be processed, after `xkb_keycodes`, `xkb_types` and `xkb_compat`. Statements of the form: xkb_symbols "basic" { ... } Declare a symbols map named `basic`. Statements inside the curly braces only affect the symbols map. ### Name statements Statements of the form: name[Group1] = "US/ASCII"; groupName[1] = "US/ASCII"; Gives the name “US/ASCII” to the first group of symbols. Other groups can be named using a different group index (ex: `Group2`), and with a different name. A group must be named. `group` and `groupName` mean the same thing, and the `Group` in `Group1` is optional. ### Key statement {#key-statement} Statements of the form: key { ... }; defines the *key description* of the [keycode] `` and is the main type of record of the `xkb_symbols` section. The possible keycodes are defined in the [`xkb_keycodes`](@ref the-xkb_keycodes-section) section. A key description consists of:
Groups
Each key may have one or more associated [groups]. Each group can be configured with the following parameters: - @ref key-type-setting "Type" - @ref key-symbols-table "Symbols" - @ref key-actions-table "Actions"
Additional attributes
These attributes are usually set via the [xkb_compat] section, but may be also set directly: - @ref key-virtual-modifiers "Virtual modifiers" - @ref key-repeat "Repeat"
@warning Using multiple groups in *symbols* files is not recommended, because some tools rely on the assumption that an `xkb_symbols` section only affect a single group. It is fine with a *keymap* file though. @note In what follows we assume the common use case with a *single* group, which benefits from a special syntax. See the section @ref key-groups "Multiple groups" for the general syntax. [groups]: @ref layout-def #### Symbols {#key-symbols-table} The main part of the key description is the *symbols table*. It maps shift levels to keysyms, e.g.: ```c key { [ q, Q ] }; // Level 1 → `q`, Level 2 → `Q` ``` Symbols are named using the symbolic names from the `xkbcommon/xkbcommon-keysyms.h` file. See the @ref keysym-syntax "keysym syntax" for further information. A group of symbols is enclosed in brackets and separated by commas. Each element of the symbol arrays corresponds to a different [shift level]. In this example, the symbol (keysym) `XKB_KEY_q` for level 1 and `XKB_KEY_Q` for level 2. These levels are configured by the @ref key-type-setting "key type", presented in the next section. @remark Remember that @ref keysym-transformations may affect the resulting keysym when some modifiers are not [consumed](@ref consumed-modifiers). @remark Trailing `NoSymbol` are dropped. @anchor key-multiple-symbols-per-level As an extension to the XKB legacy format, libxkbcommon supports multiple key symbols and actions per level (the latter since version 1.8.0): ```c key { [ {i, j} , U0132 ] }; // IJ Dutch digraph key { [ {g, U0303} , {G, U0303} ] }; // G̃ Guarani letter key { [ {U0644, U0627}, {U0644, U0622}] }; // ⁧لا⁩ ⁧لآ⁩ Arabic Lam-Alef ligatures decomposed key { [ {c, U2019, h} , {C, U2019, h} ] }; // C’H Breton trigraph ``` In this example, the keycode `` produces two symbols on level 1 (`XKB_KEY_i` and `XKB_KEY_j`) and one symbol (Unicode keysym `U0132` for “IJ”) on level 2. `` and `` produce letters that have no *precomposed* code point in Unicode. Key `` avoids the need of using Compose. @anchor keysyms-string Since 1.9.0, UTF-8-encoded *strings* may be used to denote a list of keysyms corresponding to the encoded Unicode code points. E.g. the previous example can be also written more intuitively as: ```c key { [ "ij" , "IJ" ] }; // IJ Dutch digraph key { [ "g̃" , "G̃" ] }; // G̃ Guarani letter // NOTE: We use U+200E LEFT-TO-RIGHT MARK in order to display the strings in // in the proper order. key { [ "لا"‎ , "لآ"‎ ] }; // ⁧لا⁩ ⁧لآ⁩ Arabic Lam-Alef ligatures decomposed key { [ "c’h", "C’h" ] }; // C’H Breton trigraph ``` When no actions are explicitly given, they are automatically filled thanks to [interpretations] from the [compat section][xkb_compat]. In the following example, key { [ { Control_L, ISO_Group_Shift } ] }; is equivalent to (given standard definitions from `xkeyboard-config`): key { symbols[1] = [ { Control_L, ISO_Group_Shift } ], actions[1] = [ { SetMods(modifiers=Control), SetGroup(group=+1) } ] }; When using this example with e.g. two layouts `fr,us` (respectively Azerty and Qwerty layouts), typing `Control + A` in the first layout `fr` will in fact result in `Control + Q`, because the actions are run sequentially: first set the base modifiers to Control, then switch to the second layout while `Control` is pressed. @remark Given a level, keysyms and actions may have a *different count*. For instance, the following would achieve the same effect than the former example with only 1 keysym, but it requires to use 2 explicit actions: ```c key { symbols[1] = [ Control_L ], actions[1] = [ { SetMods(modifiers=Control), SetGroup(group=+1) } ] }; ``` @note There are some *limitations* with this extension: - For now, *at most one* action of each following categories is allowed per level: - [modifier actions][]: `SetMods`, `LatchMods`, `LockMods`; - [group actions][]: `SetGroup`, `LatchGroup`, `LockGroup`. Some examples of actions combination: - `SetMods` + `SetGroup`: ok - `SetMods` + `SetMods`: *error* - `SetMods` + `LockMods`: *error* - `SetMods` + `LockGroup`: ok - Multiple actions are only supported from version 1.8.0.
@since 1.8.0: When using multiple keysyms or actions per level, `NoSymbol` and `NoAction()` are dropped in order to normalize the levels: ```c // Before normalization key <> { [{NoSymbol}, {a, NoSymbol}, {NoSymbol,b}, {a, NoSymbol, b}] }; // After normalization key <> { [NoSymbol, a, b, {a, b}] }; ```
@since 1.9.0: Trailing `NoSymbol` and `NoAction()` are dropped in groups: ```c // Before normalization key <> { [a, NoSymbol] }; // After normalization key <> { [a] }; ``` This affects the automatic key type detection.
@since 1.9.0: Added support for keysyms and actions lists of length 0 and 1, respectively `{}` and `{a}`. `{}` is equivalent to the corresponding `NoSymbol` or `NoAction()`.
@warning Keymaps containing multiple key symbols per level are not supported by the various X11-related tools (`setxkbmap`, `xkbcomp`, etc.). [symbols table]: @ref key-symbols-table #### Type {#key-type-setting} Each key has a [key type] set per group. This key type is defined in the [xkb_types] section. Its associated [shift levels] are used to index the [symbols table] presented in the previous section. A key type is set using the following syntax: ```c key { type[Group1] = "TWO_LEVEL", // Type [q, Q] // Symbols }; ``` The name of the key type is enclosed between double quotes. The key type may be omitted and will default to: - `key.type` global defaults, if set. - a standard type using the following **heuristic**: - **1** keysym: `ONE_LEVEL` - **2** keysyms: - if the two keysyms are letter and the first is lower case and the other upper case, then [`ALPHABETIC`][ALPHABETIC]; - if one of the keysyms is numpad, then `KEYPAD` else [`TWO_LEVEL`][TWO_LEVEL]. - **3 or 4** keysyms (a missing 4th keysym is set to `NoSymbol`): - if the first two keysyms are letters and the first is lower case and the other upper case: - if the last two keysyms are letters and the first is lower case and the other upper case then [`FOUR_LEVEL_ALPHABETIC`][FOUR_LEVEL_ALPHABETIC]; - else [`FOUR_LEVEL_SEMIALPHABETIC`][FOUR_LEVEL_SEMIALPHABETIC]. - if one of the first two keysyms is numpad, then `FOUR_LEVEL_KEYPAD`; - else [`FOUR_LEVEL`][FOUR_LEVEL]. @figure@figcaption Commented examples for inferred types: @endfigcaption ```c // 1 to 2 keysyms key { [Shift_L] }; // Type: ONE_LEVEL key { [1, exclam] }; // Type: TWO_LEVEL key { [q, Q] }; // Type: ALPHABETIC key { [KP_End, KP_1] }; // Type: KEYPAD // Edge case: this is consider alphabetic, although // the lower case does not correspond to the upper case. key { [q, N] }; // Type: ALPHABETIC // 3 to 4 keysyms key { [1, exclam, bar] }; // Type: FOUR_LEVEL key { [1, exclam, bar, exclamdown] }; // Type: FOUR_LEVEL key { [q, Q, at] }; // Type: FOUR_LEVEL_SEMIALPHABETIC key { [q, Q, at, Greek_OMEGA] }; // Type: FOUR_LEVEL_SEMIALPHABETIC key { [t, T, tslash, Tslash] }; // Type: FOUR_LEVEL_ALPHABETIC // The inferred type is `FOUR_LEVEL`, but using `LevelThree+Lock` // will produce `Q`, because of the keysyms transformations and // the corresponding internal capitalization processing. key { [1, exclam, q, Q] }; // Type: FOUR_LEVEL // Won’t work, because there is no heuristic for more than 4 keysyms // It will trigger the warnings XKB-183 and XKB-516 and default to ONE_LEVEL, // ignoring all the keysyms but the first one. key {[q, Q, at, any, masculine, U2642]}; // Will work as expected key { type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC", [q, Q, at, any, masculine, U2642] }; ``` @endfigure #### Actions {#key-actions-table} @note This is usually not set explicitly but via the [interpret mechanism] by using the [`action`](@ref interpret-action) statement in the [xkb_compat] section. @figure@figcaption Example: Set the modifier action of the key `` manually. @endfigcaption ```c key { symbols[Group1]=[Alt_L], actions[Group1]=[SetMods(modifiers=modMapMods)] }; ``` @endfigure For further details see [key actions][actions]. @remark Trailing `NoAction()` are dropped. #### Multiple groups {#key-groups} Each group represents a list of symbols mapped to a keycode: name[Group1]= "US/ASCII"; name[Group2]= "Russian"; ... key { [ q, Q ], [ Cyrillic_shorti, Cyrillic_SHORTI ] }; A long-form syntax can also be used: key { symbols[Group1]= [ q, Q ], symbols[Group2]= [ Cyrillic_shorti, Cyrillic_SHORTI ] }; Groups can also be omitted, but the brackets must be present. The following statement only defines the Group3 of a mapping: key { [], [], [ q, Q ] }; @warning Using multiple groups in *symbols* files is not recommended, because some tools rely on the assumption that an `xkb_symbols` section only affect a single group. It is fine with a *keymap* file though. #### Virtual modifiers {#key-virtual-modifiers} @note This is usually not set explicitly but via the [interpret mechanism] by using the [`virtualModifier`](@ref interpret-virtualModifier) statement from the [xkb_compat] section. @remarks When setting a [modifier action](@ref modifiers-actions), it is required to declare the corresponding virtual modifier using a [`virtual_modifiers`](@ref virtual-modifier-statements) statement. @figure@figcaption Example: Set the virtual modifier of the key `` to `Alt`. @endfigcaption ```c // Declare the virtual modifier that will be used virtual_modifiers Alt; key { virtualModifiers = Alt, [ Alt_L ] }; ``` @endfigure See [virtual modifier map] for further information. [interpret mechanism]: @ref interpret-mechanism #### Repeat {#key-repeat} @note This is usually not set explicitly but via the [interpret mechanism] by using the [`repeat`](@ref interpret-repeat) statement in the [xkb_compat] section. @figure@figcaption Example: make the `` key not repeating. @endfigcaption ```c key { repeat = False, [ Alt_L ] }; ``` @endfigure ### Real Modifier map {#modmap-statement} Bind a [*real* modifier](@ref real-modifier) to a key, e.g.: ```c // Bind the real modifier `Control` to the key `` and/or the first key with // the keysym `Control_L`. modifier_map Control { , Control_L }; ``` See [real modifier map] for further information. ### Set default values One may change the default values of the following statements: - `key`: use `key.FIELD = VALUE;`. E.g. `key.type = "ALPHABETIC";`. - `action`: use `ACTION_NAME.FIELD = VALUE;`. E.g. `setMods.clearLocks= True;`. ## Modifiers declaration and binding {#modifiers-declaration-and-binding} [modifiers declaration and binding]: @ref modifiers-declaration-and-binding ### Real and virtual modifiers [Modifiers] are a particularly tricky part of XKB and deserve their own section. For historical reasons they are divided in two categories:
Real modifier
They are the **8** *predefined* (AKA *core*, *X11*) modifiers: | Name | Index/Bit | Mask | Description | | --------- | --------- | ------ | -------------------------- | | `Shift` | 0 | `0x01` | Used to type upper case letters of [bicameral scripts]; keyboard shortcuts | | `Lock` | 1 | `0x02` | Used to type upper case letters of [bicameral scripts]: “Caps Lock” | | `Control` | 2 | `0x04` | Used in keyboard shortcuts | | `Mod1` | 3 | `0x08` | Generic modifier 1 | | `Mod2` | 4 | `0x10` | Generic modifier 2 | | `Mod3` | 5 | `0x20` | Generic modifier 3 | | `Mod4` | 6 | `0x40` | Generic modifier 4 | | `Mod5` | 7 | `0x80` | Generic modifier 5 | [bicameral scripts]: https://en.wikipedia.org/wiki/Letter_case#Bicameral_script They are the modifiers defined in the [*core* X11 protocol][X11 Core Protocol]. They are qualified as “real”, because in the XKB protocol they denote the *bits* that *encode* the modifiers state. See @ref modifiers-encoding "" for further information. Since they are predefined, they require no [explicit declaration](@ref virtual-modifier-statements) and have a *fixed* [encoding](@ref modifiers-encoding).
Virtual modifier
They are the modifiers that are *not* predefined. They require an [*explicit* declaration](@ref virtual-modifier-statements) and their [encoding](@ref modifiers-encoding) is *user-defined*. Note that in X11, the maximum of virtual modifiers is **16** (see `XkbNumVirtualMods`), whereas up to **24** virtual modifiers can be defined in libxkbcommon, for a total of **32** modifiers (real + virtual).
### Modifiers declarations {#virtual-modifier-statements} *Virtual* modifiers must be declared before their first use with the `virtual_modifiers` statement: - Declare a *single* modifier: ```c virtual_modifiers MyModifier; ``` - Declare *multiple* modifiers using a comma-separated list: ```c virtual_modifiers M1, M2, M3. ``` Furthermore, it is possible to set the [explicit modifier encoding] with the following syntax: - Use a *real* modifier mask: ```c // Single modifier: real modifier virtual_modifiers M1 = Mod3; // Single modifier: using mask as a plus-separated list virtual_modifiers M2 = Mod4+Mod5; // Multiple modifiers virtual_modifiers M1 = Mod3, M2 = Mod4+Mod5; ``` - Use a *numeric* mask: ```c virtual_modifiers M1 = 0x20; virtual_modifiers M2 = 0xC0; virtual_modifiers M1 = 0x20, M2 = 0xC0; ``` - Use `none`, an alias for `0`: ```c virtual_modifiers M1 = none; // Equivalent to: M1 = 0; ``` This can be done in the [`xkb_types`][xkb_types], [`xkb_compat`][xkb_compat] and [`xkb_symbols`][xkb_symbols] sections. ### Modifiers key bindings {#modifiers-bindings} [modifiers bindings]: @ref modifiers-bindings Each key has two **modifiers maps**:
*Real* modifier map
List the [*real* modifiers](@ref real-modifier) associated to the key. It is used as a compatibility layer for the X11 core protocol and to apply [interpretations]. See @ref set-real-mod-map "" for further information.
*Real* modifier map
List the [*virtual* modifiers](@ref virtual-modifier) associated to the key. It is used to set the [implicit encoding](@ref implicit-modifier-encoding) of virtual modifiers. See @ref set-virtual-mod-map "" for further information.
[real modifier map]: @ref real-modifier-map [real modifier maps]: @ref real-modifier-map [virtual modifier map]: @ref virtual-modifier-map #### Setting the real modifier map {#set-real-mod-map} The [real modifier map] is set in the [`xkb_symbols`][xkb_symbols] section using the `modifier_map` statement: - Bind *directly* to a **keycode**, e.g.: ```c // Bind `Mod1` to the keycode . modifier_map Mod1 { }; ``` - Bind *indirectly* via a **keysym**, e.g.: ```c // Bind `Mod1` looking up for the keysym `Alt_L` modifier_map Mod1 { Alt_L }; ``` Indirect bindings require to be resolved to a *single direct* bindings. Given a keysym, there can be multiple keys that generate it, so the corresponding key is chosen following this order: 1. by lowest group in which the keysym appears, 2. by lowest level, 3. by lowest key code. - Bind using a comma-separated **list** of keycodes and keysyms: ```c // Bind `Mod1` diretly to keycode and indirectly via the keysym `Alt_L` modifier_map Mod1 { , Alt_L }; ``` @note A key can be associated to _at most **one**_ real modifier. There is also a special entry, `None`, that enable *deleting* a previous entry: ```c modifier_map None { }; ``` @note `None` must use the *exact* same target (keycode or keysym) in order to delete the corresponding previous entry: ```c xkb_symbols { key { [Alt_L] }; modifier_map Mod1 { }; // Does *not* delete previous entry (expected keycode, got keysym) modifier_map None { Alt_L }; // *Does* delete previous entry (correct expected keycode) modifier_map None { }; }; ``` #### Setting the virtual modifier map {#set-virtual-mod-map} The [virtual modifier map] can be set in 2 ways: - *Directly* in the [`xkb_symbols`][xkb_symbols] section using the `virtualModifiers` key property: ```c xkb_symbols { // Virtual modifiers must be declared before use virtual_modifiers Alt; key { // Explicit virtual modifier map virtualModifiers = Alt, ... }; }; ``` - *Indirectly* using [interpretations] in [`xkb_compat`][xkb_compat] and the corresponding [`xkb_symbols`][xkb_symbols] keysyms: ```c xkb_compat { // Virtual modifiers must be declared before use virtual_modifiers Alt, Super; interpret Alt_L { // Bind the virtual modifier… virtualModifier = Alt; // … independently of the group and level (default) useModMap = AnyLevel; }; interpret Super_L { // Bind the virtual modifier… virtualModifier = Super; // … only if the keysym is on the first level of the first group useModMap = Level1; }; }; xkb_symbols { // Successful bindings key { [Alt_L] }; key { [No,Symbol, Alt_L] }; // independent of group and level key { [], [NoSymbol, Alt_L] }; // independent of group and level key { [Super_L] }; // Unsuccessful bindings key { [NoSymbol, Super_L] }; // requires first level key { [], [Super_L] }; // requires first group }; ``` ### Modifiers encoding {#modifiers-encoding} [modifier encoding]: @ref modifiers-encoding Each modifier has an associated **32 bit mask** used to *encode* it in the keyboard state. The keyboard state represents active modifiers with the bitwise OR of the encoding of each active modifiers. @note Display servers may use a different encoding in their protocols: - **Wayland protocol:** use the same *32-bit* encoding as libxkbcommon and support its full range of modifiers. - **X11 protocol:** use a *8-bit* encoding. It supports only using [real modifiers](@ref real-modifier) to encode [virtual modifiers](@ref virtual-modifier). @important - [Real modifiers](@ref real-modifier) have a *fixed predefined* encoding. - [Virtual modifiers](@ref virtual-modifier) have a *user-defined* encoding. Virtual modifiers require to be encoded by the user, *implicitly* (using the [auto mode](@ref auto-modifier-encoding) and/or the [legacy mode](@ref implicit-modifier-encoding)) and/or [*explicitly*](@ref explicit-modifier-encoding), the combination resulting in their [*effective*](@ref effective-modifier-encoding) encoding.
*Implicit* modifier encoding
Virtual modifiers *always* compute their implicit encoding, which is defined for a given virtual modifier by the bitwise OR of all the [real modifier maps] where the virtual modifier is in the [virtual modifier map] of the corresponding key. Example: ```c xkb_symbols { virtual_modifiers Alt; // Virtual modifier map: Alt is bound to // Note: alternatively one can use xkb_compat interpretations. key { virtualModifier = Alt }; // Real modifier map: Mod1 is bound to modifier_map Mod1 { }; // Implicit encoding: Alt = Mod1 }; ```
*Explicit* modifier encoding
Virtual modifiers can optionally define an initial mapping using the [`virtual_modifiers`](@ref virtual-modifier-statements) statements: ```c virtual_modifiers M1 = Mod1; // Single real modifier virtual_modifiers M2 = Mod4+Mod5;// Real modifier mask virtual_modifiers M3 = 0x400; // Numeric mask ``` See @ref virtual-modifier-statements "" for further information. @warning Although it is explicit, this may not be the [effective encoding][effective modifier encoding], detailed hereinafter.
*Effective* modifier encoding
The effective encoding is the bitwise OR of the [explicit modifier encoding] and the [implicit modifier encoding]. @note @anchor auto-modifier-encoding If using `::XKB_KEYMAP_FORMAT_TEXT_V2`, virtual modifiers that were not mapped either *implicitly* using the `virtualModifier`/`modifier_map` feature hereinabove or [*explicitly*](@ref explicit-modifier-encoding), then they are mapped to their [*canonical* mapping](@ref canonical-modifier-def). Example: ```c xkb_symbols { virtual_modifiers Alt, Meta, Super = none, Hyper = 0x1000, Useless = none; // Virtual modifier maps // Note: alternatively one can use xkb_compat interpretations. key { virtualModifier = Alt }; // Alt is bound to key { virtualModifier = Super }; // Super is bound to key { virtualModifier = Super }; // Super is bound to key { virtualModifier = Hyper }; // Hyper is bound to // Real modifier maps modifier_map Mod1 { }; // Mod1 is bound to modifier_map Mod4 { }; // Mod4 is bound to modifier_map Mod5 { }; // Mod5 is bound to modifier_map Mod3 { }; // Mod3 is bound to }; ```
Modifiers encoding of the previous example
Modifier Index Encoding
Canonical Explicit Implicit Effective
(xkbcommon) `::XKB_KEYMAP_FORMAT_TEXT_V1` `::XKB_KEYMAP_FORMAT_TEXT_V2`
Alt 8 `0x100` `Mod1` `Mod1` `Mod1`
Meta 9 `0x200` 0 (unmapped) `0x200` (canonical, xkbcommon value)
Super 10 `0x400` 0 `Mod4 + Mod5` `Mod4 + Mod5` `Mod4 + Mod5`
Hyper 11 `0x800` `0x1000` `0x1000` `0x1000`
Useless 12 `0x1000` 0 0 (unmapped) 0 (explicit mapping)
[explicit modifier encoding]: @ref explicit-modifier-encoding [implicit modifier encoding]: @ref implicit-modifier-encoding [effective modifier encoding]: @ref effective-modifier-encoding ### Canonical and non-canonical modifiers @anchor canonical-modifier-def A **canonical modifier** have an encoding defined by: `1 << mod_index`, where `mod_index` is: - Fixed for the *real* modifiers, in order to match the X11 values. See [real modifiers mapping](@ref real-modifier). - Implementation-dependent for the the *virtual* modifiers. See @ref xkbcommon-vmod-encoding "" for further details. [canonical modifier]: @ref canonical-modifier-def ### Usual modifiers and associated keysyms {#usual-modifiers-keysyms} The following table summarizes the modifiers defined in [`xkeyboard-config` 2.44][xkeyboard-config]: | Modifier | Type | Compat files | Associated keysyms | |--------------|---------|------------------|-----------------------------------------------------------| | `Shift` | Real | `compat/basic` | `Shift_L`, `Shift_R` | | ^ | ^ | `compat/iso9995` | `Shift_L`, `Shift_R`, `ISO_Level2_Latch` | | `Lock` | Real | `compat/basic`, | `Caps_Lock` | | ^ | ^ | `compat/caps` | ^ | | `Control` | Real | `compat/basic` | `Control_L`, `Control_R` | | `Alt` | Virtual | `compat/misc`, | `Alt_L`, `Alt_R` | | ^ | ^ | `compat/pc` | ^ | | `Meta` | Virtual | `compat/misc` | `Meta_L`, `Meta_R` | | `Super` | Virtual | `compat/misc` | `Super_L`, `Super_R` | | `Hyper` | Virtual | `compat/misc` | `Hyper_L`, `Hyper_R` | | `ScrollLock` | Virtual | `compat/misc` | `Scroll_Lock` | | `NumLock` | Virtual | `compat/basic`, | `Num_Lock`, | | ^ | ^ | `compat/level5` | (`ISO_Level5_Lock`) | | `LevelThree` | Virtual | `compat/iso9995` | `ISO_Level3_Shift`, `ISO_Level3_Latch`, `ISO_Level3_Lock` | | `LevelFive` | Virtual | `compat/level5` | `ISO_Level5_Shift`, `ISO_Level5_Latch`, `ISO_Level5_Lock` | | `Kana_Lock` | Virtual | `compat/japan` | `Kana_Lock` | | `Square` | Virtual | `compat/olpc` | `KP_Home` | | `Cross` | Virtual | `compat/olpc` | `KP_Next` | | `Circle` | Virtual | `compat/olpc` | `KP_End` | | `Triangle` | Virtual | `compat/olpc` | `KP_Prior` | ### Modifiers portability {#modifiers-portability} #### Avoid using numeric modifier masks @note Any field that accept virtual modifier *names* is a virtual modifier *mask*, denoting virtual modifiers *indices*. These indices are implementation-specific and should not be leaked. Therefore any *numeric* value used for these fields should be interpreted equally as a virtual modifier mask, and is thus implementation-specific. @important In order to preserve [modifier encoding] *portability*, XKB implementations are recommended to **avoid *numeric* modifier masks** and to **use virtual modifiers *names* whenever possible** when serializing the keymap. This avoids *leaking* the indices of the modifiers. #### xkbcomp and libxkbcommon implementations {#xkbcommon-vmod-encoding} @attention This section is not part of the keymap text format specification and presents libxkbcommon’s *implementation details* that may change, solely for the purpose of informing other XKB implementation. **Users should not rely on this!** Both X11 xkbcomp and libxkbcommon currently implement modifiers indices as follow: 1. Real modifiers have the following indices: @anchor real-modifier-indices | Name | Index | | --------- | ----- | | `Shift` | 0 | | `Lock` | 1 | | `Control` | 2 | | `Mod1` | 3 | | `Mod2` | 4 | | `Mod3` | 5 | | `Mod4` | 6 | | `Mod5` | 7 | 2. Virtual modifiers names are assigned to virtual modifier indices following their order of appearance in a keymap component, if that name was not previously assigned. 3. Indices are assigned in *ascending order*, from 0. 4. If an index is already assigned to a different name, then the next free index is used. 5. The order of the relevant keymap components used for virtual mods assignment is: 1. [xkb_types] 2. [xkb_compat] 3. [xkb_symbols] 6. A virtual modifier *mask* always denotes virtual modifiers *indices*. @note It suffices to declare all virtual modifiers in [xkb_types] \(or if empty, whatever non-empty section afterwards, in the order specified above) in their ascending indices order to use virtual modifiers indices **compatible with libxkbcommon**. ### Example: define and use a modifier, step by step We will use the example of the _real_ modifier `Shift` and the virtual modifier `LevelThree` in `xkeyboard-config`. In order to define and use a modifier, one must: 1. Define its behavior and [keysym] binding in the [xkb_compat] section: ```c // Declare virtual modifiers. Shift being real modifier, // we do not need to add it here. virtual_modifiers LevelThree; // Set defaults. They are overridden if set directly in the xkb_symbols. interpret.repeat= False; // only applied on first level setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; // Default statement for real modifiers: any key bound to a real // modifier via modifier_map will set this modifier at all its // levels. // Here only to illustrate: do not add it! interpret Any + Any { action= SetMods(modifiers=modMapMods); }; // Shift being real modifier, we do not need a corresponding // interpret statement because the previous one suffices. // Let’s associate LevelThree to the keysym ISO_Level3_Shift // First, match the keys and their levels with the // ISO_Level3_Shift keysym and with any real modifier // (Any = AnyOf(all)) in its modmap. interpret ISO_Level3_Shift+Any { // Only match the first level of the first group useModMapMods= level1; // Add the virtual modifier to the key’s vmodmap virtualModifier= LevelThree; // Activate the LevelThree modifier (depressed mode) action= SetMods(modifiers=LevelThree); }; // Then for keys and their levels with the // ISO_Level3_Shift keysym but with either no real modifier // in its modmap or a level higher than 1. // Indeed: // • In case the level is higher than 1 there is no match // in the previous statement. // • The condition is equivalent to // ISO_Level3_Shift+AnyOfOrNone(all), but since // the previous statement ISO_Level3_Shift+Any is more // specific, it will be matched before this one. interpret ISO_Level3_Shift { // Activate the LevelThree modifier (depressed mode) action= SetMods(modifiers=LevelThree); }; ``` 2. Define [key types] that use it in the [xkb_types] section: ```c // Declare virtual modifiers. Shift being real modifier, // we do not need to add it here. virtual_modifiers LevelThree; type "FOUR_LEVEL" { // Key type modifier mask: all the modifiers used in the key type modifiers = Shift + LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "AltGr"; level_name[Level4] = "Shift AltGr"; }; ``` 3. Bind it to a [keycode] in the [xkb_symbols] section: 1. Map [keysyms] used in the `xkb_compat` section hereinabove. 2. Bind [real modifiers] to keys using these keysyms with `modifier_map`. _Note:_ Only one key binding to real modifier is required. The corresponding keysym must then be on the first level of the first Group. _Note:_ One can optionally bind directly a virtual modifier to a key using `virtualmodifiers` instead of doing it in the `xkb_compat` section. But the recommended way is to use the `xkb_compat` section. ```c // Shift: defined in pc symbols key {[ Shift_L ]}; key {[ Shift_R ]}; modifier_map Shift { Shift_L, Shift_R }; // The previous will resolve to: // modifier_map Shift { , }; // Thus the real modifier Shift is added to the modmap of // and . // The “Any + Any” interpret statement matches and , // therefore these keys set the Shift modifier. // LevelThree: defined in pc symbols // With the following 2 lines: // 1. The modifier keysym is on the first level of the first group. // 2. The real modifier Mod5 is bound to , // i.e. Mod5 is added to its modmap. // 3. It matches the interpret statement “ISO_Level3_Shift+Any”, // which adds the LevelThree modifier to the vmodmap of . // 4. The mapping of LevelThree to real modifiers is the union // of modmaps with corresponding vmodmaps containing // LevelThree. In our case there is only one: therefore // LevelThree maps to Mod5. key {[ ISO_Level3_Shift ]}; modifier_map Mod5 { }; // LevelThree: defined in level3 symbols // Not bound to a real modifier, so interpret statement // “ISO_Level3_Shift” applies. key {[ISO_Level3_Shift], type[group1]="ONE_LEVEL" }; // Note: we could have the following line, but it is not necessary // because we have the mappings of . // modifier_map Mod5 { }; // Warning: if we had the for example the following line, the // mapping of LevelThree to real modifiers would be “Mod1+Mod5”. // modifier_map Mod1 { }; // Alternative definitions, without using interpret statements virtual_modifiers LevelThree; key { virtualmodifiers=LevelThree , repeats=False , symbols[Group1] = [ISO_Level3_Shift] , actions[Group1] = [SetMods(modifiers=LevelThree)] }; modifier_map Mod5 { }; key { repeat=False , symbols[Group1] = [ISO_Level3_Shift] , actions[Group1] = [SetMods(modifiers=LevelThree)] , type[group1]="ONE_LEVEL" }; // FOUR_LEVEL key type example from latin symbols key {[b, B, leftdoublequotemark, leftsinglequotemark]}; ``` ## Key actions {#key-actions} The following table provide an overview of the available actions: | Category | Action name | Alias | Description | |----------|---------------------|------------------|------------------------------------| | [Ineffectual action] | [`NoAction`][NoAction] | | **Default action**: *implicitly* do nothing | | ^ | [`VoidAction`][VoidAction] | | *Explicitly* do nothing | | [Modifier action] | [`SetMods`][SetMods] | | Modifies the [depressed] modifiers | | ^ | [`LatchMods`][Latchmods] | | Modifies the [latched] modifiers | | ^ | [`LockMods`][LockMods] | | Modifies the [locked] modifiers | | [Group action] | [`SetGroup`][SetGroup] | | Modifies the _base_ group | | ^ | [`LatchGroup`][LatchGroup] | | Modifies the _latched_ group | | ^ | [`LockGroup`][LockGroup] | | Modifies the _locked_ group | | [Legacy action] | `MovePointer`| `MovePtr` | Move the mouse pointer | | ^ | `PointerButton` | `PtrBtn` | Simulate a mouse button press | | ^ | `LockPointerButton` | `LockPtrBtn` | Simulate a mouse button press, locked until the action’s key is pressed again. | | ^ | `SetPointerDefault` | `SetPtrDflt` | Set the default select button (???)| | ^ | [`SetControls`][SetControls] | | Set the standard XKB controls | | ^ | [`LockControls`][LockControls] | | Lock the standard XKB controls | | ^ | [`TerminateServer`][TerminateServer] | `Terminate` | Shut down the X server | | ^ | `SwitchScreen` | | Switch virtual X screen | | ^ | [`Private`][Private]| | Raw encoding of an action | | [Unsupported legacy action]| [`RedirectKey`][redirectkey] | `Redirect` | Emulate pressing a key with a different key code | | ^ | `ISOLock` | | Convert ordinary modifier key actions into lock actions while this action is active | | ^ | `DeviceButton` | `DevBtn` | Emulate an event from an arbitrary input device such as a joystick | | ^ | `LockDeviceButton` | `LockDevBtn` | Emulate an event from an arbitrary input device such as a joystick | | ^ | `DeviceValuator` | `DevVal` | TODO | | ^ | `MessageAction` | `Message` | Generate an arbitrary special-purpose XKB event | Common syntax: - Boolean values: - `true`, `yes`, `on` - `false`, `no`, `off` ### Ineffectual actions {#ineffectual-actions} [ineffectual action]: @ref ineffectual-actions [NoAction]: @ref no-action [VoidAction]: @ref void-action
`NoAction` @anchor no-action
**Default action**: *implicitly* do nothing. Does *not* override previous actions and is dropped. No parameters.
`VoidAction` @anchor void-action
*Explicitly* do nothing. *Does* override previous actions and is not dropped. No parameters. @note This is a libxkbcommon *extension*. In order to maintain backward-compatibility, it serializes to `LockControls(controls=none,affect=neither)`. @since 1.10.0
### Modifiers actions {#modifiers-actions} [modifier action]: @ref modifiers-actions [modifier actions]: @ref modifiers-actions [SetMods]: @ref set-mods-action [LatchMods]: @ref latch-mods-action [LockMods]: @ref lock-mods-action There are 3 modifiers actions:
`SetMods` @anchor set-mods-action
Modifies the [depressed] modifiers.
Parameters
Name Aliases Data type Default value Description
`modifiers` `mods` Modifier mask `none` (0) The list of modifiers to modify, separated by `+`, or the special value `modMapMods`. The latter means the parameter value has to be read from the `vmodmap` attribute of the key.
`clearLocks` boolean `false` See its use [hereinafter](@ref set-modifier-action-effects)
`unlockOnPress` boolean `false` Control whether [locked] modifiers are unlocked on key press or release (default). See [hereinafter](@ref set-modifier-action-effects) for further details. @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
`LatchMods` @anchor latch-mods-action
Modifies the [latched] modifiers
Parameters
Name Aliases Data type Default value Description
`modifiers` `mods` Modifier mask `none` (0) see [`SetMods`][SetMods].
`clearLocks` boolean `false` See its use [hereinafter](@ref latch-modifier-action-effects)
`latchToLock` boolean `false` See its use [hereinafter](@ref latch-modifier-action-effects)
`latchOnPress` boolean `false` Control whether [latched] modifiers are latched on key press or release (default). See [hereinafter](@ref latch-modifier-action-effects) for further details. @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
`unlockOnPress` boolean `false` Control whether [locked] modifiers are unlocked on key press or release (default). See [hereinafter](@ref latch-modifier-action-effects) for further details. @note It is *implied* if both `latchOnPress=true` and `clearLocks=true`. @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
`LockMods` @anchor lock-mods-action
Modifies the [locked] modifiers.
Parameters
Name Aliases Data type Default value Description
`modifiers` `mods` Modifier mask `none` (0) see [`SetMods`][SetMods]
`affect` enumeration: - `lock` - `unlock` - `both` - `neither` `both` - `lock`: the action only locks the modifier, but cannot unlock it. - `unlock`: the action only unlocks modifier, but cannot lock it. - `both`: the first key press locks the modifier and the second key press releases the modifier.. - `neither`: do not lock nor unlock, i.e. do nothing.
`unlockOnPress` boolean `false` Control whether [locked] modifiers are unlocked on key press or release. See [hereinafter](@ref lock-modifier-action-effects) for further details. @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
@todo highlight that there is reference counting for the modifiers, e.g. to manage multiple physical keys for the same modifier. These actions perform different tasks on key press and on key release:
Effects of modifiers actions @anchor modifier-actions-effects
Action On key press On key release
`SetMods` @anchor latch-modifier-action-effects - If `clearLocks` and `unlockOnPress` are true, unlock the target modifiers. - Adds modifiers to [depressed] modifiers that were not unlocked. - Removes modifiers added on press from [depressed] modifiers, provided that no other key which affects the same modifiers is logically down. - If `clearLocks` is true, `unlockOnPress` is false and no other key were operated simultaneously with this key, then the modifiers will be removed as well from the [locked] modifiers.
`LatchMods` @anchor set-modifier-action-effects - If `unLockOnPress` and `clearLocks` are true and target modifiers were locked, then unlocks them and clear the action. - Otherwise if `latchOnPress` is true, then adds modifiers to the [latched] modifiers. - Otherwise adds modifiers to [depressed] modifiers. - If `latchOnPress` is false, then: - Removes modifiers from [depressed] modifiers. - If no keys were operated simultaneously with the latching modifier key: - If `clearLocks` is true and `unLockOnPress` is false and target modifiers were locked, then unlock then stop here and clear the action. - Otherwise add modifiers to [latched] modifiers. - If `latchToLock` is true and if the target modifiers are latched, then unlatch them and [lock][locked] them. - Latch target modifiers that were not used by `clearLocks` and `latchToLock`. - Otherwise unlatch the target modifiers and clear the action.
`LockMods` @anchor lock-modifier-action-effects - If `unlockOnPress` is true and some of the target modifiers were [locked] before the key press, then unlock them if `noUnlock` false. - Otherwise: - add target modifiers to [depressed] modifiers; - if `noLock` is false, add target modifiers to the [locked] modifiers. - If `unlockOnPress` is true and triggered unlocking on key press, do nothing. - Otherwise: - remove modifiers from the [depressed] modifiers, if no other key that affect the same modifiers is down; - if `noUnlock` is false and if any target modifiers was locked before the key press, *[unlock][locked]* them.
### Group actions {#group-actions} [group action]: @ref group-actions [group actions]: @ref group-actions [SetGroup]: @ref set-group-action [LatchGroup]: @ref latch-group-action [LockGroup]: @ref lock-group-action There are 3 group actions:
`SetGroup` @anchor set-group-action
Modifies the *base* group.
Parameters
Name Data type Default value Description
`group` Group index: - 1-based numbering - either absolute (no sign) or relative (`+`/`-` sign) 0 Target group or group delta
`clearLocks` boolean `false` See its use [hereinafter](@ref set-group-action-effects)
`LatchGroup` @anchor latch-group-action
Modifies the *latched* group.
Parameters
Name Data type Default value Description
`group` Group index (see [`SetGroup`][SetGroup]) 0 Target group or group delta
`clearLocks` boolean `false` See its use [hereinafter](@ref latch-group-action-effects)
`latchToLock` boolean `false` See its use [hereinafter](@ref latch-group-action-effects)
`LockGroup` @anchor lock-group-action
Modifies the *locked* group.
Parameters
Name Data type Default value Description
`group` Group index (see [`SetGroup`][SetGroup]) 0 Target group or group delta
`lockOnRelease` boolean false Control whether to trigger the group change on key press (default) or release. See further details [hereinafter](@ref lock-group-action-effects) @note Available since 1.11, only with `::XKB_KEYMAP_FORMAT_TEXT_V2`.
Effects of group actions
Action On key press On key release
`SetGroup` @anchor set-group-action-effects - If the `group` parameter is *absolute*, key press events sets the *base* keyboard group to `group`. - Otherwise, it adds `group` to the *base* keyboard group. In either case, the resulting *effective* keyboard group is brought back into range depending on the value of the `GroupsWrap` control for the keyboard. If *no* keys were operated simultaneously with this key and the `clearLocks` parameter is set, key release also sets the *locked* keyboard group to `Group1`.
`LatchGroup` @anchor latch-group-action-effects Same as `SetGroup`. Same as `SetGroup`. If no keys were operated simultaneously with the latching group key and the `clearLocks` parameter was not set or had no effect, key release has the following additional effects: - If `latchToLock` parameter is set and the *latched* keyboard group is not the first group, the key release adds the *delta* applied by the corresponding key press to the locked keyboard group and subtracts it from the latched keyboard group. The *locked* and *effective* keyboard group are brought back into range according to the value of the global `GroupsWrap` control for the keyboard. - Otherwise, key release adds the key press *delta* to the latched keyboard group.
`LockGroup` @anchor lock-group-action-effects - If `lockOnRelease` is set, then key press has no effect. - Otherwise: - if the `group` is absolute, key press sets the *locked* keyboard group to `group`; - otherwise, key press adds `group` to the *locked* keyboard group. In either case, the resulting *locked* and *effective* group is brought back into range depending on the value of the `GroupsWrap` control for the keyboard. - If `lockOnRelease` is not set, then key release has no effect. - Otherwise, if any other key was *pressed* after the locking key, then key release has no effect.
This enables e.g. using `Alt+Shift` combination in any order. - `Shift` down, `Alt` down, `Alt` up, `Shift` up - `Shift` down, `Alt` down, `Shift` up, `Alt` up - `Alt` down, `Shift` down, `Shift` up, `Alt` up - `Alt` down, `Shift` down, `Alt` up, `Shift` up This would not be possible if locking was cancelled by key *release* too.
- Otherwise, it has the same effect than a key press *without* `lockOnRelease` set.
### Legacy X11 actions {#legacy-x11-actions} [legacy action]: @ref legacy-x11-actions @attention The following legacy actions are kept for compatibility only: they are parsed and validated but have no effect. This allows to use keymaps defined in [xkeyboard-config] for both X11 and Wayland. #### Pointer actions
`MovePointer`
`MovePtr`
Move the mouse pointer @todo MovePointer parameters
`PointerButton`
`PtrBtn`
Simulate a mouse button press @todo PointerButton parameters
`LockPointerButton`
`LockPointerBtn`
`LockPtrButton`
`LockPtrBtn`
Simulate a mouse button press, locked until this actiion’s key is pressed again @todo LockPointerButton parameters
`SetPointerDefault`
`SetPtrDflt`
Set the default select button (???) @todo SetPointerDefault parameters
#### Control flags actions [SetControls]: @ref set-controls-action [LockControls]: @ref lock-controls-action
`SetControls` @anchor set-controls-action
Set the standard XKB controls
Parameters
Name Alias Data type Default value Description
`controls` `ctrls` Mask of the following enumeration: - `RepeatKeys` - `Repeat` - `AutoRepeat` - `SlowKeys` - `BounceKeys` - `StickyKeys` - `MouseKeys` - `MouseKeysAccel` - `AccessXKeys` - `AccessXTimeout` - `AccessXFeedback` - `AudibleBell` - `IgnoreGroupLock` - `Overlay1` - `Overlay2` Plus 2 special values: - `all` - `none` 0 Standard XKB controls
`LockControls` @anchor lock-controls-action
Lock the standard XKB controls
Parameters
Name Alias Data type Default value Description
`controls` `ctrls` Mask (see [`SetControls`][SetControls]) 0 Standard XKB controls
`affect` enumeration: - `lock` - `unlock` - `both` - `neither` `both` TODO
#### Server actions [TerminateServer]: @ref terminate-server-action
`TerminateServer` @anchor terminate-server-action
Shut down the X server No parameters.
`SwitchScreen`
@todo SwitchScreen
#### Private action {#private-action} [Private]: @ref private-action Raw encoding of an action. Aimed to support arbitrary action unknown to the XKB compiler. @warning This assumes that the corresponding action’s C `struct` is laid out in memory exactly as described in the XKB specification and libraries. However, libxkbcommon have changed these `struct`s in various ways, so this assumption is no longer true and the actions defined in the XKB protocol are unsupported.
Parameters
Name Data type Default value Description
`type` integer 0 Action type, as encoded in the XKB protocol
`data` byte array or a string of *exactly 7 bytes* "0000000" Raw byte encoding of the action following the XKB protocol
Examples: - `Private(type=123, data="abcdefg");` - `Private(type=123, data[1]=0, data[2]=100, data[3]=12);` ### Unsupported legacy X11 actions {#unsupported-legacy-x11-actions} [unsupported legacy action]: @ref unsupported-legacy-x11-actions @attention The following legacy actions are **unsupported**: they are parsed and but *not validated* and are then completely *ignored*. #### Redirect key {#redirect-key-action} [redirectkey]: @ref redirect-key-action `RedirectKey` emulates pressing a key with a different key code. `RedirectKey` normally redirects to another key on the *same device* as the key or button which caused the event, else on the *core* keyboard device.
Parameters
Name Aliases Data type Default value Description
`key` `keycode`, `kc` keycode 0 Target keycode to emulate
`clearmodifiers` `clearmods` modifier mask `none` (0) Modifiers to clear
`modifiers` `mods` modifier mask `none` (0) Modifiers to add
Effects
On key *press* On key *release*
Key press causes a key press event for the key specified by the `key` parameter instead of for the actual key. The state reported in this event reports of the current *effective* modifiers changed as follow: - Modifiers in the `clearmodifiers` parameter are cleared. - Modifiers in the `modifiers` parameter are set. Key release causes a key release event for the key specified by the `key` parameter; the state field for this event consists of the *effective* modifiers at the time of the release, changed as described on the key press.
#### ISO lock @todo `ISOLock` #### Device actions
`DeviceButton`
@todo DeviceButton
`LockDeviceButton`
@todo LockDeviceButton
`DeviceValuator`
@todo DeviceValuator
#### Message @todo `ActionMessage` ## The “xkb_geometry” section {#the-xkb_geometry-section} This section aims to describe the *physical* layout of a keyboard and its main use case is to produce a picture of the keyboard via e.g. the `xkbprint` program. @warning libxkbcommon does not support this section: while it can parse the syntax, it does not interpret it; the section is simply dropped so there is no API to query it and the keymap serialization does not contain it. @sa @ref geometry-support "Compatibility with X11". xkbcommon-libxkbcommon-54ee7ac/doc/license.md000066400000000000000000000000651510033435100213750ustar00rootroot00000000000000# License {#detailed-license} @include{txt} LICENSE xkbcommon-libxkbcommon-54ee7ac/doc/message-registry.md000066400000000000000000000750451510033435100232570ustar00rootroot00000000000000# Error index {#error-index} This page lists the warnings and errors generated by xkbcommon. There are currently 74 entries. @todo The documentation of the log messages is a work in progress. ## Index {#error-code-list} | Code | Identifier | Description | Type | | --------- | ---------------------------- | ----------- | ---- | | [XKB-034] | `malformed-number-literal` | Warn on malformed number literals | Error | | [XKB-043] | `conflicting-key-type-preserve-entries` | Conflicting “preserve” entries in a key type | Warning | | [XKB-052] | `integer-overflow` | The result of the operation is not mathematically correct | Error | | [XKB-060] | `unsupported-modifier-mask` | Warn on unsupported modifier mask | Error | | [XKB-077] | `expected-array-entry` | Expected an array entry, but the index is missing | Error | | [XKB-082] | `invalid-numeric-keysym` | Invalid numeric keysym | Error | | [XKB-101] | `illegal-keycode-alias` | Illegal keycode alias with the name of a real key | Warning | | [XKB-107] | `unrecognized-keysym` | Warn on unrecognized keysyms | Warning | | [XKB-123] | `undeclared-virtual-modifier` | A virtual modifier is used before being declared | Error | | [XKB-134] | `insufficient-buffer-size` | A buffer has an insufficient size | Error | | [XKB-150] | `wrong-statement-type` | The type of the statement is not allowed in the context | Error | | [XKB-161] | `invalid-path` | The given path is invalid | Error | | [XKB-172] | `unsupported-geometry-section` | Geometry sections are not supported | Warning | | [XKB-183] | `cannot-infer-key-type` | Warn if no key type can be inferred | Warning | | [XKB-193] | `invalid-escape-sequence` | Invalid escape sequence in a string | Warning | | [XKB-195] | `illegal-key-type-preserve-result` | The result of a key type “preserve” entry must be a subset of its input modifiers. | Warning | | [XKB-203] | `invalid-include-statement` | Syntax error in the include statement | Error | | [XKB-206] | `invalid-modmap-entry` | A modmap entry is invalid | Error | | [XKB-237] | `unsupported-group-index` | Warn when a group index is not supported | Error | | [XKB-239] | `conflicting-key-type-level-names` | The name of a key type level is defined multiple times. | Warning | | [XKB-254] | `invalid-set-default-statement` | Invalid statement setting default values | Error | | [XKB-266] | `conflicting-key-type-map-entry` | Conflicting “map” entries in type definition | Warning | | [XKB-286] | `undefined-key-type` | Warn if using an undefined key type | Warning | | [XKB-301] | `deprecated-keysym` | A keysym has been deprecated: consider using an alternative keysym | Warning | | [XKB-302] | `deprecated-keysym-name` | A keysym name has been deprecated: use the corresponding canonical name instead | Warning | | [XKB-305] | `non-base-group-name` | Warn if a group name was defined for group other than the first one | Warning | | [XKB-312] | `unsupported-shift-level` | Warn when a shift level is not supported | Error | | [XKB-338] | `included-file-not-found` | Could not find a file used in an include statement | Error | | [XKB-345] | `unknown-operator` | Use of an operator that is unknown and thus unsupported | Error | | [XKB-362] | `unsupported-legacy-action` | Use of a legacy X11 action that is not supported | Warning | | [XKB-378] | `duplicate-entry` | An entry is duplicated and will be ignored | Warning | | [XKB-386] | `recursive-include` | Included files form cycle | Error | | [XKB-407] | `conflicting-key-type-definitions` | Conflicting definitions of a key type | Warning | | [XKB-428] | `global-defaults-wrong-scope` | A global defaults statement is in a wrong scope and should be moved | Error | | [XKB-433] | `missing-default-section` | Missing default section in included file | Warning | | [XKB-461] | `conflicting-key-symbol` | Warn if there are conflicting keysyms while merging keys | Warning | | [XKB-478] | `invalid-operation` | The operation is invalid in the context | Error | | [XKB-489] | `numeric-keysym` | Warn on numeric keysym (other than 0-9) | Warning | | [XKB-516] | `extra-symbols-ignored` | TODO: add description | Warning | | [XKB-523] | `conflicting-key-name` | Conflicting definitions of a key name or alias | Warning | | [XKB-542] | `invalid-file-encoding` | Invalid file encoding | Error | | [XKB-550] | `allocation-error` | Cannot allocate memory | Error | | [XKB-563] | `invalid-action-field` | Unknown or unsupported action field | Error | | [XKB-578] | `wrong-field-type` | Warn when a field has not the expected type | Error | | [XKB-595] | `cannot-resolve-rmlvo` | Cannot resolve a given (Rules, Model, Layout, Variant, Options) configuration | Error | | [XKB-607] | `invalid-unicode-escape-sequence` | Invalid Unicode escape sequence | Warning | | [XKB-623] | `invalid-real-modifier` | Invalid _real_ modifier | Error | | [XKB-639] | `unknown-default-field` | Cannot set default value to a an unknown field | Error | | [XKB-645] | `unknown-char-escape-sequence` | Warn on unknown escape sequence in string literal | Warning | | [XKB-661] | `invalid-included-file` | The target file of an include statement could not be processed | Error | | [XKB-679] | `invalid-compose-locale` | Invalid locale for Compose | Error | | [XKB-685] | `invalid-compose-syntax` | The Compose file syntax is invalid and the entry cannot be parsed | Error | | [XKB-693] | `incompatible-actions-and-keysyms-count` | A level has a different number of keysyms and actions | Error | | [XKB-700] | `multiple-groups-at-once` | Warn if a key defines multiple groups at once | Warning | | [XKB-711] | `unsupported-symbols-field` | A legacy X11 symbol field is not supported | Warning | | [XKB-742] | `incompatible-keymap-text-format` | The keymap has features unsupported in the target format | Error | | [XKB-762] | `rules-invalid-layout-index-percent-expansion` | Cannot expand `%%i`: missing layout or variant in MLVO rule fields | Error | | [XKB-769] | `invalid-xkb-syntax` | The XKB syntax is invalid and the file cannot be parsed | Error | | [XKB-770] | `undefined-keycode` | Reference to an undefined keycode | Warning | | [XKB-784] | `invalid-expression-type` | An expression has not the expected type | Error | | [XKB-796] | `invalid-value` | A value is invalid and will be ignored | Error | | [XKB-800] | `conflicting-modmap` | Warn if there are conflicting modmap definitions | Warning | | [XKB-812] | `unknown-field` | A field is unknown and will be ignored | Error | | [XKB-822] | `keymap-compilation-failed` | Keymap compilation failed | Error | | [XKB-844] | `unknown-action-type` | Unknown action type | Error | | [XKB-883] | `conflicting-key-action` | Warn if there are conflicting actions while merging keys | Warning | | [XKB-893] | `conflicting-key-type-merging-groups` | Warn if there are conflicting key types while merging groups | Warning | | [XKB-901] | `conflicting-key-symbols-entry` | Conflicting symbols entry for a key | Error | | [XKB-903] | `missing-symbols-group-name-index` | Missing group index in a group name entry | Warning | | [XKB-935] | `conflicting-key-fields` | Warn if there are conflicting fields while merging keys | Warning | | [XKB-949] | `invalid-identifier` | An identifier is used but is not built-in | Error | | [XKB-965] | `unresolved-keymap-symbol` | Warn if using a symbol not defined in the keymap | Warning | | [XKB-967] | `invalid-rules-syntax` | The rules syntax is invalid and the file cannot be parsed | Error | | [XKB-971] | `undeclared-modifiers-in-key-type` | Some modifiers used in a key type “map” or “preserve” entry are not declared | Warning | ## Details ### XKB-034 – Malformed number literal {#XKB-034}
Since
1.0.0
Type
Error
Summary
Warn on malformed number literals
xkbcommon can parse the following number literal formats: - *decimal integer:* 1, 123, etc. - *decimal floating-point number:* 1.23, etc. - *hexadecimal integer:* prefixed with “0x”: 0x123, 0xff, 0xAB, etc. ### XKB-043 – Conflicting key type preserve entries {#XKB-043}
Since
1.0.0
Type
Warning
Summary
Conflicting “preserve” entries in a key type
### XKB-052 – Integer overflow {#XKB-052}
Since
1.10.0
Type
Error
Summary
The result of the operation is not mathematically correct
The result of the operation is not representable in the corresponding datatype and overflowed. ### XKB-060 – Unsupported modifier mask {#XKB-060}
Since
1.0.0
Type
Error
Summary
Warn on unsupported modifier mask
### XKB-077 – Expected array entry {#XKB-077}
Since
1.0.0
Type
Error
Summary
Expected an array entry, but the index is missing
### XKB-082 – Invalid numeric keysym {#XKB-082}
Since
1.0.0
Type
Error
Summary
Invalid numeric keysym
Keysyms are 32-bit integers with the 3 most significant bits always set to zero. Thus valid keysyms are in the range `0 .. 0x1fffffff` = @ref XKB_KEYSYM_MAX. See: Appendix A [“KEYSYM Encoding”][encoding] of the X Window System Protocol. [encoding]: https://www.x.org/releases/current/doc/xproto/x11protocol.html#keysym_encoding @see keysyms ### XKB-101 – Illegal keycode alias {#XKB-101}
Since
1.0.0
Type
Warning
Summary
Illegal keycode alias with the name of a real key
### XKB-107 – Unrecognized keysym {#XKB-107}
Since
1.0.0
Type
Warning
Summary
Warn on unrecognized keysyms
xkbcommon replaces keysyms it does not recognize by the keysym `NoSymbol`. You may find the list of supported keysyms in `include/xkbcommon/xkbcommon-keysyms.h`. #### Examples
Unrecognized keysym “`coma`” **Error message:** ``` xkbcommon: WARNING: [XKB-107] de:31:20: unrecognized keysym "coma" ``` xkbcommon does not recognize the keysym “`coma`”. It is most probably a typo for “comma”. See: `XKB_KEY_comma` in `include/xkbcommon/xkbcommon-keysyms.h`. **Fix:**
Before
```c key {[ coma, semicolon, periodcentered, multiply ]}; ```
After
```c key {[ comma, semicolon, periodcentered, multiply ]}; ```
### XKB-123 – Undeclared virtual modifier {#XKB-123}
Since
1.0.0
Type
Error
Summary
A virtual modifier is used before being declared
### XKB-134 – Insufficient buffer size {#XKB-134}
Since
1.0.0
Type
Error
Summary
A buffer has an insufficient size
### XKB-150 – Wrong statement type {#XKB-150}
Since
1.0.0
Type
Error
Summary
The type of the statement is not allowed in the context
### XKB-161 – Invalid path {#XKB-161}
Since
1.0.0
Type
Error
Summary
The given path is invalid
### XKB-172 – Unsupported geometry section {#XKB-172}
Since
1.0.0
Type
Warning
Summary
Geometry sections are not supported
### XKB-183 – Cannot infer key type {#XKB-183}
Since
1.0.0
Type
Warning
Summary
Warn if no key type can be inferred
### XKB-193 – Invalid escape sequence {#XKB-193}
Since
1.0.0
Type
Warning
Summary
Invalid escape sequence in a string
### XKB-195 – Illegal key type preserve result {#XKB-195}
Since
1.0.0
Type
Warning
Summary
The result of a key type “preserve” entry must be a subset of its input modifiers.
### XKB-203 – Invalid include statement {#XKB-203}
Since
1.0.0
Type
Error
Summary
Syntax error in the include statement
### XKB-206 – Invalid modmap entry {#XKB-206}
Since
1.0.0
Type
Error
Summary
A modmap entry is invalid
### XKB-237 – Unsupported group index {#XKB-237}
Since
1.0.0
Type
Error
Summary
Warn when a group index is not supported
xkbcommon supports different *group index* ranges, depending of the target *keymap format*: - `::XKB_KEYMAP_FORMAT_TEXT_V1`: 1..4 - `::XKB_KEYMAP_FORMAT_TEXT_V2`: 1..32 ### XKB-239 – Conflicting key type level names {#XKB-239}
Since
1.0.0
Type
Warning
Summary
The name of a key type level is defined multiple times.
### XKB-254 – Invalid set default statement {#XKB-254}
Since
1.0.0
Type
Error
Summary
Invalid statement setting default values
### XKB-266 – Conflicting key type map entry {#XKB-266}
Since
1.0.0
Type
Warning
Summary
Conflicting “map” entries in type definition
### XKB-286 – Undefined key type {#XKB-286}
Since
1.0.0
Type
Warning
Summary
Warn if using an undefined key type
### XKB-301 – Deprecated keysym {#XKB-301}
Since
1.8.0
Type
Warning
Summary
A keysym has been deprecated: consider using an alternative keysym
Some keysyms have ambiguous meaning. It is advised to migrate to an alternative keysym if possible, as deprecated keysyms may be removed in the future. Consider using Unicode keysyms (`Unnnn`) if relevant. ### XKB-302 – Deprecated keysym name {#XKB-302}
Since
1.8.0
Type
Warning
Summary
A keysym name has been deprecated: use the corresponding canonical name instead
Some keysym names have typos, unconventional names or are historical aliases. Please consider migrating to the reference name reported in the warning message. ### XKB-305 – Non base group name {#XKB-305}
Since
1.0.0
Type
Warning
Summary
Warn if a group name was defined for group other than the first one
### XKB-312 – Unsupported shift level {#XKB-312}
Since
1.0.0
Type
Error
Summary
Warn when a shift level is not supported
Shift levels are _one_-indexed. xkbcommon supports two formats of shift levels: as numbers and as identifiers `LevelN`, where `N` is in the range (1..8). ### XKB-338 – Included file not found {#XKB-338}
Since
1.0.0
Type
Error
Summary
Could not find a file used in an include statement
### XKB-345 – Unknown operator {#XKB-345}
Since
1.0.0
Type
Error
Summary
Use of an operator that is unknown and thus unsupported
### XKB-362 – Unsupported legacy action {#XKB-362}
Since
1.10.0
Type
Warning
Summary
Use of a legacy X11 action that is not supported
This action will be treated as `NoAction()`. See @ref unsupported-legacy-x11-actions "" for further information. ### XKB-378 – Duplicate entry {#XKB-378}
Since
1.0.0
Type
Warning
Summary
An entry is duplicated and will be ignored
### XKB-386 – Recursive include {#XKB-386}
Since
1.7.0
Type
Error
Summary
Included files form cycle
### XKB-407 – Conflicting key type definitions {#XKB-407}
Since
1.0.0
Type
Warning
Summary
Conflicting definitions of a key type
The given key type is defined multiple times, but only one definition is kept. ### XKB-428 – Global defaults wrong scope {#XKB-428}
Since
1.0.0
Type
Error
Summary
A global defaults statement is in a wrong scope and should be moved
#### Examples
Default key type in key statement **Error message:** ``` xkbcommon: ERROR: [XKB-428] Cannot set global defaults for "type" element within a key statement: move statements to the global file scope. Assignment to "key.type" ignored. ``` **Fix:**
Before
```c key { key.type = "FOUR_LEVEL_SEMIALPHABETIC", symbols = [q, Q, at] }; ```
After
```c // Either put default key type in global file scope key.type = "FOUR_LEVEL_SEMIALPHABETIC"; key { [q, Q, at] }; // or use a local setting (unqualified, i.e. without `key.`) key { type = "FOUR_LEVEL_SEMIALPHABETIC", symbols = [ q, Q, at ] }; ```
### XKB-433 – Missing default section {#XKB-433}
Since
1.0.0
Type
Warning
Summary
Missing default section in included file
When using an include statement, the included file may contains multiple sections. The include statement may specify the name of the section to include, or leave it unspecified. In the latter case, the included file must then define a *default* section. The present warning is shown when no default section is defined. To solve this, either fix the include statement by specifying the exact section to include, or declare a default section in the included file. ### XKB-461 – Conflicting key symbol {#XKB-461}
Since
1.0.0
Type
Warning
Summary
Warn if there are conflicting keysyms while merging keys
### XKB-478 – Invalid operation {#XKB-478}
Since
1.0.0
Type
Error
Summary
The operation is invalid in the context
### XKB-489 – Numeric keysym {#XKB-489}
Since
1.6.0
Type
Warning
Summary
Warn on numeric keysym (other than 0-9)
Numeric keysyms are not human-friendly. Use the corresponding named keysym or Unicode keysym, if available. #### Examples
Hexadecimal keysym `0x1001ed0` **Error message:** ``` xkbcommon: WARNING: [XKB-489] numeric keysym "0x1001ed0" ``` **Fix:**
Before
```c key { [ 0x1001ed0] }; ```
After
```c // Preferred form: human-friendly key { [ Ocircumflexacute ] }; // or key { [ U1ED0 ] }; ```
### XKB-516 – Extra symbols ignored {#XKB-516}
Since
1.0.0
Type
Warning
Summary
TODO: add description
### XKB-523 – Conflicting key name {#XKB-523}
Since
1.0.0
Type
Warning
Summary
Conflicting definitions of a key name or alias
### XKB-542 – Invalid file encoding {#XKB-542}
Since
1.7.0
Type
Error
Summary
Invalid file encoding
### XKB-550 – Allocation error {#XKB-550}
Since
1.0.0
Type
Error
Summary
Cannot allocate memory
### XKB-563 – Invalid action field {#XKB-563}
Since
1.0.0
Type
Error
Summary
Unknown or unsupported action field
### XKB-578 – Wrong field type {#XKB-578}
Since
1.0.0
Type
Error
Summary
Warn when a field has not the expected type
### XKB-595 – Cannot resolve rmlvo {#XKB-595}
Since
1.0.0
Type
Error
Summary
Cannot resolve a given (Rules, Model, Layout, Variant, Options) configuration
### XKB-607 – Invalid unicode escape sequence {#XKB-607}
Since
1.9.0
Type
Warning
Summary
Invalid Unicode escape sequence
xkbcommon support the Unicode sequence `\u{NNNN}`, where `NNNN` denotes a Unicode code point in hexadecimal format in the range `1‥0x10ffff`. ### XKB-623 – Invalid real modifier {#XKB-623}
Since
1.0.0
Type
Error
Summary
Invalid _real_ modifier
### XKB-639 – Unknown default field {#XKB-639}
Since
1.10.0
Type
Error
Summary
Cannot set default value to a an unknown field
### XKB-645 – Unknown char escape sequence {#XKB-645}
Since
1.0.0
Type
Warning
Summary
Warn on unknown escape sequence in string literal
xkbcommon support the following escape sequences in string literals: | Escape sequence | Corresponding character | | --------------- | ---------------------------------------------------------- | | `\b` | `U+0008` Backspace | | `\t` | `U+0009` Character tabulation | | `\n` | `U+000A` Line feed | | `\v` | `U+000B` Vertical tabulation | | `\f` | `U+000C` Form feed | | `\r` | `U+000D` Carriage return | | `\e` | `U+001B` Escape | | `\\` | `U+005C` Backslash | | `\"` | `U+0022` Double quote | | `\NNNN` | _Octal_ escape, `NNNN` in range `1‥0o377` | | `\u{NNNN}` | _Unicode_ hexadecimal escape, `NNNN` in range `1‥0x10ffff` | ### XKB-661 – Invalid included file {#XKB-661}
Since
1.0.0
Type
Error
Summary
The target file of an include statement could not be processed
### XKB-679 – Invalid compose locale {#XKB-679}
Since
1.12.0
Type
Error
Summary
Invalid locale for Compose
The locale is either invalid (not installed on the system) or not registered in the X11 Compose registry. ### XKB-685 – Invalid compose syntax {#XKB-685}
Since
1.0.0
Type
Error
Summary
The Compose file syntax is invalid and the entry cannot be parsed
### XKB-693 – Incompatible actions and keysyms count {#XKB-693}
Since
1.8.0
Type
Error
Summary
A level has a different number of keysyms and actions
A level must have exactly the same number of keysyms and actions. ### XKB-700 – Multiple groups at once {#XKB-700}
Since
1.0.0
Type
Warning
Summary
Warn if a key defines multiple groups at once
### XKB-711 – Unsupported symbols field {#XKB-711}
Since
1.0.0
Type
Warning
Summary
A legacy X11 symbol field is not supported
### XKB-742 – Incompatible keymap text format {#XKB-742}
Since
1.11.0
Type
Error
Summary
The keymap has features unsupported in the target format
See @ref keymap-support "" for further details. ### XKB-762 – Rules invalid layout index percent expansion {#XKB-762}
Since
1.11.0
Type
Error
Summary
Cannot expand `%%i`: missing layout or variant in MLVO rule fields
In a @ref rule-file-format "rules file", `%%i` denotes the index of the matched layout. It can only be used in the [KcCGST] value of the rule if the layout or variant is defined in the [MLVO] fields of the rule header. Otherwise the rule is always discarded. To fix the error, either remove the `:%%i` specifier or add a the relevant [MLVO] field, e.g. `layout[any]`. [KcCGST]: @ref KcCGST-intro [MLVO]: @ref RMLVO-intro ### XKB-769 – Invalid xkb syntax {#XKB-769}
Since
1.0.0
Type
Error
Summary
The XKB syntax is invalid and the file cannot be parsed
See @ref keymap-text-format-v1-v2 "" for further details. ### XKB-770 – Undefined keycode {#XKB-770}
Since
1.0.0
Type
Warning
Summary
Reference to an undefined keycode
### XKB-784 – Invalid expression type {#XKB-784}
Since
1.0.0
Type
Error
Summary
An expression has not the expected type
### XKB-796 – Invalid value {#XKB-796}
Since
1.0.0
Type
Error
Summary
A value is invalid and will be ignored
### XKB-800 – Conflicting modmap {#XKB-800}
Since
1.0.0
Type
Warning
Summary
Warn if there are conflicting modmap definitions
@todo detailed explanation and examples ### XKB-812 – Unknown field {#XKB-812}
Since
1.0.0
Type
Error
Summary
A field is unknown and will be ignored
### XKB-822 – Keymap compilation failed {#XKB-822}
Since
1.0.0
Type
Error
Summary
Keymap compilation failed
### XKB-844 – Unknown action type {#XKB-844}
Since
1.0.0
Type
Error
Summary
Unknown action type
See @ref key-actions "" for the list of supported actions. ### XKB-883 – Conflicting key action {#XKB-883}
Since
1.0.0
Type
Warning
Summary
Warn if there are conflicting actions while merging keys
### XKB-893 – Conflicting key type merging groups {#XKB-893}
Since
1.0.0
Type
Warning
Summary
Warn if there are conflicting key types while merging groups
### XKB-901 – Conflicting key symbols entry {#XKB-901}
Since
1.0.0
Type
Error
Summary
Conflicting symbols entry for a key
### XKB-903 – Missing symbols group name index {#XKB-903}
Since
1.0.0
Type
Warning
Summary
Missing group index in a group name entry
### XKB-935 – Conflicting key fields {#XKB-935}
Since
1.0.0
Type
Warning
Summary
Warn if there are conflicting fields while merging keys
### XKB-949 – Invalid identifier {#XKB-949}
Since
1.0.0
Type
Error
Summary
An identifier is used but is not built-in
### XKB-965 – Unresolved keymap symbol {#XKB-965}
Since
1.0.0
Type
Warning
Summary
Warn if using a symbol not defined in the keymap
### XKB-967 – Invalid rules syntax {#XKB-967}
Since
1.0.0
Type
Error
Summary
The rules syntax is invalid and the file cannot be parsed
See @ref rule-file-format "" for further information. ### XKB-971 – Undeclared modifiers in key type {#XKB-971}
Since
1.0.0
Type
Warning
Summary
Some modifiers used in a key type “map” or “preserve” entry are not declared
The modifiers used in `map` or `preserve` entries should be declared using the entry `modifiers` in the key type. [XKB-034]: @ref XKB-034 [XKB-043]: @ref XKB-043 [XKB-052]: @ref XKB-052 [XKB-060]: @ref XKB-060 [XKB-077]: @ref XKB-077 [XKB-082]: @ref XKB-082 [XKB-101]: @ref XKB-101 [XKB-107]: @ref XKB-107 [XKB-123]: @ref XKB-123 [XKB-134]: @ref XKB-134 [XKB-150]: @ref XKB-150 [XKB-161]: @ref XKB-161 [XKB-172]: @ref XKB-172 [XKB-183]: @ref XKB-183 [XKB-193]: @ref XKB-193 [XKB-195]: @ref XKB-195 [XKB-203]: @ref XKB-203 [XKB-206]: @ref XKB-206 [XKB-237]: @ref XKB-237 [XKB-239]: @ref XKB-239 [XKB-254]: @ref XKB-254 [XKB-266]: @ref XKB-266 [XKB-286]: @ref XKB-286 [XKB-301]: @ref XKB-301 [XKB-302]: @ref XKB-302 [XKB-305]: @ref XKB-305 [XKB-312]: @ref XKB-312 [XKB-338]: @ref XKB-338 [XKB-345]: @ref XKB-345 [XKB-362]: @ref XKB-362 [XKB-378]: @ref XKB-378 [XKB-386]: @ref XKB-386 [XKB-407]: @ref XKB-407 [XKB-428]: @ref XKB-428 [XKB-433]: @ref XKB-433 [XKB-461]: @ref XKB-461 [XKB-478]: @ref XKB-478 [XKB-489]: @ref XKB-489 [XKB-516]: @ref XKB-516 [XKB-523]: @ref XKB-523 [XKB-542]: @ref XKB-542 [XKB-550]: @ref XKB-550 [XKB-563]: @ref XKB-563 [XKB-578]: @ref XKB-578 [XKB-595]: @ref XKB-595 [XKB-607]: @ref XKB-607 [XKB-623]: @ref XKB-623 [XKB-639]: @ref XKB-639 [XKB-645]: @ref XKB-645 [XKB-661]: @ref XKB-661 [XKB-679]: @ref XKB-679 [XKB-685]: @ref XKB-685 [XKB-693]: @ref XKB-693 [XKB-700]: @ref XKB-700 [XKB-711]: @ref XKB-711 [XKB-742]: @ref XKB-742 [XKB-762]: @ref XKB-762 [XKB-769]: @ref XKB-769 [XKB-770]: @ref XKB-770 [XKB-784]: @ref XKB-784 [XKB-796]: @ref XKB-796 [XKB-800]: @ref XKB-800 [XKB-812]: @ref XKB-812 [XKB-822]: @ref XKB-822 [XKB-844]: @ref XKB-844 [XKB-883]: @ref XKB-883 [XKB-893]: @ref XKB-893 [XKB-901]: @ref XKB-901 [XKB-903]: @ref XKB-903 [XKB-935]: @ref XKB-935 [XKB-949]: @ref XKB-949 [XKB-965]: @ref XKB-965 [XKB-967]: @ref XKB-967 [XKB-971]: @ref XKB-971 xkbcommon-libxkbcommon-54ee7ac/doc/message-registry.md.jinja000066400000000000000000000035671510033435100243510ustar00rootroot00000000000000# Error index { {#--#} #error-index} {# NOTE: Prevent Doxygen issue by writing the comment after the first header. #} This page lists the warnings and errors generated by xkbcommon. There are currently {{ entries|length }} entries. @todo The documentation of the log messages is a work in progress. ## Index {% raw %}{#error-code-list}{% endraw +%} | Code | Identifier | Description | Type | | --------- | ---------------------------- | ----------- | ---- | {% for entry in entries %} | [{{entry.message_code}}] | `{{entry.id}}` | {{entry.description|prepend_todo}} | {{entry.type|capitalize}} | {% endfor %} ## Details {% for entry in entries %} ### {{entry.message_code}} – {{entry.message_name}} { {#--#}#{{entry.message_code}}}
{% if entry.removed %}
Added in
{{entry.added}}
Removed in
{{entry.removed}}
{% else %}
Since
{{entry.added}}
{% endif %}
Type
{{entry.type|capitalize}}
Summary
{{entry.description|prepend_todo}}
{% if entry.details %} {{entry.details}} {% endif %} {% if entry.examples %} #### Examples {% for example in entry.examples %}
{{example.name}} {{example.description}} {% if example.before %} **Fix:**
Before
{{example.before-}}
After
{{example.after-}}
{% endif %}
{% endfor %} {% endif %} {% endfor %} {% for entry in entries %} [{{entry.message_code}}]: @ref {{entry.message_code}} {% endfor %} xkbcommon-libxkbcommon-54ee7ac/doc/message-registry.yaml000066400000000000000000000437231510033435100236170ustar00rootroot00000000000000# Guidelines: # • A message code must always have the same meaning forever. # • Codes may be retired or introduced in new releases. In order to avoid # clashes, retired codes must not be deleted. # • Codes should not themselves reflect classification, e.g. a range for parse # errors and a range for each keymap component. # • Codes should not be assigned sequentially because it is misleading. # • Codes must be in the range 1..999. This range may be extended once every # code has be assigned. # # See the following guidelines for further details on good practices: # https://github.com/haskellfoundation/error-message-index/blob/main/tool-developers.md#code-assignment-recommendations # NOTE: Field “added: ALWAYS” means that the precise version is unknown and # anterior to the introduction of the message registry. It will be replaced by # the default version 1.0.0 in the generated documentation. While this is deemed # good enough to avoid spelunking commit history, a more precise version would # be welcome. # TODO: fix missing detailed description, examples, resolution - id: "malformed-number-literal" code: 34 added: ALWAYS type: error description: "Warn on malformed number literals" details: | xkbcommon can parse the following number literal formats: - *decimal integer:* 1, 123, etc. - *decimal floating-point number:* 1.23, etc. - *hexadecimal integer:* prefixed with “0x”: 0x123, 0xff, 0xAB, etc. - id: "conflicting-key-type-preserve-entries" code: 43 added: ALWAYS type: warning description: "Conflicting “preserve” entries in a key type" - id: "integer-overflow" code: 52 added: 1.10.0 type: error description: "The result of the operation is not mathematically correct" details: | The result of the operation is not representable in the corresponding datatype and overflowed. - id: "unsupported-modifier-mask" code: 60 added: ALWAYS type: error description: "Warn on unsupported modifier mask" - id: "expected-array-entry" code: 77 added: ALWAYS type: error description: "Expected an array entry, but the index is missing" - id: "invalid-numeric-keysym" code: 82 added: ALWAYS type: error description: "Invalid numeric keysym" details: | Keysyms are 32-bit integers with the 3 most significant bits always set to zero. Thus valid keysyms are in the range `0 .. 0x1fffffff` = @ref XKB_KEYSYM_MAX. See: Appendix A [“KEYSYM Encoding”][encoding] of the X Window System Protocol. [encoding]: https://www.x.org/releases/current/doc/xproto/x11protocol.html#keysym_encoding @see keysyms - id: "illegal-keycode-alias" code: 101 added: ALWAYS type: warning description: "Illegal keycode alias with the name of a real key" - id: "unrecognized-keysym" code: 107 added: ALWAYS type: warning description: "Warn on unrecognized keysyms" details: | xkbcommon replaces keysyms it does not recognize by the keysym `NoSymbol`. You may find the list of supported keysyms in `include/xkbcommon/xkbcommon-keysyms.h`. examples: - name: Unrecognized keysym “`coma`” description: | **Error message:** ``` xkbcommon: WARNING: [XKB-107] de:31:20: unrecognized keysym "coma" ``` xkbcommon does not recognize the keysym “`coma`”. It is most probably a typo for “comma”. See: `XKB_KEY_comma` in `include/xkbcommon/xkbcommon-keysyms.h`. before: | ```c key {[ coma, semicolon, periodcentered, multiply ]}; ``` after: | ```c key {[ comma, semicolon, periodcentered, multiply ]}; ``` - id: "undeclared-virtual-modifier" code: 123 added: ALWAYS type: error description: "A virtual modifier is used before being declared" - id: "insufficient-buffer-size" code: 134 added: ALWAYS type: error description: "A buffer has an insufficient size" - id: "wrong-statement-type" code: 150 added: ALWAYS type: error description: "The type of the statement is not allowed in the context" - id: "invalid-path" code: 161 added: ALWAYS type: error description: "The given path is invalid" - id: "unsupported-geometry-section" code: 172 added: ALWAYS type: warning description: "Geometry sections are not supported" - id: "cannot-infer-key-type" code: 183 added: ALWAYS type: warning description: "Warn if no key type can be inferred" - id: "invalid-escape-sequence" code: 193 added: ALWAYS type: warning description: "Invalid escape sequence in a string" - id: "illegal-key-type-preserve-result" code: 195 added: ALWAYS type: warning description: "The result of a key type “preserve” entry must be a subset of its input modifiers." - id: "invalid-include-statement" code: 203 added: ALWAYS type: error description: "Syntax error in the include statement" - id: "invalid-modmap-entry" code: 206 added: ALWAYS type: error description: "A modmap entry is invalid" - id: "unsupported-group-index" code: 237 added: ALWAYS type: error description: "Warn when a group index is not supported" details: | xkbcommon supports different *group index* ranges, depending of the target *keymap format*: - `::XKB_KEYMAP_FORMAT_TEXT_V1`: 1..{{XKB_MAX_GROUPS_X11}} - `::XKB_KEYMAP_FORMAT_TEXT_V2`: 1..{{XKB_MAX_GROUPS}} - id: "conflicting-key-type-level-names" code: 239 added: ALWAYS type: warning description: "The name of a key type level is defined multiple times." - id: "invalid-set-default-statement" code: 254 added: ALWAYS type: error description: "Invalid statement setting default values" - id: "conflicting-key-type-map-entry" code: 266 added: ALWAYS type: warning description: "Conflicting “map” entries in type definition" - id: "undefined-key-type" code: 286 added: ALWAYS type: warning description: "Warn if using an undefined key type" - id: "deprecated-keysym" code: 301 added: 1.8.0 type: warning description: "A keysym has been deprecated: consider using an alternative keysym" details: | Some keysyms have ambiguous meaning. It is advised to migrate to an alternative keysym if possible, as deprecated keysyms may be removed in the future. Consider using Unicode keysyms (`Unnnn`) if relevant. - id: "deprecated-keysym-name" code: 302 added: 1.8.0 type: warning description: "A keysym name has been deprecated: use the corresponding canonical name instead" details: | Some keysym names have typos, unconventional names or are historical aliases. Please consider migrating to the reference name reported in the warning message. - id: "non-base-group-name" code: 305 added: ALWAYS type: warning description: "Warn if a group name was defined for group other than the first one" - id: "unsupported-shift-level" code: 312 added: ALWAYS type: error description: "Warn when a shift level is not supported" details: | Shift levels are _one_-indexed. xkbcommon supports two formats of shift levels: as numbers and as identifiers `LevelN`, where `N` is in the range (1..8). - id: "included-file-not-found" code: 338 added: ALWAYS type: error description: "Could not find a file used in an include statement" - id: "unknown-operator" code: 345 added: ALWAYS type: error description: "Use of an operator that is unknown and thus unsupported" - id: "unsupported-legacy-action" code: 362 added: 1.10.0 type: warning description: "Use of a legacy X11 action that is not supported" details: | This action will be treated as `NoAction()`. See @ref unsupported-legacy-x11-actions "" for further information. - id: "duplicate-entry" code: 378 added: ALWAYS type: warning description: "An entry is duplicated and will be ignored" - id: "recursive-include" code: 386 added: 1.7.0 type: error description: "Included files form cycle" - id: "conflicting-key-type-definitions" code: 407 added: ALWAYS type: warning description: "Conflicting definitions of a key type" details: | The given key type is defined multiple times, but only one definition is kept. - id: "global-defaults-wrong-scope" code: 428 added: ALWAYS type: error description: "A global defaults statement is in a wrong scope and should be moved" examples: - name: Default key type in key statement description: | **Error message:** ``` xkbcommon: ERROR: [XKB-428] Cannot set global defaults for "type" element within a key statement: move statements to the global file scope. Assignment to "key.type" ignored. ``` before: | ```c key { key.type = "FOUR_LEVEL_SEMIALPHABETIC", symbols = [q, Q, at] }; ``` after: | ```c // Either put default key type in global file scope key.type = "FOUR_LEVEL_SEMIALPHABETIC"; key { [q, Q, at] }; // or use a local setting (unqualified, i.e. without `key.`) key { type = "FOUR_LEVEL_SEMIALPHABETIC", symbols = [ q, Q, at ] }; ``` - id: "missing-default-section" code: 433 added: ALWAYS type: warning description: "Missing default section in included file" details: | When using an include statement, the included file may contains multiple sections. The include statement may specify the name of the section to include, or leave it unspecified. In the latter case, the included file must then define a *default* section. The present warning is shown when no default section is defined. To solve this, either fix the include statement by specifying the exact section to include, or declare a default section in the included file. - id: "conflicting-key-symbol" code: 461 added: ALWAYS type: warning description: "Warn if there are conflicting keysyms while merging keys" - id: "invalid-operation" code: 478 added: ALWAYS type: error description: "The operation is invalid in the context" - id: "numeric-keysym" code: 489 added: 1.6.0 type: warning description: "Warn on numeric keysym (other than 0-9)" details: | Numeric keysyms are not human-friendly. Use the corresponding named keysym or Unicode keysym, if available. examples: - name: Hexadecimal keysym `0x1001ed0` description: | **Error message:** ``` xkbcommon: WARNING: [XKB-489] numeric keysym "0x1001ed0" ``` before: | ```c key { [ 0x1001ed0] }; ``` after: | ```c // Preferred form: human-friendly key { [ Ocircumflexacute ] }; // or key { [ U1ED0 ] }; ``` - id: "extra-symbols-ignored" code: 516 added: ALWAYS type: warning description: "TODO: add description" - id: "conflicting-key-name" code: 523 added: ALWAYS type: warning description: "Conflicting definitions of a key name or alias" - id: "invalid-file-encoding" code: 542 added: 1.7.0 type: error description: "Invalid file encoding" - id: "allocation-error" code: 550 added: ALWAYS type: error description: "Cannot allocate memory" - id: "invalid-action-field" code: 563 added: ALWAYS type: error description: "Unknown or unsupported action field" - id: "wrong-field-type" code: 578 added: ALWAYS type: error description: "Warn when a field has not the expected type" - id: "cannot-resolve-rmlvo" code: 595 added: ALWAYS type: error description: "Cannot resolve a given (Rules, Model, Layout, Variant, Options) configuration" - id: "invalid-unicode-escape-sequence" code: 607 added: 1.9.0 type: warning description: "Invalid Unicode escape sequence" details: | xkbcommon support the Unicode sequence `\u{NNNN}`, where `NNNN` denotes a Unicode code point in hexadecimal format in the range `1‥0x10ffff`. - id: "invalid-real-modifier" code: 623 added: ALWAYS type: error description: "Invalid _real_ modifier" - id: "unknown-default-field" code: 639 added: 1.10.0 type: error description: "Cannot set default value to a an unknown field" - id: "unknown-char-escape-sequence" code: 645 added: ALWAYS type: warning description: "Warn on unknown escape sequence in string literal" details: | xkbcommon support the following escape sequences in string literals: | Escape sequence | Corresponding character | | --------------- | ---------------------------------------------------------- | | `\b` | `U+0008` Backspace | | `\t` | `U+0009` Character tabulation | | `\n` | `U+000A` Line feed | | `\v` | `U+000B` Vertical tabulation | | `\f` | `U+000C` Form feed | | `\r` | `U+000D` Carriage return | | `\e` | `U+001B` Escape | | `\\` | `U+005C` Backslash | | `\"` | `U+0022` Double quote | | `\NNNN` | _Octal_ escape, `NNNN` in range `1‥0o377` | | `\u{NNNN}` | _Unicode_ hexadecimal escape, `NNNN` in range `1‥0x10ffff` | - id: "invalid-included-file" code: 661 added: ALWAYS type: error description: "The target file of an include statement could not be processed" - id: "invalid-compose-locale" code: 679 added: 1.12.0 type: error description: "Invalid locale for Compose" details: | The locale is either invalid (not installed on the system) or not registered in the X11 Compose registry. - id: "invalid-compose-syntax" code: 685 added: ALWAYS type: error description: "The Compose file syntax is invalid and the entry cannot be parsed" - id: "incompatible-actions-and-keysyms-count" code: 693 added: 1.8.0 type: error description: "A level has a different number of keysyms and actions" details: | A level must have exactly the same number of keysyms and actions. - id: "multiple-groups-at-once" code: 700 added: ALWAYS type: warning description: "Warn if a key defines multiple groups at once" - id: "unsupported-symbols-field" code: 711 added: ALWAYS type: warning description: "A legacy X11 symbol field is not supported" - id: "incompatible-keymap-text-format" code: 742 added: 1.11.0 type: error description: "The keymap has features unsupported in the target format" details: | See @ref keymap-support "" for further details. - id: "rules-invalid-layout-index-percent-expansion" code: 762 added: 1.11.0 type: error description: "Cannot expand `%%i`: missing layout or variant in MLVO rule fields" details: | In a @ref rule-file-format "rules file", `%%i` denotes the index of the matched layout. It can only be used in the [KcCGST] value of the rule if the layout or variant is defined in the [MLVO] fields of the rule header. Otherwise the rule is always discarded. To fix the error, either remove the `:%%i` specifier or add a the relevant [MLVO] field, e.g. `layout[any]`. [KcCGST]: @ref KcCGST-intro [MLVO]: @ref RMLVO-intro - id: "invalid-xkb-syntax" code: 769 added: ALWAYS type: error description: "The XKB syntax is invalid and the file cannot be parsed" details: | See @ref keymap-text-format-v1-v2 "" for further details. - id: "undefined-keycode" code: 770 added: ALWAYS type: warning description: "Reference to an undefined keycode" - id: "invalid-expression-type" code: 784 added: ALWAYS type: error description: "An expression has not the expected type" - id: "invalid-value" code: 796 added: ALWAYS type: error description: "A value is invalid and will be ignored" - id: "conflicting-modmap" code: 800 added: ALWAYS type: warning description: "Warn if there are conflicting modmap definitions" details: | @todo detailed explanation and examples - id: "unknown-field" code: 812 added: ALWAYS type: error description: "A field is unknown and will be ignored" - id: "keymap-compilation-failed" code: 822 added: ALWAYS type: error description: "Keymap compilation failed" - id: "unknown-action-type" code: 844 added: ALWAYS type: error description: "Unknown action type" details: | See @ref key-actions "" for the list of supported actions. - id: "conflicting-key-action" code: 883 added: ALWAYS type: warning description: "Warn if there are conflicting actions while merging keys" - id: "conflicting-key-type-merging-groups" code: 893 added: ALWAYS type: warning description: "Warn if there are conflicting key types while merging groups" - id: "conflicting-key-symbols-entry" code: 901 added: ALWAYS type: error description: "Conflicting symbols entry for a key" - id: "missing-symbols-group-name-index" code: 903 added: ALWAYS type: warning description: "Missing group index in a group name entry" - id: "conflicting-key-fields" code: 935 added: ALWAYS type: warning description: "Warn if there are conflicting fields while merging keys" - id: "invalid-identifier" code: 949 added: ALWAYS type: error description: "An identifier is used but is not built-in" - id: "unresolved-keymap-symbol" code: 965 added: ALWAYS type: warning description: "Warn if using a symbol not defined in the keymap" - id: "invalid-rules-syntax" code: 967 added: ALWAYS type: error description: "The rules syntax is invalid and the file cannot be parsed" details: | See @ref rule-file-format "" for further information. - id: "undeclared-modifiers-in-key-type" code: 971 added: ALWAYS type: warning description: "Some modifiers used in a key type “map” or “preserve” entry are not declared" details: | The modifiers used in `map` or `preserve` entries should be declared using the entry `modifiers` in the key type. # TODO: unicode keysym when named and recommended keysym exists xkbcommon-libxkbcommon-54ee7ac/doc/quick-guide.md000066400000000000000000000160771510033435100221740ustar00rootroot00000000000000# Quick Guide ## Introduction This document contains a quick walk-through of the often-used parts of the library. We will employ a few use-cases to lead the examples: 1. An evdev client. "evdev" is the Linux kernel's input subsystem; it only reports to the client which keys are pressed and released. 2. An X11 client, using the XCB library to communicate with the X server and the xcb-xkb library for using the XKB protocol. 3. A Wayland client, using the standard protocol. The snippets are not complete, and some support code is omitted. You can find complete and more complex examples in the source directory: 1. tools/interactive-evdev.c contains an interactive evdev client. 2. tools/interactive-x11.c contains an interactive X11 client. 3. tools/interactive-wayland.c contains an interactive Wayland client. Also, the library contains many more functions for examining and using the library context, the keymap and the keyboard state. See the hyper-linked reference documentation or go through the header files in xkbcommon/ for more details. ## Code Before we can do anything interesting, we need a library context: ~~~{.c} #include struct xkb_context *ctx; ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!ctx) ~~~ The `xkb_context` contains the keymap include paths, the log level and functions, and other general customizable administrativia. Next we need to create a keymap, `xkb_keymap`. This is an immutable object which contains all of the information about the keys, layouts, etc. There are different ways to do this. If we are an evdev client, we have nothing to go by, so we need to ask the user for his/her keymap preferences (for example, an Icelandic keyboard with a Dvorak layout). The configuration format is commonly called RMLVO (Rules+Model+Layout+Variant+Options), the same format used by the X server. With it, we can fill a struct called `xkb_rule_names`; passing `NULL` chooses the system's default. ~~~{.c} struct xkb_keymap *keymap; /* Example RMLVO for Icelandic Dvorak. */ struct xkb_rule_names names = { .rules = NULL, .model = "pc105", .layout = "is", .variant = "dvorak", .options = "terminate:ctrl_alt_bksp" }; keymap = xkb_keymap_new_from_names2(ctx, &names, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) ~~~ If we are a Wayland client, the compositor gives us a string complete with a keymap. In this case, we can create the keymap object like this: ~~~{.c} /* From the wl_keyboard::keymap event. */ const char *keymap_string = <...>; struct xkb_keymap *keymap; keymap = xkb_keymap_new_from_string(ctx, keymap_string, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) ~~~ If we are an X11 client, we are better off getting the keymap from the X server directly. For this we need to choose the XInput device; here we will use the core keyboard device: ~~~{.c} #include xcb_connection_t *conn = <...>; int32_t device_id; device_id = xkb_x11_get_core_keyboard_device_id(conn); if (device_id == -1) keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) ~~~ Now that we have the keymap, we are ready to handle the keyboard devices. For each device, we create an `xkb_state`, which remembers things like which keyboard modifiers and LEDs are active: ~~~{.c} struct xkb_state *state; state = xkb_state_new(keymap); if (!state) ~~~ For X11/XCB clients, this is better: ~~~{.c} state = xkb_x11_state_new_from_device(keymap, conn, device_id); if (!state) ~~~ When we have an `xkb_state` for a device, we can start handling key events from it. Given a keycode for a key, we can get its keysym: ~~~{.c} event; xkb_keycode_t keycode; xkb_keysym_t keysym; keycode = event->keycode; keysym = xkb_state_key_get_one_sym(state, keycode); ~~~ We can see which keysym we got, and get its name: ~~~{.c} char keysym_name[64]; if (keysym == XKB_KEY_Space) xkb_keysym_get_name(keysym, keysym_name, sizeof(keysym_name)); ~~~ libxkbcommon also supports an extension to the classic XKB, whereby a single event can result in multiple keysyms. Here's how to use it: ~~~{.c} const xkb_keysym_t *keysyms; int num_keysyms; num_keysyms = xkb_state_key_get_syms(state, keycode, &keysyms); ~~~ We can also get a UTF-8 string representation for this key: ~~~{.c} char *buffer; int size; // First find the needed size; return value is the same as snprintf(3). size = xkb_state_key_get_utf8(state, keycode, NULL, 0) + 1; if (size <= 1) buffer = xkb_state_key_get_utf8(state, keycode, buffer, size); ~~~ Of course, we also need to keep the `xkb_state` up-to-date with the keyboard device, if we want to get the correct keysyms in the future. If we are an evdev client, we must let the library know whether a key is pressed or released at any given time: ~~~{.c} enum xkb_state_component changed; if () changed = xkb_state_update_key(state, keycode, XKB_KEY_DOWN); else if () changed = xkb_state_update_key(state, keycode, XKB_KEY_UP); ~~~ The `changed` return value tells us exactly which parts of the state have changed. If it is a key-repeat event, we can ask the keymap what to do with it: ~~~{.c} if ( && !xkb_keymap_key_repeats(keymap, keycode)) ~~~ On the other hand, if we are an X or Wayland client, the server already does the hard work for us. It notifies us when the device's state changes, and we can simply use what it tells us (the necessary information usually comes in a form of some "state changed" event): ~~~{.c} changed = xkb_state_update_mask(state, event->depressed_mods, event->latched_mods, event->locked_mods, event->depressed_layout, event->latched_layout, event->locked_layout); ~~~ Now that we have an always-up-to-date `xkb_state`, we can examine it. For example, we can check whether the Control modifier is active, or whether the Num Lock LED is active: ~~~{.c} if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0) if (xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) > 0) ~~~ And that's it! Eventually, we should free the objects we've created: ~~~{.c} xkb_state_unref(state); xkb_keymap_unref(keymap); xkb_context_unref(ctx); ~~~ xkbcommon-libxkbcommon-54ee7ac/doc/release-notes.md000066400000000000000000000001221510033435100225130ustar00rootroot00000000000000# Release notes {#release-notes} @tableofcontents{html:1} @include{doc} NEWS.md xkbcommon-libxkbcommon-54ee7ac/doc/rules-format.md000066400000000000000000000463711510033435100224050ustar00rootroot00000000000000The rules file {#rule-file-format} ============== The purpose of the rules file is to map between configuration values that are easy for a user to specify and understand, and the configuration values that the keymap compiler, `xkbcomp`, uses and understands. The following diagram presents an overview of this process. See the [XKB introduction] for further details on the components. @dotfile xkb-configuration "XKB keymap configurations" @tableofcontents{html:2} `libxkbcommon`’s keymap compiler `xkbcomp` uses the `xkb_component_names` struct internally, which maps directly to [include statements] of the appropriate [sections] \(called [KcCGST] for short): - [key codes], - [compatibility], - geometry ([not supported](@ref geometry-support) by xkbcommon), - [symbols], - [types]. These are not really intuitive nor straightforward for the uninitiated. Instead, the user passes in a `xkb_rule_names` struct, which consists of the following fields (called [RMLVO] for short): - the name of a [rules] file (in Linux this is usually “evdev”), - a keyboard [model] \(e.g. “pc105”), - a set of [layouts][layout] (which will end up in different groups, e.g. “us,fr”), - a set of [variants][variant] (used to alter/augment the respective layout, e.g. “intl,dvorak”), - a set of [options] \(used to tweak some general behavior of the keyboard, e.g. “ctrl:nocaps,compose:menu” to make the Caps Lock key act like Ctrl and the Menu key like Compose). [KcCGST]: @ref KcCGST-intro [RMLVO]: @ref RMLVO-intro [MLVO]: @ref RMLVO-intro [XKB introduction]: @ref xkb-intro [include statements]: @ref xkb-include [sections]: @ref keymap-section-def [key codes]: @ref the-xkb_keycodes-section [compatibility]: @ref the-xkb_compat-section [symbols]: @ref the-xkb_symbols-section [types]: @ref the-xkb_types-section [rules]: @ref config-rules-def [model]: @ref config-model-def [layout]: @ref config-layout-def [variant]: @ref config-variant-def [option]: @ref config-options-def [options]: @ref config-options-def # Format of the file ## Rules and rule sets {#rule-def} @anchor rule-set-def The file consists of **rule sets**, each consisting of **rules** (one per line), which match the [MLVO] values on the left hand side, and, if the values match to the values the user passed in, results in the values on the right hand side being [added][value update] to the resulting [KcCGST]. See @ref rmlvo-resolution for further details. [rule set]: @ref rule-set-def [rule sets]: @ref rule-set-def [rule]: @ref rule-def ```c // This is a comment // The following line is a rule header. // It starts with ‘!’ and introduces a rules set. // It indicates that the rules map MLVO options to KcCGST symbols. ! option = symbols // The following lines are rules that add symbols of the RHS when the // LHS matches an option. ctrl:nocaps = +ctrl(nocaps) compose:menu = +compose(menu) // One may use multiple MLVO components on the LHS ! layout option = symbols be caps:digits_row = +capslock(digits_row) fr caps:digits_row = +capslock(digits_row) ``` ## Groups {#rules-group-def} Since some values are related and repeated often, it is possible to *group* them together and refer to them by a **group name** in the rules. [group]: @ref rules-group-def ```c // Let’s rewrite the previous rules set using groups. // Groups starts with ‘$’. // Define a group for countries with AZERTY layouts ! $azerty = be fr // The following rule will match option `caps:digits_row` only for // layouts in the $azerty group, i.e. `fr` and `be`. ! layout option = symbols $azerty caps:digits_row = +capslock(digits_row) ``` ## Wild cards {#rules-wildcard-def} Along with matching values by simple string equality and for membership in a [group] defined previously, rules may also contain **wild card** values with the following behavior:
* @anchor rules-wildcard-legacy-def
Legacy wild card: - For `model` and `options`: *always* match. - For `layout` and `variant`: match any *non-empty* value. This wild card usually appears near the end of a rule set to set *default* values. @note Prefer using the wild cards @ref rules-wildcard-some-def "\" or @ref rules-wildcard-any-def "\" for their simpler semantics, as it does not depend on the context.
\ @anchor rules-wildcard-none-def
Match *empty* values @since 1.9.0
\ @anchor rules-wildcard-some-def
Match *non-empty* value @since 1.9.0
\ @anchor rules-wildcard-any-def
Match *any* (optionally empty) value. Its behavior does not depend on the context, contrary to the legacy wild card @ref rules-wildcard-legacy-def "*". This wild card usually appears near the end of a rule set to set *default* values. @since 1.9.0
```c ! layout = keycodes // The following two lines only match exactly their respective groups. $azerty = +aliases(azerty) $qwertz = +aliases(qwertz) // This line will match layouts that are neither in $azerty nor in // $qwertz groups. * = +aliases(qwerty) ``` # Grammar It is advised to look at a file like `rules/evdev` along with this grammar. @note Comments, whitespace, etc. are not shown. ```bnf File ::= { "!" (Include | Group | RuleSet) } Include ::= "include" Group ::= GroupName "=" { GroupElement } "\n" GroupName ::= "$" GroupElement ::= RuleSet ::= Mapping { Rule } Mapping ::= { Mlvo } "=" { Kccgst } "\n" Mlvo ::= "model" | "option" | ("layout" | "variant") [ Index ] Index ::= "[" ({ NumericIndex } | { SpecialIndex }) "]" NumericIndex ::= 1..XKB_MAX_GROUPS SpecialIndex ::= "single" | "first" | "later" | "any" Kccgst ::= "keycodes" | "symbols" | "types" | "compat" | "geometry" Rule ::= { MlvoValue } "=" { KccgstValue } "\n" MlvoValue ::= "*" | "" | "" | "" | GroupName | KccgstValue ::= [ { Qualifier } ] Qualifier ::= ":" ({ NumericIndex } | "all") ``` @note - Include processes the rules in the file path specified in the `ident`, in order. **%-expansion** is performed, as follows: @anchor rules-include-expansion
`%%`
A literal %.
\%H
The value of the `$HOME` environment variable.
\%E
The extra lookup path for system-wide XKB data (usually `/etc/xkb/rules`).
\%S
The system-installed rules directory (usually `/usr/share/X11/xkb/rules`).
**Note:** This feature is supported by libxkbcommon but not by the legacy X11 tools. - @anchor rules-extended-layout-indices (Since version `1.8.0`) The following *extended layout indices* can be used to avoid repetition and clarify the semantics:
`single`
Matches a single layout; `layout[single]` is the same as without explicit index: `layout`.
`first`
Matches the first layout/variant, no matter how many layouts are in the RMLVO configuration. Acts as both `layout` and `layout[1]`.
`later`
Matches all but the first layout. This is an index *range*. Acts as `layout[2]` .. `layout[4]`.
any
Matches layout at any position. This is an index *range*. Acts as `layout`, `layout[1]` .. `layout[4]`.
When using a layout index *range* (`later`, `any`), the @ref rules-i-expansion "%i expansion" can be used in the `KccgstValue` to refer to the index of the matched layout. - The order of values in a `Rule` must be the same as the `Mapping` it follows. The mapping line determines the meaning of the values in the rules which follow in the `RuleSet`. - If a `Rule` is matched, **%-expansion** is performed on the `KccgstValue`, as follows:
\%m, \%l, \%v
The [model], [layout] or [variant], if *only one* was given (e.g. \%l for “us,il” is invalid).
\%l[1], \%l[2], …, \%v[1], \%v[2], …
[Layout][layout] or [variant] for the specified layout `Index`, if *more than one* was given, e.g.: \%l[1] is invalid for “us” but expands to “us” for “us,de”.
`%+m`, `%+l`, `%+l[1]`, `%+l[2]`, …, `%+v`, `%+v[1]`, `%+v[2]`, …
As above, but prefixed with ‘+’. Similarly, ‘|’, ‘^’, ‘-’, ‘_’ may be used instead of ‘+’. See the [merge mode] documentation for the special meaning of ‘+’, ‘|’ and ‘^’.
`%(m)`, `%(l)`, `%(l[1])`, `%(l[2])`, …, `%(v)`, `%(v[1])`, `%(v[2])`, …
As above, but prefixed by ‘(’ and suffixed by ‘)’.
@anchor rules-i-expansion `:%%i`, `%%l[%%i]`, `%(l[%%i])`, etc.
In case the mapping uses an @ref rules-extended-layout-indices "extended layout index", `%%i` corresponds to the index of the matched layout. ℹ️ Notes: - Added in version `1.8.0` - Since `1.11.0`: This feature can only be used if the rule header has a `layout` or `variant` [MLVO] field.
In case the expansion is *invalid*, as described above, it is *skipped* (the rest of the string is still processed); this includes the prefix and suffix. This is why one should use e.g. %(v[1]) instead of (\%v[1]). See @ref rules-symbols-example for an illustration. - @anchor rules-all-qualifier (Since version `1.8.0`) If a `Rule` is matched, the `:all` *qualifier* in the `KccgstValue` applies the qualified value (and its optional merge mode) to all layouts. If there is no merge mode, it defaults to *override* `+`.
Examples of `:all` qualified use
`KccgstValue` Layouts count Final `KccgstValue`
`x:all` 1 `x:1`
2 `x:1+x:2`
`+x:all` 1 `+x:1`
3 `+x:1+x:2+x:3`
`|x:all` 1 `|x:1`
4 `|x:1|x:2|x:3|x:4`
`x|y:all` 1 `x|y:1`
3 `x|y:1|y:2|y:3`
`x:all+y|z:all` 2 `x:1+x:2+y|z:1|z:2`
# RMLVO resolution process {#rmlvo-resolution} ## Process First of all, the rules *file* is extracted from the provided [RMLVO][RMLVO] configuration (usually `evdev`). Then its path is resolved and the file is parsed to get the [rule sets]. Then *each rule set* is checked against the provided [MLVO] configuration, following their *order* in the rules file. @important @anchor irrelevant-options-order Contrary to layouts and variants, the *options order* in a [MLVO] configuration (e.g. via `xkbcli`) is irrelevant for its resolution: only the order of the rules matters. See “@ref rules-options-example ""” for an illustration. If a [rule] matches in a @ref rule-set-def "rule set", then:
  1. @anchor rules-kccgst-value-update The *KcCGST* value of the rule is used to update the [KcCGST] configuration, using the following instructions. Note that `foo` and `bar` are placeholders; ‘+’ specifies the *override* [merge mode] and can be replaced by ‘|’ or ‘^’ to specify respectively the *augment* or *replace* merge mode instead. | Rule value | Old KcCGST value | New KcCGST value | | ----------------- | ---------------- | --------------------- | | `bar` | | `bar` | | `bar` | `foo` | `foo` (*skip* `bar`) | | `bar` | `+foo` | `bar+foo` (*prepend*) | | `+bar` | | `+bar` | | `+bar` | `foo` | `foo+bar` | | `+bar` | `+foo` | `+foo+bar` |
  2. The rest of the set will be *skipped*, except if the set matches against [options]. Indeed, those may contain *multiple* legitimate rules, so they are processed entirely. See @ref rules-options-example for an illustration.
[value update]: @ref rules-kccgst-value-update [merge mode]: @ref merge-mode-def ## Examples ### Example: key codes Using the following example: ```c ! $jollamodels = jollasbj ! $azerty = be fr ! $qwertz = al ch cz de hr hu ro si sk ! model = keycodes $jollamodels = evdev+jolla(jolla) olpc = evdev+olpc(olpc) * = evdev ! layout = keycodes $azerty = +aliases(azerty) $qwertz = +aliases(qwertz) * = +aliases(qwerty) ``` we would have the following resolutions of [key codes]: | Model | Layout | Keycodes | | ---------- | :------: | :----------------------------------- | | `jollasbj` | `us` | `evdev+jolla(jolla)+aliases(qwerty)` | | `olpc` | `be` | `evdev+olpc(olpc)+aliases(azerty)` | | `pc` | `al` | `evdev+aliases(qwertz)` | ### Example: layouts, variants and symbols {#rules-symbols-example} Using the following example: ```c ! layout = symbols * = pc+%l%(v) // The following would not work: syntax for *multiple* layouts // in a rule set for *single* layout. //* = pc+%l[1]%(v[1]) ! layout[1] = symbols * = pc+%l[1]%(v[1]) // The following would not work: syntax for *single* layout // in a rule set for *multiple* layouts. //* = pc+%l%(v) ! layout[2] = symbols * = +%l[2]%(v[2]):2 ! layout[3] = symbols * = +%l[3]%(v[3]):3 ``` we would have the following resolutions of [symbols]: | Layout | Variant | Symbols | Rules sets used | | ---------- | ------------ | ----------------------------- | --------------- | | `us` | | `pc+us` | #1 | | `us` | `intl` | `pc+us(intl)` | #1 | | `us,es` | | `pc+us+es:2` | #2, #3 | | `us,es,fr` | `intl,,bepo` | `pc+us(intl)+es:2+fr(bepo):3` | #2, #3, #4 | Since version `1.8.0`, the previous code can be replaced with simply: ```c ! layout[first] = symbols * = pc+%l[%i]%(v[%i]) ! layout[later] = symbols * = +%l[%i]%(v[%i]):%i ``` ### Example: layout, option and symbols {#rules-options-example} Using the following example: ```c ! $azerty = be fr ! layout = symbols * = pc+%l%(v) ! layout[1] = symbols * = pc+%l[1]%(v[1]) ! layout[2] = symbols * = +%l[2]%(v[2]) // Repeat the previous rules set with indices 3 and 4 ! layout option = symbols $azerty caps:digits_row = +capslock(digits_row) * misc:typo = +typo(base) * lv3:ralt_alt = +level3(ralt_alt) ! layout[1] option = symbols $azerty caps:digits_row = +capslock(digits_row):1 * misc:typo = +typo(base):1 * lv3:ralt_alt = +level3(ralt_alt):1 // Repeat the previous rules set for indices 2 to 4 ``` we would have the following resolutions of [symbols]: | Layout | Option | Symbols | | ------- | ---------------------------------------- | ----------------------------------------------------------- | | `be` | `caps:digits_row` | `pc+be+capslock(digits_row)` | | `gb` | `caps:digits_row` | `pc+gb` | | `fr` | `misc:typo` | `pc+fr+typo(base)` | | `fr` | `misc:typo,caps:digits_row` | `pc+fr+capslock(digits_row)+typo(base)` | | `fr` | `lv3:ralt_alt,caps:digits_row,misc:typo` | `pc+fr+capslock(digits_row)+typo(base)+level3(ralt_alt)` | | `fr,gb` | `caps:digits_row,misc:typo` | `pc+fr+gb:2+capslock(digits_row)+typo(base):1+typo(base):2` | Note that the configuration with `gb` [layout] has no match for the [option] `caps:digits_row` and that the order of the [options] in the [RMLVO] configuration has no influence on the resulting [symbols], as it depends solely on their order in the rules. Since version `1.8.0`, the previous code can be replaced with simply: ```c ! $azerty = be fr ! layout[first] = symbols * = pc+%l[%i]%(v[%i]) ! layout[later] = symbols * = +%l[%i]%(v[%i]) ! layout[any] option = symbols $azerty caps:digits_row = +capslock(digits_row):%i ! option = symbols misc:typo = +typo(base):all lv3:ralt_alt = +level3(ralt_alt):all // The previous is equivalent to: ! layout[any] option = symbols * misc:typo = +typo(base):%i * lv3:ralt_alt = +level3(ralt_alt):%i ``` ### Example: layout-specific options {#rules-layout-specific-options-example} Using the following example: ```c ! layout[first] = symbols * = pc ! layout[any] = symbols * = %l[%i]%(v[%i]) // Not layout-specific ! option = symbols opt1 = +opt1 // Layout-specific: note the range `[any]` and the `:%i` specifier ! layout[any] option = symbols * opt2 = +opt2:%i ``` we would have the following resolutions of [symbols]: | Layout | Option | Symbols | Comment | | ------- | --------- | -------------------------- | -------------------------------------- | | `be,gb` | `opt1` | `pc+be+gb:2+opt1` | Matched: no layout index | | `be,gb` | `opt1!1` | `pc+be+gb:2` | No match: not a layout-specific option | | `be,gb` | `opt1!2` | `pc+be+gb:2` | No match: not a layout-specific option | | `be,gb` | `opt2` | `pc+be+gb:2+opt2:1+opt2:2` | Matched: all layouts | | `be,gb` | `opt2!1` | `pc+be+gb:2+opt2:1` | Matched: only specified layout | | `be,gb` | `opt2!2` | `pc+be+gb:2+opt2:2` | Matched: only specified layout | @note Such option should use the attribute `layout-specific="true"` in the corresponding `configItem` tag of the XML registry file, so that keyboard configuration can expose this feature in their user interface. xkbcommon-libxkbcommon-54ee7ac/doc/user-configuration.md000066400000000000000000000362561510033435100236110ustar00rootroot00000000000000# User-configuration {#user-configuration} This page describes how to add a *custom* layout or option so that it will be parsed by libxkbcommon. @note For an introduction to XKB and keymap components, please see “@ref xkb-intro ""”. @warning The below requires libxkbcommon as keymap compiler and **does not work in _X11_** sessions, because X servers have hard-coded paths. @important An erroneous XKB configuration may make your keyboard unusable. Therefore it is advised to try custom configurations safely using `xkbcli` tools; see [debugging] for further details. [debugging]: @ref testing-custom-config @tableofcontents{html:2} ## Data locations {#user-config-locations} libxkbcommon searches the following paths for XKB configuration files: 1. `$XDG_CONFIG_HOME/xkb/`, or `$HOME/.config/xkb/` if the `$XDG_CONFIG_HOME` environment variable is not defined. See the [XDG Base Directory Specification] for further details. 2.
@deprecated `$HOME/.xkb/` as a *legacy* alternative to the previous XDG option.
3. `$XKB_CONFIG_EXTRA_PATH` if set, otherwise `/xkb` (on most distributions this is `/etc/xkb`). 4. `$XKB_CONFIG_ROOT` if set, otherwise `/X11/xkb/` (path defined by the `xkeyboard-config` package, on most distributions this is `/usr/share/X11/xkb`). [XDG Base Directory Specification]: https://specifications.freedesktop.org/basedir-spec/latest/ A keymap created with `xkb_keymap::xkb_keymap_new_from_names2()` will look up those paths in order until the required data is found. @note Where libxkbcommon runs in a privileged context, only the system (``) path is available. Each directory should have one or more of the following subdirectories: - `compat` - `geometry` (libxkbcommon ignores this directory) - `keycodes` - `rules` - `symbols` - `types` The majority of user-specific configurations involve modifying key symbols and this is what this document focuses on. For use-cases where a user may need to add new key types or compat entries the general approach remains the same. A detailed description for how to add those types or compat entries is out of scope for this document. You should never need to add user-specific keycodes. Where a keycode is missing, the addition should be filed in the upstream [xkeyboard-config] project. [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config ## RMLVO vs KcCGST Due to how XKB is configured, there is no such thing as a “layout” in XKB itself, or, indeed, any of the rules, models, variant, options ([RMLVO]) described in `struct xkb_rule_names`. [RMLVO] names are merely lookup keys in the rules file provided by [xkeyboard-config] to map to the correct keycode, compat, geometry (ignored by libxkbcommon), symbols and types ([KcCGST]). The [KcCGST] data is the one used by XKB and libxkbcommon to map keys to actual symbols. [RMLVO]: @ref RMLVO-intro [KcCGST]: @ref KcCGST-intro For example, a common [RMLVO] configuration is layout `us`, variant `dvorak` and option `terminate:ctrl_alt_bksp`. Using the default rules file and model this maps into the following [KcCGST] components: @figure@figcaption Output of the command: `xkbcli compile-keymap --kccgst --layout us --variant dvorak --options terminate:ctrl_alt_bksp` @endfigcaption ```c xkb_keymap { xkb_keycodes { include "evdev+aliases(qwerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+us(dvorak)+inet(evdev)+terminate(ctrl_alt_bksp)" }; xkb_geometry { include "pc(pc105)" }; }; ``` @endfigure A detailed explanation of how rules files convert [RMLVO] to [KcCGST] is out of scope for this document. See [the rules file](md_doc_rules-format.html) page instead. ## Adding a layout {#user-config-layout} Adding a layout requires that the user adds **symbols** in the correct location. The default rules files (usually `evdev`) have a catch-all to map a layout, say `foo`, and a variant, say `bar`, into the `bar` section in the file `/X11/xkb/symbols/foo`. This is sufficient to define a new keyboard layout. The example below defines the keyboard layout `banana` with an optional variant `orange`: @figure@figcaption Content of `$XDG_CONFIG_HOME/xkb/symbols/banana` @endfigcaption ```c // Like a US layout but swap the top row so numbers are on Shift default partial alphanumeric_keys xkb_symbols "basic" { include "us(basic)" name[Group1]= "Banana (US)"; key { [ exclam, 1] }; key { [ at, 2] }; key { [ numbersign, 3] }; key { [ dollar, 4] }; key { [ percent, 5] }; key { [ asciicircum, 6] }; key { [ ampersand, 7] }; key { [ asterisk, 8] }; key { [ parenleft, 9] }; key { [ parenright, 0] }; key { [ underscore, minus] }; key { [ plus, equal] }; }; // Same as banana but map the euro sign to the 5 key partial alphanumeric_keys xkb_symbols "orange" { include "banana(basic)" name[Group1] = "Banana (Eurosign on 5)"; include "eurosign(5)" }; ``` @endfigure The `default` section is loaded when no variant is given. The first example sections uses ``include`` to populate with a symbols list defined elsewhere (here: section `basic` from the file `symbols/us`, aka. the default US keyboard layout) and overrides parts of these symbols. The effect of this section is to swap the numbers and symbols in the top-most row (compared to the US layout) but otherwise use the US layout. The `orange` variant uses the `banana` symbols and includes a different section to define the `eurosign`. It does not specifically override any symbols. The exact details of how `xkb_symbols` section works is out of scope for this document; see: @ref keymap-text-format-v1-v2 "". @remark This example uses a file name `banana` that should not clash with the system files in `/X11/xkb/symbols`. Using the same file name than the system files is possible but may require special handling, see: @ref user-config-system-file-names "". ## Adding an option {#user-config-option} For technical reasons, options do **not** have a catch-all to map option names to files and sections and must be specifically mapped by the user. This requires a custom rules file. As the `evdev` ruleset is hardcoded in many clients, the custom rules file must usually be named `evdev`. @figure@figcaption Content of `$XDG_CONFIG_HOME/xkb/rules/evdev` @endfigcaption ``` // Mandatory to extend the ! include %S/evdev ! option = symbols custom:foo = +custom(bar) custom:baz = +other(baz) ``` @endfigure The `include` statement includes the system-provided `evdev` ruleset. This allows users to only override those options they need afterwards. This rules file maps the [RMLVO] option `custom:foo` to the `bar` section in the `symbols/custom` file and the `custom:baz` option to the `baz` section in the `symbols/other` file. Note how the [RMLVO] option name may be different to the file or section name. @important The *order* of the options matters! In this example, `custom:foo` will *always* be applied *before* `custom:baz` and both options will *always* be applied *after* the system ones, even if the order is different in the [RMLVO] configuration passed to libxkbcommon (e.g. with `xkbcli`). See the [related section][options-order] in the rules documentation for further details. [options-order]: @ref irrelevant-options-order The files themselves are similar to the layout examples in the previous section: @figure@figcaption Content of `$XDG_CONFIG_HOME/xkb/symbols/custom` @endfigcaption ```c // map the Tilde key to nothing on the first shift level partial alphanumeric_keys xkb_symbols "bar" { key { [ VoidSymbol ] }; }; ``` @endfigure @figure@figcaption Content of `$XDG_CONFIG_HOME/xkb/symbols/other` @endfigcaption ```c // map first key in bottom row (Z in the US layout) to k/K partial alphanumeric_keys xkb_symbols "baz" { key { [ k, K ] }; }; ``` @endfigure With these in place, a user may select any layout/variant together with the `custom:foo` and/or `custom:baz` options. @remark This example uses file names `custom` and `other` that should not clash with the system files in `/X11/xkb/symbols`. Using the same file name than the system files is possible but may require special handling, see: @ref user-config-system-file-names "". ## Using system file names {#user-config-system-file-names} The previous examples use custom keymap files with file name that do not clash with the files in the *system* directory, `/X11/xkb/`. It is possible to add a custom variant/option using the *same* file name than the system file, e.g. `$XDG_CONFIG_HOME/xkb/symbols/us` instead of `$XDG_CONFIG_HOME/xkb/symbols/banana` for the example in @ref user-config-layout "". ### Compatibility @attention For **libxkbcommon \< 1.9**, the custom file must contain an *explicit default* section if the system file has one, else it may break the keyboard setup by including a section of the custom file instead of the system one. The custom default section should enforce that the system default section is included.
The following example defines a `broccoli` layout variant: @figure@figcaption Content of `$XDG_CONFIG_HOME/xkb/symbols/us` @endfigcaption ```c // Explicit default section with no name required default partial alphanumeric_keys xkb_symbols { include "us(basic)" }; partial alphanumeric_keys xkb_symbols "broccoli" { include "us(basic)" name[Group1] = "Broccoli"; key { [ b, B, U1F966 ]}; // 🥦 include "level3(ralt_switch)" }; ``` @endfigure For **libxkbcommon ≥ 1.9** an explicit default section is not required anymore: libxkbcommon will look up for the proper default section in the XKB paths: @figure@figcaption Content of `$XDG_CONFIG_HOME/xkb/symbols/us` @endfigcaption ```c // No default section required partial alphanumeric_keys xkb_symbols "broccoli" { include "us(basic)" name[Group1] = "Broccoli"; key { [ b, B, U1F966 ]}; // 🥦 include "level3(ralt_switch)" }; ``` ### Overriding the system sections One may override the system sections: - Simply use the same section name. - For the default section, additionally prepend the flag `default` before `xkb_symbols` in the custom file. @warning It will affect *all* layouts/variants that depend on the system section. @warning Including the *system* section can lead to a circular import. Therefore is it **highly recommended to *not* override the system sections** and prefer creating proper independent variants. @since 1.11.0: It is possible to include the system section and avoid circular include by prepending \%S to the included file. See the @ref keymap-include-percent-expansion "corresponding documentation". ## Discoverable layouts @warning The below requires `libxkbregistry` as XKB lookup tool and **does not work where clients parse the XML file directly**. The above sections apply only to the data files and require that the user knows about the existence of the new entries. To make custom entries discoverable by the configuration tools (e.g. the GNOME Control Center), the new entries must also be added to the XML file that is parsed by `libxkbregistry`. In most cases, this is the `evdev.xml` file in the rules directory. The following tags are required:
`name`
- For *layouts*, this is the name of the corresponding *file*. - For *variant*, this is the name of the corresponding *section* in the file. - For *options*, this is the unique identifier used in the *rules* file (see @ref user-config-option ""), usually following the pattern `:`.
`shortDescription`
For layout and variants, this is the [ISO 639] language code.
`description`
This is the text that will be displayed to label the entry. For layouts and variants, this should be the same as `name[Group1]`.
See the [xkeyboard-config][xkeyboard-config-contrib] documentation for further information. [ISO 639]: https://en.wikipedia.org/wiki/ISO_639 [xkeyboard-config-contrib]: https://xkeyboard-config.freedesktop.org/doc/contributing/#layouts-variants The example below shows the XML file that would add the custom layout and custom options as outlined above to the XKB registry: @figure@figcaption Content of `$XDG_CONFIG_HOME/xkb/rules/evdev.xml` @endfigcaption ```xml banana ban Banana (US) orange or Banana (Eurosign on 5) us broccoli bro Broccoli custom Custom options ``` @endfigure The default behavior of `libxkbregistry` ensures that the new layout and options are added to the system-provided layouts and options. For details on the XML format, see the DTD in `/X11/xkb/rules/xkb.dtd` and the system-provided XML files `/X11/xkb/rules/*.xml`. @note Depending on the desktop environment, it may require restarting the session in order to make the configuration changes effective. @note It is advised to try the custom configuration *before* restarting the session using the various `xkbcli` tools. See [debugging] for further details. xkbcommon-libxkbcommon-54ee7ac/fuzz/000077500000000000000000000000001510033435100176615ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/fuzz/compose/000077500000000000000000000000001510033435100213265ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/fuzz/compose/dict000066400000000000000000000000711510033435100221720ustar00rootroot00000000000000"Ctrl" "Lock" "Caps" "Shift" "Alt" "Meta" "None" "acute" xkbcommon-libxkbcommon-54ee7ac/fuzz/compose/target.c000066400000000000000000000022031510033435100227550ustar00rootroot00000000000000/* * A target program for fuzzing the Compose text format. * * Currently, just parses an input file, and hopefully doesn't crash or hang. */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-compose.h" int main(int argc, char *argv[]) { struct xkb_context *ctx; FILE *file; struct xkb_compose_table *table; if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); return 1; } ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES | XKB_CONTEXT_NO_ENVIRONMENT_NAMES); assert(ctx); #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); while (__AFL_LOOP(1000)) #endif { file = fopen(argv[1], "rb"); assert(file); table = xkb_compose_table_new_from_file(ctx, file, "en_US.UTF-8", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); xkb_compose_table_unref(table); fclose(file); } puts(table ? "OK" : "FAIL"); xkb_context_unref(ctx); } xkbcommon-libxkbcommon-54ee7ac/fuzz/compose/testcases/000077500000000000000000000000001510033435100233245ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/fuzz/compose/testcases/Compose000066400000000000000000000001771510033435100246610ustar00rootroot00000000000000 : "~" asciitilde # X Meta !Alt ~Shift : "\"\'\x43\123abc" acute # Y xkbcommon-libxkbcommon-54ee7ac/fuzz/fuzz.sh000077500000000000000000000005771510033435100212270ustar00rootroot00000000000000#!/bin/sh set -e case "$1" in keymap|compose) ;; *) echo "usage: $0 keymap|compose" 1>&2 exit 1 ;; esac export CC=afl-clang-fast export AFL_HARDEN=1 test -d fuzz/build || meson setup -Db_lto=true fuzz/build meson compile -C fuzz/build afl-fuzz -i fuzz/$1/testcases -x fuzz/$1/dict -o fuzz/$1/findings -t 200 -m 10 -- ./fuzz/build/fuzz-$1 @@ xkbcommon-libxkbcommon-54ee7ac/fuzz/keymap/000077500000000000000000000000001510033435100211475ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/fuzz/keymap/dict000066400000000000000000000023071510033435100220170ustar00rootroot00000000000000"Control" "Group1" "Group5" "Lock" "Mod1" "Mod9" "Shift" "U1" "0x1" "Up" "accel" "action" "actions" "affect" "alias" "all" "allowexplicit" "allownone" "alphanumeric_keys" "alternate" "alternate_group" "any" "augment" "both" "button" "clearLocks" "clearmods" "controls" "count" "ctrls" "data" "default" "dev" "device" "dfltbtn" "driveskbd" "false" "foo" "function_keys" "genKeyEvent" "group" "groupname" "groups" "groupsclamp" "groupsredirect" "groupswrap" "hidden" "include" "increment" "index" "indicator" "indicatordriveskbd" "interpret" "kc" "key" "keycode" "keypad_keys" "keys" "latchToLock" "leddriveskbd" "levelname" "lock" "locking" "logo" "map" "mod_map" "modifier_keys" "modifier_map" "modifiers" "modmap" "modmapmods" "mods" "name" "neither" "no" "none" "nosymbol" "off" "on" "outline" "overlay" "override" "partial" "preserve" "radiogroup" "repeat" "replace" "report" "row" "same" "sameServer" "screen" "section" "shape" "solid" "symbols" "text" "true" "type" "unlock" "usemodmap" "value" "virtual" "virtual_modifiers" "virtualmod" "vmods" "voidsymbol" "whichgroupstate" "whichmodstate" "x" "xkb_compat" "xkb_geometry" "xkb_keycodes" "xkb_keymap" "xkb_layout" "xkb_semantics" "xkb_symbols" "xkb_types" "y" "yes" xkbcommon-libxkbcommon-54ee7ac/fuzz/keymap/target.c000066400000000000000000000017771510033435100226150ustar00rootroot00000000000000/* * A target program for fuzzing the XKB keymap text format. * * Currently, just parses an input file, and hopefully doesn't crash or hang. */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" int main(int argc, char *argv[]) { struct xkb_context *ctx; FILE *file; struct xkb_keymap *keymap; if (argc != 2) { fprintf(stderr, "usage: %s \n", argv[0]); return 1; } ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES | XKB_CONTEXT_NO_ENVIRONMENT_NAMES); assert(ctx); #ifdef __AFL_HAVE_MANUAL_CONTROL __AFL_INIT(); while (__AFL_LOOP(1000)) #endif { file = fopen(argv[1], "rb"); assert(file); keymap = xkb_keymap_new_from_file(ctx, file, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); xkb_keymap_unref(keymap); fclose(file); } puts(keymap ? "OK" : "FAIL"); xkb_context_unref(ctx); } xkbcommon-libxkbcommon-54ee7ac/fuzz/keymap/testcases/000077500000000000000000000000001510033435100231455ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/fuzz/keymap/testcases/input.xkb000066400000000000000000000024531510033435100250160ustar00rootroot00000000000000xkb_keymap{ xkb_keycodes"0"{ minimum=0; maximum=500; =0; indicator 1="X"; alias=; }; xkb_types"X"{ virtual_modifiers NumLock; type"X"{ modifiers=Shift; map[Shift]=Level2; level_name[Level1]="X"; preserve[Shift]=Shift; }; }; partial xkb_compat{ virtual_modifiers Alt; interpret.useModMapMods=AnyLevel; interpret.repeat=False; interpret.locking=False; interpret ISO_Level2_Latch+Exactly(Shift){ repeat=True; virtualModifier=NumLock; useModMapMods=level1; action=LatchMods(modifiers=Shift,clearLocks,latchToLock); action=MovePtr(x=+0,y=-0); action=SwitchScreen(screen=00,!same); action=Private(type=0x80,data[0]=0x00); }; indicator"X"{whichModState=locked;modifiers=Lock;}; }; xkb_symbols{ name[group1]="X"; key{type[group2]="X",symbols[Group1]=[0,exclam],symbols[Group2]=[0xff,U00],symbols[Group3]=[z]}; modifier_map Control{}; }; default xkb_geometry"X"{ description="X"; width=470; shape.cornerRadius=1; shape"NORM"{cornerRadius=0,{[0.0,0]},{[0,0],[0,0.0]}}; solid"X"{shape="X";top=00;left=00;color="X";}; indicator.onColor="X"; indicator.top=00.0; indicator.shape="X"; indicator"X"{left=0;}; text.top=00; text.color="X"; text"X"{left=0;text="X";}; section.left=00; row.left=0; key.shape="X"; key.gap=1; section"X"{top=22;row{top=1;keys{{,color="X"},{,00.0},,,};};}; alias=; }; }; xkbcommon-libxkbcommon-54ee7ac/include/000077500000000000000000000000001510033435100203065ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/include/xkbcommon/000077500000000000000000000000001510033435100223035ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/include/xkbcommon/xkbcommon-compat.h000066400000000000000000000062211510033435100257330ustar00rootroot00000000000000/* * Copyright © 2012 Daniel Stone * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #ifndef _XKBCOMMON_COMPAT_H #define _XKBCOMMON_COMPAT_H /** * Renamed keymap API. */ #define xkb_group_index_t xkb_layout_index_t #define xkb_group_mask_t xkb_layout_mask_t #define xkb_map_compile_flags xkb_keymap_compile_flags #define XKB_GROUP_INVALID XKB_LAYOUT_INVALID #define XKB_STATE_DEPRESSED \ (XKB_STATE_MODS_DEPRESSED | XKB_STATE_LAYOUT_DEPRESSED) #define XKB_STATE_LATCHED \ (XKB_STATE_MODS_LATCHED | XKB_STATE_LAYOUT_LATCHED) #define XKB_STATE_LOCKED \ (XKB_STATE_MODS_LOCKED | XKB_STATE_LAYOUT_LOCKED) #define XKB_STATE_EFFECTIVE \ (XKB_STATE_DEPRESSED | XKB_STATE_LATCHED | XKB_STATE_LOCKED | \ XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LAYOUT_EFFECTIVE) #define xkb_map_new_from_names(context, names, flags) \ xkb_keymap_new_from_names(context, names, flags) #define xkb_map_new_from_file(context, file, format, flags) \ xkb_keymap_new_from_file(context, file, format, flags) #define xkb_map_new_from_string(context, string, format, flags) \ xkb_keymap_new_from_string(context, string, format, flags) #define xkb_map_get_as_string(keymap) \ xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1) #define xkb_map_ref(keymap) xkb_keymap_ref(keymap) #define xkb_map_unref(keymap) xkb_keymap_unref(keymap) #define xkb_map_num_mods(keymap) xkb_keymap_num_mods(keymap) #define xkb_map_mod_get_name(keymap, idx) xkb_keymap_mod_get_name(keymap, idx) #define xkb_map_mod_get_index(keymap, str) xkb_keymap_mod_get_index(keymap, str) #define xkb_key_mod_index_is_consumed(state, key, mod) \ xkb_state_mod_index_is_consumed(state, key, mod) #define xkb_key_mod_mask_remove_consumed(state, key, modmask) \ xkb_state_mod_mask_remove_consumed(state, key, modmask) #define xkb_map_num_groups(keymap) xkb_keymap_num_layouts(keymap) #define xkb_key_num_groups(keymap, key) \ xkb_keymap_num_layouts_for_key(keymap, key) #define xkb_map_group_get_name(keymap, idx) \ xkb_keymap_layout_get_name(keymap, idx) #define xkb_map_group_get_index(keymap, str) \ xkb_keymap_layout_get_index(keymap, str) #define xkb_map_num_leds(keymap) xkb_keymap_num_leds(keymap) #define xkb_map_led_get_name(keymap, idx) xkb_keymap_led_get_name(keymap, idx) #define xkb_map_led_get_index(keymap, str) \ xkb_keymap_led_get_index(keymap, str) #define xkb_key_repeats(keymap, key) xkb_keymap_key_repeats(keymap, key) #define xkb_key_get_syms(state, key, syms_out) \ xkb_state_key_get_syms(state, key, syms_out) #define xkb_state_group_name_is_active(state, name, type) \ xkb_state_layout_name_is_active(state, name, type) #define xkb_state_group_index_is_active(state, idx, type) \ xkb_state_layout_index_is_active(state, idx, type) #define xkb_state_serialize_group(state, component) \ xkb_state_serialize_layout(state, component) #define xkb_state_get_map(state) xkb_state_get_keymap(state) /* Not needed anymore, since there's NO_FLAGS. */ #define XKB_MAP_COMPILE_PLACEHOLDER XKB_KEYMAP_COMPILE_NO_FLAGS #define XKB_MAP_COMPILE_NO_FLAGS XKB_KEYMAP_COMPILE_NO_FLAGS #endif xkbcommon-libxkbcommon-54ee7ac/include/xkbcommon/xkbcommon-compose.h000066400000000000000000000456361510033435100261320ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #ifndef _XKBCOMMON_COMPOSE_H #define _XKBCOMMON_COMPOSE_H #include #ifdef __cplusplus extern "C" { #endif /** * @file * libxkbcommon Compose API - support for Compose and dead-keys. */ /** * @defgroup compose Compose and dead-keys support * Support for Compose and dead-keys. * @since 0.5.0 * * @{ */ /** * @page compose-overview Overview * @parblock * * Compose and dead-keys are a common feature of many keyboard input * systems. They extend the range of the keysyms that can be produced * directly from a keyboard by using a sequence of key strokes, instead * of just one. * * Here are some example sequences, in the libX11 Compose file format: * * : "á" aacute # LATIN SMALL LETTER A WITH ACUTE * : "@" at # COMMERCIAL AT * * When the user presses a key which produces the `` keysym, * nothing initially happens (thus the key is dubbed a *dead-key*). But * when the user enters ``, “á” is *composed*, in place of “a”. If * instead the user had entered a keysym which does not follow * `` in any compose sequence, the sequence is said to be * *cancelled*. * * Compose files define many such sequences. For a description of the * common file format for Compose files, see the `Compose(5)` man page. * * A successfully-composed sequence has two results: a keysym and a UTF-8 * string. At least one of the two is defined for each sequence. If only * a keysym is given, the keysym’s string representation is used for the * result string (using xkb_keysym_to_utf8()). * * This library provides low-level support for Compose file parsing and * processing. Higher-level APIs (such as libX11’s `Xutf8LookupString(3)`) * may be built upon it, or it can be used directly. * * @endparblock */ /** * @page compose-conflicting Conflicting Sequences * @parblock * * To avoid ambiguity, a sequence is not allowed to be a prefix of another. * When such a conflict occurs, the sequence defined last is the one retained. * * Sequences of length 1 are allowed. * * @endparblock */ /** * @page compose-cancellation Cancellation Behavior * @parblock * * What should happen when a sequence is cancelled? For example, consider * there are only the above sequences, and the input keysyms are * ` `. There are a few approaches: * * 1. Swallow the cancelling keysym; that is, no keysym is produced. * This is the approach taken by libX11. * 2. Let the cancelling keysym through; that is, `` is produced. * 3. Replay the entire sequence; that is, ` ` is produced. * This is the approach taken by Microsoft Windows (approximately; * instead of ``, the underlying key is used. This is * difficult to simulate with XKB keymaps). * * You can program whichever approach best fits users' expectations. * * @endparblock */ /** * @struct xkb_compose_table * Opaque Compose table object. * * The compose table holds the definitions of the Compose sequences, as * gathered from Compose files. It is immutable. */ struct xkb_compose_table; /** * @struct xkb_compose_state * Opaque Compose state object. * * The compose state maintains state for compose sequence matching, such * as which possible sequences are being matched, and the position within * these sequences. It acts as a simple state machine wherein keysyms are * the input, and composed keysyms and strings are the output. * * The compose state is usually associated with a keyboard device. */ struct xkb_compose_state; /** Flags affecting Compose file compilation. */ enum xkb_compose_compile_flags { /** Do not apply any flags. */ XKB_COMPOSE_COMPILE_NO_FLAGS = 0 }; /** The recognized Compose file formats. */ enum xkb_compose_format { /** The classic libX11 Compose text format, described in Compose(5). */ XKB_COMPOSE_FORMAT_TEXT_V1 = 1 }; /** * @page compose-locale Compose Locale * @parblock * * Compose files are locale dependent: * - Compose files are written for a locale, and the locale is used when * searching for the appropriate file to use. * - Compose files may reference the locale internally, with directives * such as `%%L`. * * As such, functions like `xkb_compose_table::xkb_compose_table_new_from_locale()` * require a `locale` parameter. This will usually be the current locale (see * `locale(7)` for more details). You may also want to allow the user to * explicitly configure it, so he can use the Compose file of a given * locale, but not use that locale for other things. * * You may query the current locale as follows: * * ```c * const char *locale; * locale = setlocale(LC_CTYPE, NULL); * ``` * * This will only give useful results if the program had previously set * the current locale using setlocale(3), with `LC_CTYPE` or `LC_ALL` * and a non-`NULL` argument. * * If you prefer not to use the locale system of the C runtime library, * you may nevertheless obtain the user’s locale directly using * environment variables, as described in `locale(7)`. For example, * * ```c * const char *locale; * locale = getenv("LC_ALL"); * if (!locale || !*locale) * locale = getenv("LC_CTYPE"); * if (!locale || !*locale) * locale = getenv("LANG"); * if (!locale || !*locale) * locale = "C"; * ``` * * Note that some locales supported by the C standard library may not * have a Compose file assigned. * * @endparblock */ /** * Create a compose table for a given locale. * * The locale is used for searching the file-system for an appropriate * Compose file. The search order is described in Compose(5). It is * affected by the following environment variables: * * 1. `XCOMPOSEFILE` - see Compose(5). * 2. `XDG_CONFIG_HOME` - before `$HOME/.XCompose` is checked, * `$XDG_CONFIG_HOME/XCompose` is checked (with a fall back to * `$HOME/.config/XCompose` if `XDG_CONFIG_HOME` is not defined). * This is a libxkbcommon extension to the search procedure in * Compose(5) (since libxkbcommon 1.0.0). Note that other * implementations, such as libX11, might not find a Compose file in * this path. * 3. `HOME` - see Compose(5). * 4. `XLOCALEDIR` - if set, used as the base directory for the system’s * X locale files, e.g. `/usr/share/X11/locale`, instead of the * preconfigured directory. * * Since 1.12, system locales not registered in `$XLOCALEDIR` will fallback * to `en_US.UTF-8`, if missing locale detection is supported by the C standard * library in use. * * @param context * The library context in which to create the compose table. * @param locale * The current locale. See @ref compose-locale. * \n * The value is copied, so it is safe to pass the result of `getenv(3)` * (or similar) without fear of it being invalidated by a subsequent * `setenv(3)` (or similar). * @param flags * Optional flags for the compose table, or 0. * * @returns A compose table for the given locale, or `NULL` if the * compilation failed or a Compose file was not found. * * @memberof xkb_compose_table */ XKB_EXPORT struct xkb_compose_table * xkb_compose_table_new_from_locale(struct xkb_context *context, const char *locale, enum xkb_compose_compile_flags flags); /** * Create a new compose table from a Compose file. * * @param context * The library context in which to create the compose table. * @param file * The Compose file to compile. * @param locale * The current locale. See @ref compose-locale. * @param format * The text format of the Compose file to compile. * @param flags * Optional flags for the compose table, or 0. * * @returns A compose table compiled from the given file, or `NULL` if * the compilation failed. * * @memberof xkb_compose_table */ XKB_EXPORT struct xkb_compose_table * xkb_compose_table_new_from_file(struct xkb_context *context, FILE *file, const char *locale, enum xkb_compose_format format, enum xkb_compose_compile_flags flags); /** * Create a new compose table from a memory buffer. * * This is just like xkb_compose_table_new_from_file(), but instead of * a file, gets the table as one enormous string. * * @see xkb_compose_table_new_from_file() * @memberof xkb_compose_table */ XKB_EXPORT struct xkb_compose_table * xkb_compose_table_new_from_buffer(struct xkb_context *context, const char *buffer, size_t length, const char *locale, enum xkb_compose_format format, enum xkb_compose_compile_flags flags); /** * Take a new reference on a compose table. * * @returns The passed in object. * * @memberof xkb_compose_table */ XKB_EXPORT struct xkb_compose_table * xkb_compose_table_ref(struct xkb_compose_table *table); /** * Release a reference on a compose table, and possibly free it. * * @param table The object. If it is `NULL`, this function does nothing. * * @memberof xkb_compose_table */ XKB_EXPORT void xkb_compose_table_unref(struct xkb_compose_table *table); /** * @struct xkb_compose_table_entry * Opaque Compose table entry object. * * Represents a single entry in a Compose file in the iteration API. * It is immutable. * * @sa xkb_compose_table_iterator_new * @since 1.6.0 */ struct xkb_compose_table_entry; /** * Get the left-hand keysym sequence of a Compose table entry. * * For example, given the following entry: * * ``` * : "~" asciitilde # TILDE * ``` * * it will return `{XKB_KEY_dead_tilde, XKB_KEY_space}`. * * @param[in] entry The compose table entry object to process. * * @param[out] sequence_length Number of keysyms in the sequence. * * @returns The array of left-hand side keysyms. The number of keysyms * is returned in the @p sequence_length out-parameter. * * @memberof xkb_compose_table_entry * @since 1.6.0 */ XKB_EXPORT const xkb_keysym_t * xkb_compose_table_entry_sequence(struct xkb_compose_table_entry *entry, size_t *sequence_length); /** * Get the right-hand result keysym of a Compose table entry. * * For example, given the following entry: * * ``` * : "~" asciitilde # TILDE * ``` * * it will return `XKB_KEY_asciitilde`. * * The keysym is optional; if the entry does not specify a keysym, * returns `XKB_KEY_NoSymbol`. * * @memberof xkb_compose_table_entry * @since 1.6.0 */ XKB_EXPORT xkb_keysym_t xkb_compose_table_entry_keysym(struct xkb_compose_table_entry *entry); /** * Get the right-hand result string of a Compose table entry. * * The string is UTF-8 encoded and `NULL`-terminated. * * For example, given the following entry: * * ``` * : "~" asciitilde # TILDE * ``` * * it will return `"~"`. * * The string is optional; if the entry does not specify a string, * returns the empty string. * * @memberof xkb_compose_table_entry * @since 1.6.0 */ XKB_EXPORT const char * xkb_compose_table_entry_utf8(struct xkb_compose_table_entry *entry); /** * @struct xkb_compose_table_iterator * Iterator over a compose table’s entries. * * @sa xkb_compose_table_iterator_new() * @since 1.6.0 */ struct xkb_compose_table_iterator; /** * Create a new iterator for a compose table. * * Intended use: * * ```c * struct xkb_compose_table_iterator *iter = xkb_compose_table_iterator_new(compose_table); * struct xkb_compose_table_entry *entry; * while ((entry = xkb_compose_table_iterator_next(iter))) { * // ... * } * xkb_compose_table_iterator_free(iter); * ``` * * @returns A new compose table iterator, or `NULL` on failure. * * @memberof xkb_compose_table_iterator * @sa xkb_compose_table_iterator_free() * @since 1.6.0 */ XKB_EXPORT struct xkb_compose_table_iterator * xkb_compose_table_iterator_new(struct xkb_compose_table *table); /** * Free a compose iterator. * * @memberof xkb_compose_table_iterator * @since 1.6.0 */ XKB_EXPORT void xkb_compose_table_iterator_free(struct xkb_compose_table_iterator *iter); /** * Get the next compose entry from a compose table iterator. * * The entries are returned in lexicographic order of the left-hand * side of entries. This does not correspond to the order in which * the entries appear in the Compose file. * * @attention The return value is valid until the next call to this function. * * Returns `NULL` in case there is no more entries. * * @memberof xkb_compose_table_iterator * @since 1.6.0 */ XKB_EXPORT struct xkb_compose_table_entry * xkb_compose_table_iterator_next(struct xkb_compose_table_iterator *iter); /** Flags for compose state creation. */ enum xkb_compose_state_flags { /** Do not apply any flags. */ XKB_COMPOSE_STATE_NO_FLAGS = 0 }; /** * Create a new compose state object. * * @param table * The compose table the state will use. * @param flags * Optional flags for the compose state, or 0. * * @returns A new compose state, or `NULL` on failure. * * @memberof xkb_compose_state */ XKB_EXPORT struct xkb_compose_state * xkb_compose_state_new(struct xkb_compose_table *table, enum xkb_compose_state_flags flags); /** * Take a new reference on a compose state object. * * @returns The passed in object. * * @memberof xkb_compose_state */ XKB_EXPORT struct xkb_compose_state * xkb_compose_state_ref(struct xkb_compose_state *state); /** * Release a reference on a compose state object, and possibly free it. * * @param state The object. If `NULL`, do nothing. * * @memberof xkb_compose_state */ XKB_EXPORT void xkb_compose_state_unref(struct xkb_compose_state *state); /** * Get the compose table which a compose state object is using. * * @returns The compose table which was passed to xkb_compose_state_new() * when creating this state object. * * This function does not take a new reference on the compose table; you * must explicitly reference it yourself if you plan to use it beyond the * lifetime of the state. * * @memberof xkb_compose_state */ XKB_EXPORT struct xkb_compose_table * xkb_compose_state_get_compose_table(struct xkb_compose_state *state); /** Status of the Compose sequence state machine. */ enum xkb_compose_status { /** The initial state; no sequence has started yet. */ XKB_COMPOSE_NOTHING, /** In the middle of a sequence. */ XKB_COMPOSE_COMPOSING, /** A complete sequence has been matched. */ XKB_COMPOSE_COMPOSED, /** The last sequence was cancelled due to an unmatched keysym. */ XKB_COMPOSE_CANCELLED }; /** The effect of a keysym fed to xkb_compose_state_feed(). */ enum xkb_compose_feed_result { /** The keysym had no effect - it did not affect the status. */ XKB_COMPOSE_FEED_IGNORED, /** The keysym started, advanced or cancelled a sequence. */ XKB_COMPOSE_FEED_ACCEPTED }; /** * Feed one keysym to the Compose sequence state machine. * * This function can advance into a compose sequence, cancel a sequence, * start a new sequence, or do nothing in particular. The resulting * status may be observed with `xkb_compose_state_get_status()`. * * Some keysyms, such as keysyms for modifier keys, are ignored - they * have no effect on the status or otherwise. * * The following is a description of the possible status transitions, in * the format CURRENT STATUS => NEXT STATUS, given a non-ignored input * keysym `keysym`: * @verbatim NOTHING or CANCELLED or COMPOSED => NOTHING if keysym does not start a sequence. COMPOSING if keysym starts a sequence. COMPOSED if keysym starts and terminates a single-keysym sequence. COMPOSING => COMPOSING if keysym advances any of the currently possible sequences but does not terminate any of them. COMPOSED if keysym terminates one of the currently possible sequences. CANCELLED if keysym does not advance any of the currently possible sequences. @endverbatim * * The current Compose formats do not support multiple-keysyms. Therefore, if * you are using a function such as `xkb_state::xkb_state_key_get_syms()` * and it returns more than one keysym, consider feeding `XKB_KEY_NoSymbol` * instead. * * @param state * The compose state object. * @param keysym * A keysym, usually obtained after a key-press event, with a * function such as `xkb_state::xkb_state_key_get_one_sym()`. * * @returns Whether the keysym was ignored. This is useful, for example, * if you want to keep a record of the sequence matched thus far. * * @memberof xkb_compose_state */ XKB_EXPORT enum xkb_compose_feed_result xkb_compose_state_feed(struct xkb_compose_state *state, xkb_keysym_t keysym); /** * Reset the Compose sequence state machine. * * The status is set to `::XKB_COMPOSE_NOTHING`, and the current sequence * is discarded. * * @memberof xkb_compose_state */ XKB_EXPORT void xkb_compose_state_reset(struct xkb_compose_state *state); /** * Get the current status of the compose state machine. * * @see xkb_compose_status * @memberof xkb_compose_state **/ XKB_EXPORT enum xkb_compose_status xkb_compose_state_get_status(struct xkb_compose_state *state); /** * Get the result Unicode/UTF-8 string for a composed sequence. * * See @ref compose-overview for more details. This function is only * useful when the status is `::XKB_COMPOSE_COMPOSED`. * * @param[in] state * The compose state. * @param[out] buffer * A buffer to write the string into. * @param[in] size * Size of the buffer. * * @warning If the buffer passed is too small, the string is truncated * (though still `NULL`-terminated). * * @returns * The number of bytes required for the string, excluding the `NULL` byte. * If the sequence is not complete, or does not have a viable result * string, returns 0, and sets `buffer` to the empty string (if possible). * @returns * You may check if truncation has occurred by comparing the return value * with the size of `buffer`, similarly to the `snprintf(3)` function. * You may safely pass `NULL` and 0 to `buffer` and `size` to find the * required size (without the `NULL`-byte). * * @memberof xkb_compose_state **/ XKB_EXPORT int xkb_compose_state_get_utf8(struct xkb_compose_state *state, char *buffer, size_t size); /** * Get the result keysym for a composed sequence. * * See @ref compose-overview for more details. This function is only * useful when the status is `::XKB_COMPOSE_COMPOSED`. * * @returns The result keysym. If the sequence is not complete, or does * not specify a result keysym, returns `XKB_KEY_NoSymbol`. * * @memberof xkb_compose_state **/ XKB_EXPORT xkb_keysym_t xkb_compose_state_get_one_sym(struct xkb_compose_state *state); /** @} */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* _XKBCOMMON_COMPOSE_H */ xkbcommon-libxkbcommon-54ee7ac/include/xkbcommon/xkbcommon-keysyms.h000066400000000000000000010015151510033435100261560ustar00rootroot00000000000000#ifndef _XKBCOMMON_KEYSYMS_H #define _XKBCOMMON_KEYSYMS_H /* This file is autogenerated; please do not commit directly. */ /** * @file * Key symbols (keysyms) definitions. */ #define XKB_KEY_NoSymbol 0x000000 /* Special KeySym */ /*********************************************************** Copyright 1987, 1994, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* * The "X11 Window System Protocol" standard defines in Appendix A the * keysym codes. These 29-bit integer values identify characters or * functions associated with each key (e.g., via the visible * engraving) of a keyboard layout. This file assigns mnemonic macro * names for these keysyms. * * This file is also compiled (by src/util/makekeys.c in libX11) into * hash tables that can be accessed with X11 library functions such as * XStringToKeysym() and XKeysymToString(). * * Where a keysym corresponds one-to-one to an ISO 10646 / Unicode * character, this is noted in a comment that provides both the U+xxxx * Unicode position, as well as the official Unicode name of the * character. * * Some keysyms map to a character already mapped by another keysym, * with compatible but more precise semantics, such as the keypad- * related keysyms. In this case, none of the keysym are deprecated. * The most generic keysym is annotated as previously and more specific * keysyms have the same annotation between angle brackets: * * #define XKB_KEY_space 0x0020 // U+0020 SPACE * #define XKB_KEY_KP_Space 0xff80 // * * Where the correspondence is either not one-to-one or semantically * unclear, the Unicode position and name are enclosed in * parentheses. Such legacy keysyms should be considered deprecated * and are not recommended for use in future keyboard mappings. * * For any future extension of the keysyms with characters already * found in ISO 10646 / Unicode, the following algorithm shall be * used. The new keysym code position will simply be the character's * Unicode number plus 0x01000000. The keysym values in the range * 0x01000100 to 0x0110ffff are reserved to represent Unicode * characters in the range U+0100 to U+10FFFF. * * While most newer Unicode-based X11 clients do already accept * Unicode-mapped keysyms in the range 0x01000100 to 0x0110ffff, it * will remain necessary for clients -- in the interest of * compatibility with existing servers -- to also understand the * existing legacy keysym values in the range 0x0100 to 0x20ff. * * Where several mnemonic names are defined for the same keysym in this * file, the first one listed is considered the "canonical" name. This * is the name that should be used when retrieving a keysym name from * its code. The next names are considered "aliases" to the canonical * name. * * Aliases are made explicit by writing in their comment "alias for", * followed by the corresponding canonical name. Example: * * #define XKB_KEY_dead_tilde 0xfe53 * #define XKB_KEY_dead_perispomeni 0xfe53 // alias for dead_tilde * * The rules to consider a keysym mnemonic name deprecated are: * * 1. A legacy keysym with its Unicode mapping in parentheses is * deprecated (see above). * * 2. A keysym name is *explicitly* deprecated by starting its comment * with "deprecated". Examples: * * #define XKB_KEY_L1 0xffc8 // deprecated alias for F11 * #define XKB_KEY_quoteleft 0x0060 // deprecated * * 3. A keysym name is *explicitly* *not* deprecated by starting its * comment with "non-deprecated alias". Examples: * * #define XKB_KEY_dead_tilde 0xfe53 * #define XKB_KEY_dead_perispomeni 0xfe53 // non-deprecated alias for dead_tilde * * 4. If none of the previous rules apply, an alias is *implicitly* * deprecated if there is at least one previous name for the * corresponding keysym that is *not* explicitly deprecated. * * Examples: * * // SingleCandidate is the canonical name * #define XKB_KEY_SingleCandidate 0xff3c * // Hangul_SingleCandidate is deprecated because it is an alias * // and it does not start with "non-deprecated alias" * #define XKB_KEY_Hangul_SingleCandidate 0xff3c // Single candidate * * // guillemotleft is the canonical name, but it is deprecated * #define XKB_KEY_guillemotleft 0x00ab // deprecated alias for guillemetleft (misspelling) * // guillemetleft is not deprecated, because the keysym has no endorsed name before it. * #define XKB_KEY_guillemetleft 0x00ab // U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK * // The following hypothetical name is deprecated because guillemetleft come before. * #define XKB_KEY_guillemetleft2 0x00ab * * Mnemonic names for keysyms are defined in this file with lines * that match one of these Perl regular expressions: * * /^\#define XKB_KEY_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\* U\+([0-9A-F]{4,6}) (.*) \*\/\s*$/ * /^\#define XKB_KEY_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\*\*\/\s*$/ * /^\#define XKB_KEY_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*\/\*\(U\+([0-9A-F]{4,6}) (.*)\)\*\/\s*$/ * /^\#define XKB_KEY_([a-zA-Z_0-9]+)\s+0x([0-9a-f]+)\s*(\/\*\s*(.*)\s*\*\/)?\s*$/ * * Before adding new keysyms, please do consider the following: In * addition to the keysym names defined in this file, the * XStringToKeysym() and XKeysymToString() functions will also handle * any keysym string of the form "U0020" to "U007E" and "U00A0" to * "U10FFFF" for all possible Unicode characters. In other words, * every possible Unicode character has already a keysym string * defined algorithmically, even if it is not listed here. Therefore, * defining an additional keysym macro is only necessary where a * non-hexadecimal mnemonic name is needed, or where the new keysym * does not represent any existing Unicode character. * * When adding new keysyms to this file, do not forget to also update the * following as needed: * * - the mappings in src/KeyBind.c in the libX11 repo * https://gitlab.freedesktop.org/xorg/lib/libx11 * * - the protocol specification in specs/keysyms.xml in this repo * https://gitlab.freedesktop.org/xorg/proto/xorgproto * * Before removing or changing the order of the keysyms, please consider * the following: it is very difficult to know what keysyms are used and * how. * * - A sandboxed application may have incompatibilities with the host * system. For example, if new keysym name is introduced and is made * the canonical name, then an application with an older keysym parser * will not be able to parse the new name. * - Customization of keyboard layout and Compose files are two popular * use cases. Checking the standard keyboard layout database xkeyboard-config * https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config * and the standard Compose files in libx11 * https://gitlab.freedesktop.org/xorg/lib/libx11 is a mandatory * step, but may *not* be enough for a proper impact assessment for * e.g. keysyms removals. * * Therefore, it is advised to proceed to no removal and to make a new * name canonical only 10 years after its introduction. This means that * some keysyms may have their first listed name deprecated during the * period of transition. Once this period is over, the deprecated name * should be moved after the new canonical name. */ #define XKB_KEY_VoidSymbol 0xffffff /* Void symbol */ /* * TTY function keys, cleverly chosen to map to ASCII, for convenience of * programming, but could have been arbitrary (at the cost of lookup * tables in client code). */ #define XKB_KEY_BackSpace 0xff08 /* U+0008 BACKSPACE */ #define XKB_KEY_Tab 0xff09 /* U+0009 CHARACTER TABULATION */ #define XKB_KEY_Linefeed 0xff0a /* U+000A LINE FEED */ #define XKB_KEY_Clear 0xff0b /* U+000B LINE TABULATION */ #define XKB_KEY_Return 0xff0d /* U+000D CARRIAGE RETURN */ #define XKB_KEY_Pause 0xff13 /* Pause, hold */ #define XKB_KEY_Scroll_Lock 0xff14 #define XKB_KEY_Sys_Req 0xff15 #define XKB_KEY_Escape 0xff1b /* U+001B ESCAPE */ #define XKB_KEY_Delete 0xffff /* U+007F DELETE */ /* International & multi-key character composition */ #define XKB_KEY_Multi_key 0xff20 /* Multi-key character compose */ #define XKB_KEY_Codeinput 0xff37 #define XKB_KEY_SingleCandidate 0xff3c #define XKB_KEY_MultipleCandidate 0xff3d #define XKB_KEY_PreviousCandidate 0xff3e /* Japanese keyboard support */ #define XKB_KEY_Kanji 0xff21 /* Kanji, Kanji convert */ #define XKB_KEY_Muhenkan 0xff22 /* Cancel Conversion */ #define XKB_KEY_Henkan_Mode 0xff23 /* Start/Stop Conversion */ #define XKB_KEY_Henkan 0xff23 /* non-deprecated alias for Henkan_Mode */ #define XKB_KEY_Romaji 0xff24 /* to Romaji */ #define XKB_KEY_Hiragana 0xff25 /* to Hiragana */ #define XKB_KEY_Katakana 0xff26 /* to Katakana */ #define XKB_KEY_Hiragana_Katakana 0xff27 /* Hiragana/Katakana toggle */ #define XKB_KEY_Zenkaku 0xff28 /* to Zenkaku */ #define XKB_KEY_Hankaku 0xff29 /* to Hankaku */ #define XKB_KEY_Zenkaku_Hankaku 0xff2a /* Zenkaku/Hankaku toggle */ #define XKB_KEY_Touroku 0xff2b /* Add to Dictionary */ #define XKB_KEY_Massyo 0xff2c /* Delete from Dictionary */ #define XKB_KEY_Kana_Lock 0xff2d /* Kana Lock */ #define XKB_KEY_Kana_Shift 0xff2e /* Kana Shift */ #define XKB_KEY_Eisu_Shift 0xff2f /* Alphanumeric Shift */ #define XKB_KEY_Eisu_toggle 0xff30 /* Alphanumeric toggle */ #define XKB_KEY_Kanji_Bangou 0xff37 /* Codeinput */ #define XKB_KEY_Zen_Koho 0xff3d /* Multiple/All Candidate(s) */ #define XKB_KEY_Mae_Koho 0xff3e /* Previous Candidate */ /* 0xff31 thru 0xff3f are under XK_KOREAN */ /* Cursor control & motion */ #define XKB_KEY_Home 0xff50 #define XKB_KEY_Left 0xff51 /* Move left, left arrow */ #define XKB_KEY_Up 0xff52 /* Move up, up arrow */ #define XKB_KEY_Right 0xff53 /* Move right, right arrow */ #define XKB_KEY_Down 0xff54 /* Move down, down arrow */ #define XKB_KEY_Prior 0xff55 /* Prior, previous */ #define XKB_KEY_Page_Up 0xff55 /* deprecated alias for Prior */ #define XKB_KEY_Next 0xff56 /* Next */ #define XKB_KEY_Page_Down 0xff56 /* deprecated alias for Next */ #define XKB_KEY_End 0xff57 /* EOL */ #define XKB_KEY_Begin 0xff58 /* BOL */ /* Misc functions */ #define XKB_KEY_Select 0xff60 /* Select, mark */ #define XKB_KEY_Print 0xff61 #define XKB_KEY_Execute 0xff62 /* Execute, run, do */ #define XKB_KEY_Insert 0xff63 /* Insert, insert here */ #define XKB_KEY_Undo 0xff65 #define XKB_KEY_Redo 0xff66 /* Redo, again */ #define XKB_KEY_Menu 0xff67 #define XKB_KEY_Find 0xff68 /* Find, search */ #define XKB_KEY_Cancel 0xff69 /* Cancel, stop, abort, exit */ #define XKB_KEY_Help 0xff6a /* Help */ #define XKB_KEY_Break 0xff6b #define XKB_KEY_Mode_switch 0xff7e /* Character set switch */ #define XKB_KEY_script_switch 0xff7e /* non-deprecated alias for Mode_switch */ #define XKB_KEY_Num_Lock 0xff7f /* Keypad functions, keypad numbers cleverly chosen to map to ASCII */ #define XKB_KEY_KP_Space 0xff80 /**/ #define XKB_KEY_KP_Tab 0xff89 /**/ #define XKB_KEY_KP_Enter 0xff8d /**/ #define XKB_KEY_KP_F1 0xff91 /* PF1, KP_A, ... */ #define XKB_KEY_KP_F2 0xff92 #define XKB_KEY_KP_F3 0xff93 #define XKB_KEY_KP_F4 0xff94 #define XKB_KEY_KP_Home 0xff95 #define XKB_KEY_KP_Left 0xff96 #define XKB_KEY_KP_Up 0xff97 #define XKB_KEY_KP_Right 0xff98 #define XKB_KEY_KP_Down 0xff99 #define XKB_KEY_KP_Prior 0xff9a #define XKB_KEY_KP_Page_Up 0xff9a /* deprecated alias for KP_Prior */ #define XKB_KEY_KP_Next 0xff9b #define XKB_KEY_KP_Page_Down 0xff9b /* deprecated alias for KP_Next */ #define XKB_KEY_KP_End 0xff9c #define XKB_KEY_KP_Begin 0xff9d #define XKB_KEY_KP_Insert 0xff9e #define XKB_KEY_KP_Delete 0xff9f #define XKB_KEY_KP_Equal 0xffbd /**/ #define XKB_KEY_KP_Multiply 0xffaa /**/ #define XKB_KEY_KP_Add 0xffab /**/ #define XKB_KEY_KP_Separator 0xffac /**/ #define XKB_KEY_KP_Subtract 0xffad /**/ #define XKB_KEY_KP_Decimal 0xffae /**/ #define XKB_KEY_KP_Divide 0xffaf /**/ #define XKB_KEY_KP_0 0xffb0 /**/ #define XKB_KEY_KP_1 0xffb1 /**/ #define XKB_KEY_KP_2 0xffb2 /**/ #define XKB_KEY_KP_3 0xffb3 /**/ #define XKB_KEY_KP_4 0xffb4 /**/ #define XKB_KEY_KP_5 0xffb5 /**/ #define XKB_KEY_KP_6 0xffb6 /**/ #define XKB_KEY_KP_7 0xffb7 /**/ #define XKB_KEY_KP_8 0xffb8 /**/ #define XKB_KEY_KP_9 0xffb9 /**/ /* * Auxiliary functions; note the duplicate definitions for left and right * function keys; Sun keyboards and a few other manufacturers have such * function key groups on the left and/or right sides of the keyboard. * We've not found a keyboard with more than 35 function keys total. */ #define XKB_KEY_F1 0xffbe #define XKB_KEY_F2 0xffbf #define XKB_KEY_F3 0xffc0 #define XKB_KEY_F4 0xffc1 #define XKB_KEY_F5 0xffc2 #define XKB_KEY_F6 0xffc3 #define XKB_KEY_F7 0xffc4 #define XKB_KEY_F8 0xffc5 #define XKB_KEY_F9 0xffc6 #define XKB_KEY_F10 0xffc7 #define XKB_KEY_F11 0xffc8 #define XKB_KEY_L1 0xffc8 /* deprecated alias for F11 */ #define XKB_KEY_F12 0xffc9 #define XKB_KEY_L2 0xffc9 /* deprecated alias for F12 */ #define XKB_KEY_F13 0xffca #define XKB_KEY_L3 0xffca /* deprecated alias for F13 */ #define XKB_KEY_F14 0xffcb #define XKB_KEY_L4 0xffcb /* deprecated alias for F14 */ #define XKB_KEY_F15 0xffcc #define XKB_KEY_L5 0xffcc /* deprecated alias for F15 */ #define XKB_KEY_F16 0xffcd #define XKB_KEY_L6 0xffcd /* deprecated alias for F16 */ #define XKB_KEY_F17 0xffce #define XKB_KEY_L7 0xffce /* deprecated alias for F17 */ #define XKB_KEY_F18 0xffcf #define XKB_KEY_L8 0xffcf /* deprecated alias for F18 */ #define XKB_KEY_F19 0xffd0 #define XKB_KEY_L9 0xffd0 /* deprecated alias for F19 */ #define XKB_KEY_F20 0xffd1 #define XKB_KEY_L10 0xffd1 /* deprecated alias for F20 */ #define XKB_KEY_F21 0xffd2 #define XKB_KEY_R1 0xffd2 /* deprecated alias for F21 */ #define XKB_KEY_F22 0xffd3 #define XKB_KEY_R2 0xffd3 /* deprecated alias for F22 */ #define XKB_KEY_F23 0xffd4 #define XKB_KEY_R3 0xffd4 /* deprecated alias for F23 */ #define XKB_KEY_F24 0xffd5 #define XKB_KEY_R4 0xffd5 /* deprecated alias for F24 */ #define XKB_KEY_F25 0xffd6 #define XKB_KEY_R5 0xffd6 /* deprecated alias for F25 */ #define XKB_KEY_F26 0xffd7 #define XKB_KEY_R6 0xffd7 /* deprecated alias for F26 */ #define XKB_KEY_F27 0xffd8 #define XKB_KEY_R7 0xffd8 /* deprecated alias for F27 */ #define XKB_KEY_F28 0xffd9 #define XKB_KEY_R8 0xffd9 /* deprecated alias for F28 */ #define XKB_KEY_F29 0xffda #define XKB_KEY_R9 0xffda /* deprecated alias for F29 */ #define XKB_KEY_F30 0xffdb #define XKB_KEY_R10 0xffdb /* deprecated alias for F30 */ #define XKB_KEY_F31 0xffdc #define XKB_KEY_R11 0xffdc /* deprecated alias for F31 */ #define XKB_KEY_F32 0xffdd #define XKB_KEY_R12 0xffdd /* deprecated alias for F32 */ #define XKB_KEY_F33 0xffde #define XKB_KEY_R13 0xffde /* deprecated alias for F33 */ #define XKB_KEY_F34 0xffdf #define XKB_KEY_R14 0xffdf /* deprecated alias for F34 */ #define XKB_KEY_F35 0xffe0 #define XKB_KEY_R15 0xffe0 /* deprecated alias for F35 */ /* Modifiers */ #define XKB_KEY_Shift_L 0xffe1 /* Left shift */ #define XKB_KEY_Shift_R 0xffe2 /* Right shift */ #define XKB_KEY_Control_L 0xffe3 /* Left control */ #define XKB_KEY_Control_R 0xffe4 /* Right control */ #define XKB_KEY_Caps_Lock 0xffe5 /* Caps lock */ #define XKB_KEY_Shift_Lock 0xffe6 /* Shift lock */ #define XKB_KEY_Meta_L 0xffe7 /* Left meta */ #define XKB_KEY_Meta_R 0xffe8 /* Right meta */ #define XKB_KEY_Alt_L 0xffe9 /* Left alt */ #define XKB_KEY_Alt_R 0xffea /* Right alt */ #define XKB_KEY_Super_L 0xffeb /* Left super */ #define XKB_KEY_Super_R 0xffec /* Right super */ #define XKB_KEY_Hyper_L 0xffed /* Left hyper */ #define XKB_KEY_Hyper_R 0xffee /* Right hyper */ /* * Keyboard (XKB) Extension function and modifier keys * (from Appendix C of "The X Keyboard Extension: Protocol Specification") * Byte 3 = 0xfe */ #define XKB_KEY_ISO_Lock 0xfe01 #define XKB_KEY_ISO_Level2_Latch 0xfe02 #define XKB_KEY_ISO_Level3_Shift 0xfe03 #define XKB_KEY_ISO_Level3_Latch 0xfe04 #define XKB_KEY_ISO_Level3_Lock 0xfe05 #define XKB_KEY_ISO_Level5_Shift 0xfe11 #define XKB_KEY_ISO_Level5_Latch 0xfe12 #define XKB_KEY_ISO_Level5_Lock 0xfe13 #define XKB_KEY_ISO_Group_Shift 0xff7e /* non-deprecated alias for Mode_switch */ #define XKB_KEY_ISO_Group_Latch 0xfe06 #define XKB_KEY_ISO_Group_Lock 0xfe07 #define XKB_KEY_ISO_Next_Group 0xfe08 #define XKB_KEY_ISO_Next_Group_Lock 0xfe09 #define XKB_KEY_ISO_Prev_Group 0xfe0a #define XKB_KEY_ISO_Prev_Group_Lock 0xfe0b #define XKB_KEY_ISO_First_Group 0xfe0c #define XKB_KEY_ISO_First_Group_Lock 0xfe0d #define XKB_KEY_ISO_Last_Group 0xfe0e #define XKB_KEY_ISO_Last_Group_Lock 0xfe0f #define XKB_KEY_ISO_Left_Tab 0xfe20 #define XKB_KEY_ISO_Move_Line_Up 0xfe21 #define XKB_KEY_ISO_Move_Line_Down 0xfe22 #define XKB_KEY_ISO_Partial_Line_Up 0xfe23 #define XKB_KEY_ISO_Partial_Line_Down 0xfe24 #define XKB_KEY_ISO_Partial_Space_Left 0xfe25 #define XKB_KEY_ISO_Partial_Space_Right 0xfe26 #define XKB_KEY_ISO_Set_Margin_Left 0xfe27 #define XKB_KEY_ISO_Set_Margin_Right 0xfe28 #define XKB_KEY_ISO_Release_Margin_Left 0xfe29 #define XKB_KEY_ISO_Release_Margin_Right 0xfe2a #define XKB_KEY_ISO_Release_Both_Margins 0xfe2b #define XKB_KEY_ISO_Fast_Cursor_Left 0xfe2c #define XKB_KEY_ISO_Fast_Cursor_Right 0xfe2d #define XKB_KEY_ISO_Fast_Cursor_Up 0xfe2e #define XKB_KEY_ISO_Fast_Cursor_Down 0xfe2f #define XKB_KEY_ISO_Continuous_Underline 0xfe30 #define XKB_KEY_ISO_Discontinuous_Underline 0xfe31 #define XKB_KEY_ISO_Emphasize 0xfe32 #define XKB_KEY_ISO_Center_Object 0xfe33 #define XKB_KEY_ISO_Enter 0xfe34 #define XKB_KEY_dead_grave 0xfe50 #define XKB_KEY_dead_acute 0xfe51 #define XKB_KEY_dead_circumflex 0xfe52 #define XKB_KEY_dead_tilde 0xfe53 #define XKB_KEY_dead_perispomeni 0xfe53 /* non-deprecated alias for dead_tilde */ #define XKB_KEY_dead_macron 0xfe54 #define XKB_KEY_dead_breve 0xfe55 #define XKB_KEY_dead_abovedot 0xfe56 #define XKB_KEY_dead_diaeresis 0xfe57 #define XKB_KEY_dead_abovering 0xfe58 #define XKB_KEY_dead_doubleacute 0xfe59 #define XKB_KEY_dead_caron 0xfe5a #define XKB_KEY_dead_cedilla 0xfe5b #define XKB_KEY_dead_ogonek 0xfe5c #define XKB_KEY_dead_iota 0xfe5d #define XKB_KEY_dead_voiced_sound 0xfe5e #define XKB_KEY_dead_semivoiced_sound 0xfe5f #define XKB_KEY_dead_belowdot 0xfe60 #define XKB_KEY_dead_hook 0xfe61 #define XKB_KEY_dead_horn 0xfe62 #define XKB_KEY_dead_stroke 0xfe63 #define XKB_KEY_dead_abovecomma 0xfe64 #define XKB_KEY_dead_psili 0xfe64 /* non-deprecated alias for dead_abovecomma */ #define XKB_KEY_dead_abovereversedcomma 0xfe65 #define XKB_KEY_dead_dasia 0xfe65 /* non-deprecated alias for dead_abovereversedcomma */ #define XKB_KEY_dead_doublegrave 0xfe66 #define XKB_KEY_dead_belowring 0xfe67 #define XKB_KEY_dead_belowmacron 0xfe68 #define XKB_KEY_dead_belowcircumflex 0xfe69 #define XKB_KEY_dead_belowtilde 0xfe6a #define XKB_KEY_dead_belowbreve 0xfe6b #define XKB_KEY_dead_belowdiaeresis 0xfe6c #define XKB_KEY_dead_invertedbreve 0xfe6d #define XKB_KEY_dead_belowcomma 0xfe6e #define XKB_KEY_dead_currency 0xfe6f /* extra dead elements for German T3 layout */ #define XKB_KEY_dead_lowline 0xfe90 #define XKB_KEY_dead_aboveverticalline 0xfe91 #define XKB_KEY_dead_belowverticalline 0xfe92 #define XKB_KEY_dead_longsolidusoverlay 0xfe93 /* dead vowels for universal syllable entry */ #define XKB_KEY_dead_a 0xfe80 #define XKB_KEY_dead_A 0xfe81 #define XKB_KEY_dead_e 0xfe82 #define XKB_KEY_dead_E 0xfe83 #define XKB_KEY_dead_i 0xfe84 #define XKB_KEY_dead_I 0xfe85 #define XKB_KEY_dead_o 0xfe86 #define XKB_KEY_dead_O 0xfe87 #define XKB_KEY_dead_u 0xfe88 #define XKB_KEY_dead_U 0xfe89 #define XKB_KEY_dead_small_schwa 0xfe8a /* deprecated alias for dead_schwa */ #define XKB_KEY_dead_schwa 0xfe8a #define XKB_KEY_dead_capital_schwa 0xfe8b /* deprecated alias for dead_SCHWA */ #define XKB_KEY_dead_SCHWA 0xfe8b #define XKB_KEY_dead_greek 0xfe8c #define XKB_KEY_dead_hamza 0xfe8d #define XKB_KEY_First_Virtual_Screen 0xfed0 #define XKB_KEY_Prev_Virtual_Screen 0xfed1 #define XKB_KEY_Next_Virtual_Screen 0xfed2 #define XKB_KEY_Last_Virtual_Screen 0xfed4 #define XKB_KEY_Terminate_Server 0xfed5 #define XKB_KEY_AccessX_Enable 0xfe70 #define XKB_KEY_AccessX_Feedback_Enable 0xfe71 #define XKB_KEY_RepeatKeys_Enable 0xfe72 #define XKB_KEY_SlowKeys_Enable 0xfe73 #define XKB_KEY_BounceKeys_Enable 0xfe74 #define XKB_KEY_StickyKeys_Enable 0xfe75 #define XKB_KEY_MouseKeys_Enable 0xfe76 #define XKB_KEY_MouseKeys_Accel_Enable 0xfe77 #define XKB_KEY_Overlay1_Enable 0xfe78 #define XKB_KEY_Overlay2_Enable 0xfe79 #define XKB_KEY_AudibleBell_Enable 0xfe7a #define XKB_KEY_Pointer_Left 0xfee0 #define XKB_KEY_Pointer_Right 0xfee1 #define XKB_KEY_Pointer_Up 0xfee2 #define XKB_KEY_Pointer_Down 0xfee3 #define XKB_KEY_Pointer_UpLeft 0xfee4 #define XKB_KEY_Pointer_UpRight 0xfee5 #define XKB_KEY_Pointer_DownLeft 0xfee6 #define XKB_KEY_Pointer_DownRight 0xfee7 #define XKB_KEY_Pointer_Button_Dflt 0xfee8 #define XKB_KEY_Pointer_Button1 0xfee9 #define XKB_KEY_Pointer_Button2 0xfeea #define XKB_KEY_Pointer_Button3 0xfeeb #define XKB_KEY_Pointer_Button4 0xfeec #define XKB_KEY_Pointer_Button5 0xfeed #define XKB_KEY_Pointer_DblClick_Dflt 0xfeee #define XKB_KEY_Pointer_DblClick1 0xfeef #define XKB_KEY_Pointer_DblClick2 0xfef0 #define XKB_KEY_Pointer_DblClick3 0xfef1 #define XKB_KEY_Pointer_DblClick4 0xfef2 #define XKB_KEY_Pointer_DblClick5 0xfef3 #define XKB_KEY_Pointer_Drag_Dflt 0xfef4 #define XKB_KEY_Pointer_Drag1 0xfef5 #define XKB_KEY_Pointer_Drag2 0xfef6 #define XKB_KEY_Pointer_Drag3 0xfef7 #define XKB_KEY_Pointer_Drag4 0xfef8 #define XKB_KEY_Pointer_Drag5 0xfefd #define XKB_KEY_Pointer_EnableKeys 0xfef9 #define XKB_KEY_Pointer_Accelerate 0xfefa #define XKB_KEY_Pointer_DfltBtnNext 0xfefb #define XKB_KEY_Pointer_DfltBtnPrev 0xfefc /* Single-Stroke Multiple-Character N-Graph Keysyms For The X Input Method */ #define XKB_KEY_ch 0xfea0 #define XKB_KEY_Ch 0xfea1 #define XKB_KEY_CH 0xfea2 #define XKB_KEY_c_h 0xfea3 #define XKB_KEY_C_h 0xfea4 #define XKB_KEY_C_H 0xfea5 /* * 3270 Terminal Keys * Byte 3 = 0xfd */ #define XKB_KEY_3270_Duplicate 0xfd01 #define XKB_KEY_3270_FieldMark 0xfd02 #define XKB_KEY_3270_Right2 0xfd03 #define XKB_KEY_3270_Left2 0xfd04 #define XKB_KEY_3270_BackTab 0xfd05 #define XKB_KEY_3270_EraseEOF 0xfd06 #define XKB_KEY_3270_EraseInput 0xfd07 #define XKB_KEY_3270_Reset 0xfd08 #define XKB_KEY_3270_Quit 0xfd09 #define XKB_KEY_3270_PA1 0xfd0a #define XKB_KEY_3270_PA2 0xfd0b #define XKB_KEY_3270_PA3 0xfd0c #define XKB_KEY_3270_Test 0xfd0d #define XKB_KEY_3270_Attn 0xfd0e #define XKB_KEY_3270_CursorBlink 0xfd0f #define XKB_KEY_3270_AltCursor 0xfd10 #define XKB_KEY_3270_KeyClick 0xfd11 #define XKB_KEY_3270_Jump 0xfd12 #define XKB_KEY_3270_Ident 0xfd13 #define XKB_KEY_3270_Rule 0xfd14 #define XKB_KEY_3270_Copy 0xfd15 #define XKB_KEY_3270_Play 0xfd16 #define XKB_KEY_3270_Setup 0xfd17 #define XKB_KEY_3270_Record 0xfd18 #define XKB_KEY_3270_ChangeScreen 0xfd19 #define XKB_KEY_3270_DeleteWord 0xfd1a #define XKB_KEY_3270_ExSelect 0xfd1b #define XKB_KEY_3270_CursorSelect 0xfd1c #define XKB_KEY_3270_PrintScreen 0xfd1d #define XKB_KEY_3270_Enter 0xfd1e /* * Latin 1 * (ISO/IEC 8859-1 = Unicode U+0020..U+00FF) * Byte 3 = 0 */ #define XKB_KEY_space 0x0020 /* U+0020 SPACE */ #define XKB_KEY_exclam 0x0021 /* U+0021 EXCLAMATION MARK */ #define XKB_KEY_quotedbl 0x0022 /* U+0022 QUOTATION MARK */ #define XKB_KEY_numbersign 0x0023 /* U+0023 NUMBER SIGN */ #define XKB_KEY_dollar 0x0024 /* U+0024 DOLLAR SIGN */ #define XKB_KEY_percent 0x0025 /* U+0025 PERCENT SIGN */ #define XKB_KEY_ampersand 0x0026 /* U+0026 AMPERSAND */ #define XKB_KEY_apostrophe 0x0027 /* U+0027 APOSTROPHE */ #define XKB_KEY_quoteright 0x0027 /* deprecated */ #define XKB_KEY_parenleft 0x0028 /* U+0028 LEFT PARENTHESIS */ #define XKB_KEY_parenright 0x0029 /* U+0029 RIGHT PARENTHESIS */ #define XKB_KEY_asterisk 0x002a /* U+002A ASTERISK */ #define XKB_KEY_plus 0x002b /* U+002B PLUS SIGN */ #define XKB_KEY_comma 0x002c /* U+002C COMMA */ #define XKB_KEY_minus 0x002d /* U+002D HYPHEN-MINUS */ #define XKB_KEY_period 0x002e /* U+002E FULL STOP */ #define XKB_KEY_slash 0x002f /* U+002F SOLIDUS */ #define XKB_KEY_0 0x0030 /* U+0030 DIGIT ZERO */ #define XKB_KEY_1 0x0031 /* U+0031 DIGIT ONE */ #define XKB_KEY_2 0x0032 /* U+0032 DIGIT TWO */ #define XKB_KEY_3 0x0033 /* U+0033 DIGIT THREE */ #define XKB_KEY_4 0x0034 /* U+0034 DIGIT FOUR */ #define XKB_KEY_5 0x0035 /* U+0035 DIGIT FIVE */ #define XKB_KEY_6 0x0036 /* U+0036 DIGIT SIX */ #define XKB_KEY_7 0x0037 /* U+0037 DIGIT SEVEN */ #define XKB_KEY_8 0x0038 /* U+0038 DIGIT EIGHT */ #define XKB_KEY_9 0x0039 /* U+0039 DIGIT NINE */ #define XKB_KEY_colon 0x003a /* U+003A COLON */ #define XKB_KEY_semicolon 0x003b /* U+003B SEMICOLON */ #define XKB_KEY_less 0x003c /* U+003C LESS-THAN SIGN */ #define XKB_KEY_equal 0x003d /* U+003D EQUALS SIGN */ #define XKB_KEY_greater 0x003e /* U+003E GREATER-THAN SIGN */ #define XKB_KEY_question 0x003f /* U+003F QUESTION MARK */ #define XKB_KEY_at 0x0040 /* U+0040 COMMERCIAL AT */ #define XKB_KEY_A 0x0041 /* U+0041 LATIN CAPITAL LETTER A */ #define XKB_KEY_B 0x0042 /* U+0042 LATIN CAPITAL LETTER B */ #define XKB_KEY_C 0x0043 /* U+0043 LATIN CAPITAL LETTER C */ #define XKB_KEY_D 0x0044 /* U+0044 LATIN CAPITAL LETTER D */ #define XKB_KEY_E 0x0045 /* U+0045 LATIN CAPITAL LETTER E */ #define XKB_KEY_F 0x0046 /* U+0046 LATIN CAPITAL LETTER F */ #define XKB_KEY_G 0x0047 /* U+0047 LATIN CAPITAL LETTER G */ #define XKB_KEY_H 0x0048 /* U+0048 LATIN CAPITAL LETTER H */ #define XKB_KEY_I 0x0049 /* U+0049 LATIN CAPITAL LETTER I */ #define XKB_KEY_J 0x004a /* U+004A LATIN CAPITAL LETTER J */ #define XKB_KEY_K 0x004b /* U+004B LATIN CAPITAL LETTER K */ #define XKB_KEY_L 0x004c /* U+004C LATIN CAPITAL LETTER L */ #define XKB_KEY_M 0x004d /* U+004D LATIN CAPITAL LETTER M */ #define XKB_KEY_N 0x004e /* U+004E LATIN CAPITAL LETTER N */ #define XKB_KEY_O 0x004f /* U+004F LATIN CAPITAL LETTER O */ #define XKB_KEY_P 0x0050 /* U+0050 LATIN CAPITAL LETTER P */ #define XKB_KEY_Q 0x0051 /* U+0051 LATIN CAPITAL LETTER Q */ #define XKB_KEY_R 0x0052 /* U+0052 LATIN CAPITAL LETTER R */ #define XKB_KEY_S 0x0053 /* U+0053 LATIN CAPITAL LETTER S */ #define XKB_KEY_T 0x0054 /* U+0054 LATIN CAPITAL LETTER T */ #define XKB_KEY_U 0x0055 /* U+0055 LATIN CAPITAL LETTER U */ #define XKB_KEY_V 0x0056 /* U+0056 LATIN CAPITAL LETTER V */ #define XKB_KEY_W 0x0057 /* U+0057 LATIN CAPITAL LETTER W */ #define XKB_KEY_X 0x0058 /* U+0058 LATIN CAPITAL LETTER X */ #define XKB_KEY_Y 0x0059 /* U+0059 LATIN CAPITAL LETTER Y */ #define XKB_KEY_Z 0x005a /* U+005A LATIN CAPITAL LETTER Z */ #define XKB_KEY_bracketleft 0x005b /* U+005B LEFT SQUARE BRACKET */ #define XKB_KEY_backslash 0x005c /* U+005C REVERSE SOLIDUS */ #define XKB_KEY_bracketright 0x005d /* U+005D RIGHT SQUARE BRACKET */ #define XKB_KEY_asciicircum 0x005e /* U+005E CIRCUMFLEX ACCENT */ #define XKB_KEY_underscore 0x005f /* U+005F LOW LINE */ #define XKB_KEY_grave 0x0060 /* U+0060 GRAVE ACCENT */ #define XKB_KEY_quoteleft 0x0060 /* deprecated */ #define XKB_KEY_a 0x0061 /* U+0061 LATIN SMALL LETTER A */ #define XKB_KEY_b 0x0062 /* U+0062 LATIN SMALL LETTER B */ #define XKB_KEY_c 0x0063 /* U+0063 LATIN SMALL LETTER C */ #define XKB_KEY_d 0x0064 /* U+0064 LATIN SMALL LETTER D */ #define XKB_KEY_e 0x0065 /* U+0065 LATIN SMALL LETTER E */ #define XKB_KEY_f 0x0066 /* U+0066 LATIN SMALL LETTER F */ #define XKB_KEY_g 0x0067 /* U+0067 LATIN SMALL LETTER G */ #define XKB_KEY_h 0x0068 /* U+0068 LATIN SMALL LETTER H */ #define XKB_KEY_i 0x0069 /* U+0069 LATIN SMALL LETTER I */ #define XKB_KEY_j 0x006a /* U+006A LATIN SMALL LETTER J */ #define XKB_KEY_k 0x006b /* U+006B LATIN SMALL LETTER K */ #define XKB_KEY_l 0x006c /* U+006C LATIN SMALL LETTER L */ #define XKB_KEY_m 0x006d /* U+006D LATIN SMALL LETTER M */ #define XKB_KEY_n 0x006e /* U+006E LATIN SMALL LETTER N */ #define XKB_KEY_o 0x006f /* U+006F LATIN SMALL LETTER O */ #define XKB_KEY_p 0x0070 /* U+0070 LATIN SMALL LETTER P */ #define XKB_KEY_q 0x0071 /* U+0071 LATIN SMALL LETTER Q */ #define XKB_KEY_r 0x0072 /* U+0072 LATIN SMALL LETTER R */ #define XKB_KEY_s 0x0073 /* U+0073 LATIN SMALL LETTER S */ #define XKB_KEY_t 0x0074 /* U+0074 LATIN SMALL LETTER T */ #define XKB_KEY_u 0x0075 /* U+0075 LATIN SMALL LETTER U */ #define XKB_KEY_v 0x0076 /* U+0076 LATIN SMALL LETTER V */ #define XKB_KEY_w 0x0077 /* U+0077 LATIN SMALL LETTER W */ #define XKB_KEY_x 0x0078 /* U+0078 LATIN SMALL LETTER X */ #define XKB_KEY_y 0x0079 /* U+0079 LATIN SMALL LETTER Y */ #define XKB_KEY_z 0x007a /* U+007A LATIN SMALL LETTER Z */ #define XKB_KEY_braceleft 0x007b /* U+007B LEFT CURLY BRACKET */ #define XKB_KEY_bar 0x007c /* U+007C VERTICAL LINE */ #define XKB_KEY_braceright 0x007d /* U+007D RIGHT CURLY BRACKET */ #define XKB_KEY_asciitilde 0x007e /* U+007E TILDE */ #define XKB_KEY_nobreakspace 0x00a0 /* U+00A0 NO-BREAK SPACE */ #define XKB_KEY_exclamdown 0x00a1 /* U+00A1 INVERTED EXCLAMATION MARK */ #define XKB_KEY_cent 0x00a2 /* U+00A2 CENT SIGN */ #define XKB_KEY_sterling 0x00a3 /* U+00A3 POUND SIGN */ #define XKB_KEY_currency 0x00a4 /* U+00A4 CURRENCY SIGN */ #define XKB_KEY_yen 0x00a5 /* U+00A5 YEN SIGN */ #define XKB_KEY_brokenbar 0x00a6 /* U+00A6 BROKEN BAR */ #define XKB_KEY_section 0x00a7 /* U+00A7 SECTION SIGN */ #define XKB_KEY_diaeresis 0x00a8 /* U+00A8 DIAERESIS */ #define XKB_KEY_copyright 0x00a9 /* U+00A9 COPYRIGHT SIGN */ #define XKB_KEY_ordfeminine 0x00aa /* U+00AA FEMININE ORDINAL INDICATOR */ #define XKB_KEY_guillemotleft 0x00ab /* deprecated alias for guillemetleft (misspelling) */ #define XKB_KEY_guillemetleft 0x00ab /* U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */ #define XKB_KEY_notsign 0x00ac /* U+00AC NOT SIGN */ #define XKB_KEY_hyphen 0x00ad /* U+00AD SOFT HYPHEN */ #define XKB_KEY_registered 0x00ae /* U+00AE REGISTERED SIGN */ #define XKB_KEY_macron 0x00af /* U+00AF MACRON */ #define XKB_KEY_degree 0x00b0 /* U+00B0 DEGREE SIGN */ #define XKB_KEY_plusminus 0x00b1 /* U+00B1 PLUS-MINUS SIGN */ #define XKB_KEY_twosuperior 0x00b2 /* U+00B2 SUPERSCRIPT TWO */ #define XKB_KEY_threesuperior 0x00b3 /* U+00B3 SUPERSCRIPT THREE */ #define XKB_KEY_acute 0x00b4 /* U+00B4 ACUTE ACCENT */ #define XKB_KEY_mu 0x00b5 /* U+00B5 MICRO SIGN */ #define XKB_KEY_paragraph 0x00b6 /* U+00B6 PILCROW SIGN */ #define XKB_KEY_periodcentered 0x00b7 /* U+00B7 MIDDLE DOT */ #define XKB_KEY_cedilla 0x00b8 /* U+00B8 CEDILLA */ #define XKB_KEY_onesuperior 0x00b9 /* U+00B9 SUPERSCRIPT ONE */ #define XKB_KEY_masculine 0x00ba /* deprecated alias for ordmasculine (inconsistent name) */ #define XKB_KEY_ordmasculine 0x00ba /* U+00BA MASCULINE ORDINAL INDICATOR */ #define XKB_KEY_guillemotright 0x00bb /* deprecated alias for guillemetright (misspelling) */ #define XKB_KEY_guillemetright 0x00bb /* U+00BB RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */ #define XKB_KEY_onequarter 0x00bc /* U+00BC VULGAR FRACTION ONE QUARTER */ #define XKB_KEY_onehalf 0x00bd /* U+00BD VULGAR FRACTION ONE HALF */ #define XKB_KEY_threequarters 0x00be /* U+00BE VULGAR FRACTION THREE QUARTERS */ #define XKB_KEY_questiondown 0x00bf /* U+00BF INVERTED QUESTION MARK */ #define XKB_KEY_Agrave 0x00c0 /* U+00C0 LATIN CAPITAL LETTER A WITH GRAVE */ #define XKB_KEY_Aacute 0x00c1 /* U+00C1 LATIN CAPITAL LETTER A WITH ACUTE */ #define XKB_KEY_Acircumflex 0x00c2 /* U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ #define XKB_KEY_Atilde 0x00c3 /* U+00C3 LATIN CAPITAL LETTER A WITH TILDE */ #define XKB_KEY_Adiaeresis 0x00c4 /* U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS */ #define XKB_KEY_Aring 0x00c5 /* U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE */ #define XKB_KEY_AE 0x00c6 /* U+00C6 LATIN CAPITAL LETTER AE */ #define XKB_KEY_Ccedilla 0x00c7 /* U+00C7 LATIN CAPITAL LETTER C WITH CEDILLA */ #define XKB_KEY_Egrave 0x00c8 /* U+00C8 LATIN CAPITAL LETTER E WITH GRAVE */ #define XKB_KEY_Eacute 0x00c9 /* U+00C9 LATIN CAPITAL LETTER E WITH ACUTE */ #define XKB_KEY_Ecircumflex 0x00ca /* U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ #define XKB_KEY_Ediaeresis 0x00cb /* U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS */ #define XKB_KEY_Igrave 0x00cc /* U+00CC LATIN CAPITAL LETTER I WITH GRAVE */ #define XKB_KEY_Iacute 0x00cd /* U+00CD LATIN CAPITAL LETTER I WITH ACUTE */ #define XKB_KEY_Icircumflex 0x00ce /* U+00CE LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ #define XKB_KEY_Idiaeresis 0x00cf /* U+00CF LATIN CAPITAL LETTER I WITH DIAERESIS */ #define XKB_KEY_ETH 0x00d0 /* U+00D0 LATIN CAPITAL LETTER ETH */ #define XKB_KEY_Eth 0x00d0 /* deprecated */ #define XKB_KEY_Ntilde 0x00d1 /* U+00D1 LATIN CAPITAL LETTER N WITH TILDE */ #define XKB_KEY_Ograve 0x00d2 /* U+00D2 LATIN CAPITAL LETTER O WITH GRAVE */ #define XKB_KEY_Oacute 0x00d3 /* U+00D3 LATIN CAPITAL LETTER O WITH ACUTE */ #define XKB_KEY_Ocircumflex 0x00d4 /* U+00D4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ #define XKB_KEY_Otilde 0x00d5 /* U+00D5 LATIN CAPITAL LETTER O WITH TILDE */ #define XKB_KEY_Odiaeresis 0x00d6 /* U+00D6 LATIN CAPITAL LETTER O WITH DIAERESIS */ #define XKB_KEY_multiply 0x00d7 /* U+00D7 MULTIPLICATION SIGN */ #define XKB_KEY_Oslash 0x00d8 /* U+00D8 LATIN CAPITAL LETTER O WITH STROKE */ #define XKB_KEY_Ooblique 0x00d8 /* deprecated alias for Oslash */ #define XKB_KEY_Ugrave 0x00d9 /* U+00D9 LATIN CAPITAL LETTER U WITH GRAVE */ #define XKB_KEY_Uacute 0x00da /* U+00DA LATIN CAPITAL LETTER U WITH ACUTE */ #define XKB_KEY_Ucircumflex 0x00db /* U+00DB LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ #define XKB_KEY_Udiaeresis 0x00dc /* U+00DC LATIN CAPITAL LETTER U WITH DIAERESIS */ #define XKB_KEY_Yacute 0x00dd /* U+00DD LATIN CAPITAL LETTER Y WITH ACUTE */ #define XKB_KEY_THORN 0x00de /* U+00DE LATIN CAPITAL LETTER THORN */ #define XKB_KEY_Thorn 0x00de /* deprecated */ #define XKB_KEY_ssharp 0x00df /* U+00DF LATIN SMALL LETTER SHARP S */ #define XKB_KEY_agrave 0x00e0 /* U+00E0 LATIN SMALL LETTER A WITH GRAVE */ #define XKB_KEY_aacute 0x00e1 /* U+00E1 LATIN SMALL LETTER A WITH ACUTE */ #define XKB_KEY_acircumflex 0x00e2 /* U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX */ #define XKB_KEY_atilde 0x00e3 /* U+00E3 LATIN SMALL LETTER A WITH TILDE */ #define XKB_KEY_adiaeresis 0x00e4 /* U+00E4 LATIN SMALL LETTER A WITH DIAERESIS */ #define XKB_KEY_aring 0x00e5 /* U+00E5 LATIN SMALL LETTER A WITH RING ABOVE */ #define XKB_KEY_ae 0x00e6 /* U+00E6 LATIN SMALL LETTER AE */ #define XKB_KEY_ccedilla 0x00e7 /* U+00E7 LATIN SMALL LETTER C WITH CEDILLA */ #define XKB_KEY_egrave 0x00e8 /* U+00E8 LATIN SMALL LETTER E WITH GRAVE */ #define XKB_KEY_eacute 0x00e9 /* U+00E9 LATIN SMALL LETTER E WITH ACUTE */ #define XKB_KEY_ecircumflex 0x00ea /* U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX */ #define XKB_KEY_ediaeresis 0x00eb /* U+00EB LATIN SMALL LETTER E WITH DIAERESIS */ #define XKB_KEY_igrave 0x00ec /* U+00EC LATIN SMALL LETTER I WITH GRAVE */ #define XKB_KEY_iacute 0x00ed /* U+00ED LATIN SMALL LETTER I WITH ACUTE */ #define XKB_KEY_icircumflex 0x00ee /* U+00EE LATIN SMALL LETTER I WITH CIRCUMFLEX */ #define XKB_KEY_idiaeresis 0x00ef /* U+00EF LATIN SMALL LETTER I WITH DIAERESIS */ #define XKB_KEY_eth 0x00f0 /* U+00F0 LATIN SMALL LETTER ETH */ #define XKB_KEY_ntilde 0x00f1 /* U+00F1 LATIN SMALL LETTER N WITH TILDE */ #define XKB_KEY_ograve 0x00f2 /* U+00F2 LATIN SMALL LETTER O WITH GRAVE */ #define XKB_KEY_oacute 0x00f3 /* U+00F3 LATIN SMALL LETTER O WITH ACUTE */ #define XKB_KEY_ocircumflex 0x00f4 /* U+00F4 LATIN SMALL LETTER O WITH CIRCUMFLEX */ #define XKB_KEY_otilde 0x00f5 /* U+00F5 LATIN SMALL LETTER O WITH TILDE */ #define XKB_KEY_odiaeresis 0x00f6 /* U+00F6 LATIN SMALL LETTER O WITH DIAERESIS */ #define XKB_KEY_division 0x00f7 /* U+00F7 DIVISION SIGN */ #define XKB_KEY_oslash 0x00f8 /* U+00F8 LATIN SMALL LETTER O WITH STROKE */ #define XKB_KEY_ooblique 0x00f8 /* deprecated alias for oslash */ #define XKB_KEY_ugrave 0x00f9 /* U+00F9 LATIN SMALL LETTER U WITH GRAVE */ #define XKB_KEY_uacute 0x00fa /* U+00FA LATIN SMALL LETTER U WITH ACUTE */ #define XKB_KEY_ucircumflex 0x00fb /* U+00FB LATIN SMALL LETTER U WITH CIRCUMFLEX */ #define XKB_KEY_udiaeresis 0x00fc /* U+00FC LATIN SMALL LETTER U WITH DIAERESIS */ #define XKB_KEY_yacute 0x00fd /* U+00FD LATIN SMALL LETTER Y WITH ACUTE */ #define XKB_KEY_thorn 0x00fe /* U+00FE LATIN SMALL LETTER THORN */ #define XKB_KEY_ydiaeresis 0x00ff /* U+00FF LATIN SMALL LETTER Y WITH DIAERESIS */ /* * Latin 2 * Byte 3 = 1 */ #define XKB_KEY_Aogonek 0x01a1 /* U+0104 LATIN CAPITAL LETTER A WITH OGONEK */ #define XKB_KEY_breve 0x01a2 /* U+02D8 BREVE */ #define XKB_KEY_Lstroke 0x01a3 /* U+0141 LATIN CAPITAL LETTER L WITH STROKE */ #define XKB_KEY_Lcaron 0x01a5 /* U+013D LATIN CAPITAL LETTER L WITH CARON */ #define XKB_KEY_Sacute 0x01a6 /* U+015A LATIN CAPITAL LETTER S WITH ACUTE */ #define XKB_KEY_Scaron 0x01a9 /* U+0160 LATIN CAPITAL LETTER S WITH CARON */ #define XKB_KEY_Scedilla 0x01aa /* U+015E LATIN CAPITAL LETTER S WITH CEDILLA */ #define XKB_KEY_Tcaron 0x01ab /* U+0164 LATIN CAPITAL LETTER T WITH CARON */ #define XKB_KEY_Zacute 0x01ac /* U+0179 LATIN CAPITAL LETTER Z WITH ACUTE */ #define XKB_KEY_Zcaron 0x01ae /* U+017D LATIN CAPITAL LETTER Z WITH CARON */ #define XKB_KEY_Zabovedot 0x01af /* U+017B LATIN CAPITAL LETTER Z WITH DOT ABOVE */ #define XKB_KEY_aogonek 0x01b1 /* U+0105 LATIN SMALL LETTER A WITH OGONEK */ #define XKB_KEY_ogonek 0x01b2 /* U+02DB OGONEK */ #define XKB_KEY_lstroke 0x01b3 /* U+0142 LATIN SMALL LETTER L WITH STROKE */ #define XKB_KEY_lcaron 0x01b5 /* U+013E LATIN SMALL LETTER L WITH CARON */ #define XKB_KEY_sacute 0x01b6 /* U+015B LATIN SMALL LETTER S WITH ACUTE */ #define XKB_KEY_caron 0x01b7 /* U+02C7 CARON */ #define XKB_KEY_scaron 0x01b9 /* U+0161 LATIN SMALL LETTER S WITH CARON */ #define XKB_KEY_scedilla 0x01ba /* U+015F LATIN SMALL LETTER S WITH CEDILLA */ #define XKB_KEY_tcaron 0x01bb /* U+0165 LATIN SMALL LETTER T WITH CARON */ #define XKB_KEY_zacute 0x01bc /* U+017A LATIN SMALL LETTER Z WITH ACUTE */ #define XKB_KEY_doubleacute 0x01bd /* U+02DD DOUBLE ACUTE ACCENT */ #define XKB_KEY_zcaron 0x01be /* U+017E LATIN SMALL LETTER Z WITH CARON */ #define XKB_KEY_zabovedot 0x01bf /* U+017C LATIN SMALL LETTER Z WITH DOT ABOVE */ #define XKB_KEY_Racute 0x01c0 /* U+0154 LATIN CAPITAL LETTER R WITH ACUTE */ #define XKB_KEY_Abreve 0x01c3 /* U+0102 LATIN CAPITAL LETTER A WITH BREVE */ #define XKB_KEY_Lacute 0x01c5 /* U+0139 LATIN CAPITAL LETTER L WITH ACUTE */ #define XKB_KEY_Cacute 0x01c6 /* U+0106 LATIN CAPITAL LETTER C WITH ACUTE */ #define XKB_KEY_Ccaron 0x01c8 /* U+010C LATIN CAPITAL LETTER C WITH CARON */ #define XKB_KEY_Eogonek 0x01ca /* U+0118 LATIN CAPITAL LETTER E WITH OGONEK */ #define XKB_KEY_Ecaron 0x01cc /* U+011A LATIN CAPITAL LETTER E WITH CARON */ #define XKB_KEY_Dcaron 0x01cf /* U+010E LATIN CAPITAL LETTER D WITH CARON */ #define XKB_KEY_Dstroke 0x01d0 /* U+0110 LATIN CAPITAL LETTER D WITH STROKE */ #define XKB_KEY_Nacute 0x01d1 /* U+0143 LATIN CAPITAL LETTER N WITH ACUTE */ #define XKB_KEY_Ncaron 0x01d2 /* U+0147 LATIN CAPITAL LETTER N WITH CARON */ #define XKB_KEY_Odoubleacute 0x01d5 /* U+0150 LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ #define XKB_KEY_Rcaron 0x01d8 /* U+0158 LATIN CAPITAL LETTER R WITH CARON */ #define XKB_KEY_Uring 0x01d9 /* U+016E LATIN CAPITAL LETTER U WITH RING ABOVE */ #define XKB_KEY_Udoubleacute 0x01db /* U+0170 LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ #define XKB_KEY_Tcedilla 0x01de /* U+0162 LATIN CAPITAL LETTER T WITH CEDILLA */ #define XKB_KEY_racute 0x01e0 /* U+0155 LATIN SMALL LETTER R WITH ACUTE */ #define XKB_KEY_abreve 0x01e3 /* U+0103 LATIN SMALL LETTER A WITH BREVE */ #define XKB_KEY_lacute 0x01e5 /* U+013A LATIN SMALL LETTER L WITH ACUTE */ #define XKB_KEY_cacute 0x01e6 /* U+0107 LATIN SMALL LETTER C WITH ACUTE */ #define XKB_KEY_ccaron 0x01e8 /* U+010D LATIN SMALL LETTER C WITH CARON */ #define XKB_KEY_eogonek 0x01ea /* U+0119 LATIN SMALL LETTER E WITH OGONEK */ #define XKB_KEY_ecaron 0x01ec /* U+011B LATIN SMALL LETTER E WITH CARON */ #define XKB_KEY_dcaron 0x01ef /* U+010F LATIN SMALL LETTER D WITH CARON */ #define XKB_KEY_dstroke 0x01f0 /* U+0111 LATIN SMALL LETTER D WITH STROKE */ #define XKB_KEY_nacute 0x01f1 /* U+0144 LATIN SMALL LETTER N WITH ACUTE */ #define XKB_KEY_ncaron 0x01f2 /* U+0148 LATIN SMALL LETTER N WITH CARON */ #define XKB_KEY_odoubleacute 0x01f5 /* U+0151 LATIN SMALL LETTER O WITH DOUBLE ACUTE */ #define XKB_KEY_rcaron 0x01f8 /* U+0159 LATIN SMALL LETTER R WITH CARON */ #define XKB_KEY_uring 0x01f9 /* U+016F LATIN SMALL LETTER U WITH RING ABOVE */ #define XKB_KEY_udoubleacute 0x01fb /* U+0171 LATIN SMALL LETTER U WITH DOUBLE ACUTE */ #define XKB_KEY_tcedilla 0x01fe /* U+0163 LATIN SMALL LETTER T WITH CEDILLA */ #define XKB_KEY_abovedot 0x01ff /* U+02D9 DOT ABOVE */ /* * Latin 3 * Byte 3 = 2 */ #define XKB_KEY_Hstroke 0x02a1 /* U+0126 LATIN CAPITAL LETTER H WITH STROKE */ #define XKB_KEY_Hcircumflex 0x02a6 /* U+0124 LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ #define XKB_KEY_Iabovedot 0x02a9 /* U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE */ #define XKB_KEY_Gbreve 0x02ab /* U+011E LATIN CAPITAL LETTER G WITH BREVE */ #define XKB_KEY_Jcircumflex 0x02ac /* U+0134 LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ #define XKB_KEY_hstroke 0x02b1 /* U+0127 LATIN SMALL LETTER H WITH STROKE */ #define XKB_KEY_hcircumflex 0x02b6 /* U+0125 LATIN SMALL LETTER H WITH CIRCUMFLEX */ #define XKB_KEY_idotless 0x02b9 /* U+0131 LATIN SMALL LETTER DOTLESS I */ #define XKB_KEY_gbreve 0x02bb /* U+011F LATIN SMALL LETTER G WITH BREVE */ #define XKB_KEY_jcircumflex 0x02bc /* U+0135 LATIN SMALL LETTER J WITH CIRCUMFLEX */ #define XKB_KEY_Cabovedot 0x02c5 /* U+010A LATIN CAPITAL LETTER C WITH DOT ABOVE */ #define XKB_KEY_Ccircumflex 0x02c6 /* U+0108 LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ #define XKB_KEY_Gabovedot 0x02d5 /* U+0120 LATIN CAPITAL LETTER G WITH DOT ABOVE */ #define XKB_KEY_Gcircumflex 0x02d8 /* U+011C LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ #define XKB_KEY_Ubreve 0x02dd /* U+016C LATIN CAPITAL LETTER U WITH BREVE */ #define XKB_KEY_Scircumflex 0x02de /* U+015C LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ #define XKB_KEY_cabovedot 0x02e5 /* U+010B LATIN SMALL LETTER C WITH DOT ABOVE */ #define XKB_KEY_ccircumflex 0x02e6 /* U+0109 LATIN SMALL LETTER C WITH CIRCUMFLEX */ #define XKB_KEY_gabovedot 0x02f5 /* U+0121 LATIN SMALL LETTER G WITH DOT ABOVE */ #define XKB_KEY_gcircumflex 0x02f8 /* U+011D LATIN SMALL LETTER G WITH CIRCUMFLEX */ #define XKB_KEY_ubreve 0x02fd /* U+016D LATIN SMALL LETTER U WITH BREVE */ #define XKB_KEY_scircumflex 0x02fe /* U+015D LATIN SMALL LETTER S WITH CIRCUMFLEX */ /* * Latin 4 * Byte 3 = 3 */ #define XKB_KEY_kra 0x03a2 /* U+0138 LATIN SMALL LETTER KRA */ #define XKB_KEY_kappa 0x03a2 /* deprecated */ #define XKB_KEY_Rcedilla 0x03a3 /* U+0156 LATIN CAPITAL LETTER R WITH CEDILLA */ #define XKB_KEY_Itilde 0x03a5 /* U+0128 LATIN CAPITAL LETTER I WITH TILDE */ #define XKB_KEY_Lcedilla 0x03a6 /* U+013B LATIN CAPITAL LETTER L WITH CEDILLA */ #define XKB_KEY_Emacron 0x03aa /* U+0112 LATIN CAPITAL LETTER E WITH MACRON */ #define XKB_KEY_Gcedilla 0x03ab /* U+0122 LATIN CAPITAL LETTER G WITH CEDILLA */ #define XKB_KEY_Tslash 0x03ac /* U+0166 LATIN CAPITAL LETTER T WITH STROKE */ #define XKB_KEY_rcedilla 0x03b3 /* U+0157 LATIN SMALL LETTER R WITH CEDILLA */ #define XKB_KEY_itilde 0x03b5 /* U+0129 LATIN SMALL LETTER I WITH TILDE */ #define XKB_KEY_lcedilla 0x03b6 /* U+013C LATIN SMALL LETTER L WITH CEDILLA */ #define XKB_KEY_emacron 0x03ba /* U+0113 LATIN SMALL LETTER E WITH MACRON */ #define XKB_KEY_gcedilla 0x03bb /* U+0123 LATIN SMALL LETTER G WITH CEDILLA */ #define XKB_KEY_tslash 0x03bc /* U+0167 LATIN SMALL LETTER T WITH STROKE */ #define XKB_KEY_ENG 0x03bd /* U+014A LATIN CAPITAL LETTER ENG */ #define XKB_KEY_eng 0x03bf /* U+014B LATIN SMALL LETTER ENG */ #define XKB_KEY_Amacron 0x03c0 /* U+0100 LATIN CAPITAL LETTER A WITH MACRON */ #define XKB_KEY_Iogonek 0x03c7 /* U+012E LATIN CAPITAL LETTER I WITH OGONEK */ #define XKB_KEY_Eabovedot 0x03cc /* U+0116 LATIN CAPITAL LETTER E WITH DOT ABOVE */ #define XKB_KEY_Imacron 0x03cf /* U+012A LATIN CAPITAL LETTER I WITH MACRON */ #define XKB_KEY_Ncedilla 0x03d1 /* U+0145 LATIN CAPITAL LETTER N WITH CEDILLA */ #define XKB_KEY_Omacron 0x03d2 /* U+014C LATIN CAPITAL LETTER O WITH MACRON */ #define XKB_KEY_Kcedilla 0x03d3 /* U+0136 LATIN CAPITAL LETTER K WITH CEDILLA */ #define XKB_KEY_Uogonek 0x03d9 /* U+0172 LATIN CAPITAL LETTER U WITH OGONEK */ #define XKB_KEY_Utilde 0x03dd /* U+0168 LATIN CAPITAL LETTER U WITH TILDE */ #define XKB_KEY_Umacron 0x03de /* U+016A LATIN CAPITAL LETTER U WITH MACRON */ #define XKB_KEY_amacron 0x03e0 /* U+0101 LATIN SMALL LETTER A WITH MACRON */ #define XKB_KEY_iogonek 0x03e7 /* U+012F LATIN SMALL LETTER I WITH OGONEK */ #define XKB_KEY_eabovedot 0x03ec /* U+0117 LATIN SMALL LETTER E WITH DOT ABOVE */ #define XKB_KEY_imacron 0x03ef /* U+012B LATIN SMALL LETTER I WITH MACRON */ #define XKB_KEY_ncedilla 0x03f1 /* U+0146 LATIN SMALL LETTER N WITH CEDILLA */ #define XKB_KEY_omacron 0x03f2 /* U+014D LATIN SMALL LETTER O WITH MACRON */ #define XKB_KEY_kcedilla 0x03f3 /* U+0137 LATIN SMALL LETTER K WITH CEDILLA */ #define XKB_KEY_uogonek 0x03f9 /* U+0173 LATIN SMALL LETTER U WITH OGONEK */ #define XKB_KEY_utilde 0x03fd /* U+0169 LATIN SMALL LETTER U WITH TILDE */ #define XKB_KEY_umacron 0x03fe /* U+016B LATIN SMALL LETTER U WITH MACRON */ /* * Latin 8 */ #define XKB_KEY_Wcircumflex 0x1000174 /* U+0174 LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ #define XKB_KEY_wcircumflex 0x1000175 /* U+0175 LATIN SMALL LETTER W WITH CIRCUMFLEX */ #define XKB_KEY_Ycircumflex 0x1000176 /* U+0176 LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ #define XKB_KEY_ycircumflex 0x1000177 /* U+0177 LATIN SMALL LETTER Y WITH CIRCUMFLEX */ #define XKB_KEY_Babovedot 0x1001e02 /* U+1E02 LATIN CAPITAL LETTER B WITH DOT ABOVE */ #define XKB_KEY_babovedot 0x1001e03 /* U+1E03 LATIN SMALL LETTER B WITH DOT ABOVE */ #define XKB_KEY_Dabovedot 0x1001e0a /* U+1E0A LATIN CAPITAL LETTER D WITH DOT ABOVE */ #define XKB_KEY_dabovedot 0x1001e0b /* U+1E0B LATIN SMALL LETTER D WITH DOT ABOVE */ #define XKB_KEY_Fabovedot 0x1001e1e /* U+1E1E LATIN CAPITAL LETTER F WITH DOT ABOVE */ #define XKB_KEY_fabovedot 0x1001e1f /* U+1E1F LATIN SMALL LETTER F WITH DOT ABOVE */ #define XKB_KEY_Mabovedot 0x1001e40 /* U+1E40 LATIN CAPITAL LETTER M WITH DOT ABOVE */ #define XKB_KEY_mabovedot 0x1001e41 /* U+1E41 LATIN SMALL LETTER M WITH DOT ABOVE */ #define XKB_KEY_Pabovedot 0x1001e56 /* U+1E56 LATIN CAPITAL LETTER P WITH DOT ABOVE */ #define XKB_KEY_pabovedot 0x1001e57 /* U+1E57 LATIN SMALL LETTER P WITH DOT ABOVE */ #define XKB_KEY_Sabovedot 0x1001e60 /* U+1E60 LATIN CAPITAL LETTER S WITH DOT ABOVE */ #define XKB_KEY_sabovedot 0x1001e61 /* U+1E61 LATIN SMALL LETTER S WITH DOT ABOVE */ #define XKB_KEY_Tabovedot 0x1001e6a /* U+1E6A LATIN CAPITAL LETTER T WITH DOT ABOVE */ #define XKB_KEY_tabovedot 0x1001e6b /* U+1E6B LATIN SMALL LETTER T WITH DOT ABOVE */ #define XKB_KEY_Wgrave 0x1001e80 /* U+1E80 LATIN CAPITAL LETTER W WITH GRAVE */ #define XKB_KEY_wgrave 0x1001e81 /* U+1E81 LATIN SMALL LETTER W WITH GRAVE */ #define XKB_KEY_Wacute 0x1001e82 /* U+1E82 LATIN CAPITAL LETTER W WITH ACUTE */ #define XKB_KEY_wacute 0x1001e83 /* U+1E83 LATIN SMALL LETTER W WITH ACUTE */ #define XKB_KEY_Wdiaeresis 0x1001e84 /* U+1E84 LATIN CAPITAL LETTER W WITH DIAERESIS */ #define XKB_KEY_wdiaeresis 0x1001e85 /* U+1E85 LATIN SMALL LETTER W WITH DIAERESIS */ #define XKB_KEY_Ygrave 0x1001ef2 /* U+1EF2 LATIN CAPITAL LETTER Y WITH GRAVE */ #define XKB_KEY_ygrave 0x1001ef3 /* U+1EF3 LATIN SMALL LETTER Y WITH GRAVE */ /* * Latin 9 * Byte 3 = 0x13 */ #define XKB_KEY_OE 0x13bc /* U+0152 LATIN CAPITAL LIGATURE OE */ #define XKB_KEY_oe 0x13bd /* U+0153 LATIN SMALL LIGATURE OE */ #define XKB_KEY_Ydiaeresis 0x13be /* U+0178 LATIN CAPITAL LETTER Y WITH DIAERESIS */ /* * Katakana * Byte 3 = 4 */ #define XKB_KEY_overline 0x047e /* U+203E OVERLINE */ #define XKB_KEY_kana_fullstop 0x04a1 /* U+3002 IDEOGRAPHIC FULL STOP */ #define XKB_KEY_kana_openingbracket 0x04a2 /* U+300C LEFT CORNER BRACKET */ #define XKB_KEY_kana_closingbracket 0x04a3 /* U+300D RIGHT CORNER BRACKET */ #define XKB_KEY_kana_comma 0x04a4 /* U+3001 IDEOGRAPHIC COMMA */ #define XKB_KEY_kana_conjunctive 0x04a5 /* U+30FB KATAKANA MIDDLE DOT */ #define XKB_KEY_kana_middledot 0x04a5 /* deprecated */ #define XKB_KEY_kana_WO 0x04a6 /* U+30F2 KATAKANA LETTER WO */ #define XKB_KEY_kana_a 0x04a7 /* U+30A1 KATAKANA LETTER SMALL A */ #define XKB_KEY_kana_i 0x04a8 /* U+30A3 KATAKANA LETTER SMALL I */ #define XKB_KEY_kana_u 0x04a9 /* U+30A5 KATAKANA LETTER SMALL U */ #define XKB_KEY_kana_e 0x04aa /* U+30A7 KATAKANA LETTER SMALL E */ #define XKB_KEY_kana_o 0x04ab /* U+30A9 KATAKANA LETTER SMALL O */ #define XKB_KEY_kana_ya 0x04ac /* U+30E3 KATAKANA LETTER SMALL YA */ #define XKB_KEY_kana_yu 0x04ad /* U+30E5 KATAKANA LETTER SMALL YU */ #define XKB_KEY_kana_yo 0x04ae /* U+30E7 KATAKANA LETTER SMALL YO */ #define XKB_KEY_kana_tsu 0x04af /* U+30C3 KATAKANA LETTER SMALL TU */ #define XKB_KEY_kana_tu 0x04af /* deprecated */ #define XKB_KEY_prolongedsound 0x04b0 /* U+30FC KATAKANA-HIRAGANA PROLONGED SOUND MARK */ #define XKB_KEY_kana_A 0x04b1 /* U+30A2 KATAKANA LETTER A */ #define XKB_KEY_kana_I 0x04b2 /* U+30A4 KATAKANA LETTER I */ #define XKB_KEY_kana_U 0x04b3 /* U+30A6 KATAKANA LETTER U */ #define XKB_KEY_kana_E 0x04b4 /* U+30A8 KATAKANA LETTER E */ #define XKB_KEY_kana_O 0x04b5 /* U+30AA KATAKANA LETTER O */ #define XKB_KEY_kana_KA 0x04b6 /* U+30AB KATAKANA LETTER KA */ #define XKB_KEY_kana_KI 0x04b7 /* U+30AD KATAKANA LETTER KI */ #define XKB_KEY_kana_KU 0x04b8 /* U+30AF KATAKANA LETTER KU */ #define XKB_KEY_kana_KE 0x04b9 /* U+30B1 KATAKANA LETTER KE */ #define XKB_KEY_kana_KO 0x04ba /* U+30B3 KATAKANA LETTER KO */ #define XKB_KEY_kana_SA 0x04bb /* U+30B5 KATAKANA LETTER SA */ #define XKB_KEY_kana_SHI 0x04bc /* U+30B7 KATAKANA LETTER SI */ #define XKB_KEY_kana_SU 0x04bd /* U+30B9 KATAKANA LETTER SU */ #define XKB_KEY_kana_SE 0x04be /* U+30BB KATAKANA LETTER SE */ #define XKB_KEY_kana_SO 0x04bf /* U+30BD KATAKANA LETTER SO */ #define XKB_KEY_kana_TA 0x04c0 /* U+30BF KATAKANA LETTER TA */ #define XKB_KEY_kana_CHI 0x04c1 /* U+30C1 KATAKANA LETTER TI */ #define XKB_KEY_kana_TI 0x04c1 /* deprecated */ #define XKB_KEY_kana_TSU 0x04c2 /* U+30C4 KATAKANA LETTER TU */ #define XKB_KEY_kana_TU 0x04c2 /* deprecated */ #define XKB_KEY_kana_TE 0x04c3 /* U+30C6 KATAKANA LETTER TE */ #define XKB_KEY_kana_TO 0x04c4 /* U+30C8 KATAKANA LETTER TO */ #define XKB_KEY_kana_NA 0x04c5 /* U+30CA KATAKANA LETTER NA */ #define XKB_KEY_kana_NI 0x04c6 /* U+30CB KATAKANA LETTER NI */ #define XKB_KEY_kana_NU 0x04c7 /* U+30CC KATAKANA LETTER NU */ #define XKB_KEY_kana_NE 0x04c8 /* U+30CD KATAKANA LETTER NE */ #define XKB_KEY_kana_NO 0x04c9 /* U+30CE KATAKANA LETTER NO */ #define XKB_KEY_kana_HA 0x04ca /* U+30CF KATAKANA LETTER HA */ #define XKB_KEY_kana_HI 0x04cb /* U+30D2 KATAKANA LETTER HI */ #define XKB_KEY_kana_FU 0x04cc /* U+30D5 KATAKANA LETTER HU */ #define XKB_KEY_kana_HU 0x04cc /* deprecated */ #define XKB_KEY_kana_HE 0x04cd /* U+30D8 KATAKANA LETTER HE */ #define XKB_KEY_kana_HO 0x04ce /* U+30DB KATAKANA LETTER HO */ #define XKB_KEY_kana_MA 0x04cf /* U+30DE KATAKANA LETTER MA */ #define XKB_KEY_kana_MI 0x04d0 /* U+30DF KATAKANA LETTER MI */ #define XKB_KEY_kana_MU 0x04d1 /* U+30E0 KATAKANA LETTER MU */ #define XKB_KEY_kana_ME 0x04d2 /* U+30E1 KATAKANA LETTER ME */ #define XKB_KEY_kana_MO 0x04d3 /* U+30E2 KATAKANA LETTER MO */ #define XKB_KEY_kana_YA 0x04d4 /* U+30E4 KATAKANA LETTER YA */ #define XKB_KEY_kana_YU 0x04d5 /* U+30E6 KATAKANA LETTER YU */ #define XKB_KEY_kana_YO 0x04d6 /* U+30E8 KATAKANA LETTER YO */ #define XKB_KEY_kana_RA 0x04d7 /* U+30E9 KATAKANA LETTER RA */ #define XKB_KEY_kana_RI 0x04d8 /* U+30EA KATAKANA LETTER RI */ #define XKB_KEY_kana_RU 0x04d9 /* U+30EB KATAKANA LETTER RU */ #define XKB_KEY_kana_RE 0x04da /* U+30EC KATAKANA LETTER RE */ #define XKB_KEY_kana_RO 0x04db /* U+30ED KATAKANA LETTER RO */ #define XKB_KEY_kana_WA 0x04dc /* U+30EF KATAKANA LETTER WA */ #define XKB_KEY_kana_N 0x04dd /* U+30F3 KATAKANA LETTER N */ #define XKB_KEY_voicedsound 0x04de /* U+309B KATAKANA-HIRAGANA VOICED SOUND MARK */ #define XKB_KEY_semivoicedsound 0x04df /* U+309C KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ #define XKB_KEY_kana_switch 0xff7e /* non-deprecated alias for Mode_switch */ /* * Arabic * Byte 3 = 5 */ #define XKB_KEY_Farsi_0 0x10006f0 /* U+06F0 EXTENDED ARABIC-INDIC DIGIT ZERO */ #define XKB_KEY_Farsi_1 0x10006f1 /* U+06F1 EXTENDED ARABIC-INDIC DIGIT ONE */ #define XKB_KEY_Farsi_2 0x10006f2 /* U+06F2 EXTENDED ARABIC-INDIC DIGIT TWO */ #define XKB_KEY_Farsi_3 0x10006f3 /* U+06F3 EXTENDED ARABIC-INDIC DIGIT THREE */ #define XKB_KEY_Farsi_4 0x10006f4 /* U+06F4 EXTENDED ARABIC-INDIC DIGIT FOUR */ #define XKB_KEY_Farsi_5 0x10006f5 /* U+06F5 EXTENDED ARABIC-INDIC DIGIT FIVE */ #define XKB_KEY_Farsi_6 0x10006f6 /* U+06F6 EXTENDED ARABIC-INDIC DIGIT SIX */ #define XKB_KEY_Farsi_7 0x10006f7 /* U+06F7 EXTENDED ARABIC-INDIC DIGIT SEVEN */ #define XKB_KEY_Farsi_8 0x10006f8 /* U+06F8 EXTENDED ARABIC-INDIC DIGIT EIGHT */ #define XKB_KEY_Farsi_9 0x10006f9 /* U+06F9 EXTENDED ARABIC-INDIC DIGIT NINE */ #define XKB_KEY_Arabic_percent 0x100066a /* U+066A ARABIC PERCENT SIGN */ #define XKB_KEY_Arabic_superscript_alef 0x1000670 /* U+0670 ARABIC LETTER SUPERSCRIPT ALEF */ #define XKB_KEY_Arabic_tteh 0x1000679 /* U+0679 ARABIC LETTER TTEH */ #define XKB_KEY_Arabic_peh 0x100067e /* U+067E ARABIC LETTER PEH */ #define XKB_KEY_Arabic_tcheh 0x1000686 /* U+0686 ARABIC LETTER TCHEH */ #define XKB_KEY_Arabic_ddal 0x1000688 /* U+0688 ARABIC LETTER DDAL */ #define XKB_KEY_Arabic_rreh 0x1000691 /* U+0691 ARABIC LETTER RREH */ #define XKB_KEY_Arabic_comma 0x05ac /* U+060C ARABIC COMMA */ #define XKB_KEY_Arabic_fullstop 0x10006d4 /* U+06D4 ARABIC FULL STOP */ #define XKB_KEY_Arabic_0 0x1000660 /* U+0660 ARABIC-INDIC DIGIT ZERO */ #define XKB_KEY_Arabic_1 0x1000661 /* U+0661 ARABIC-INDIC DIGIT ONE */ #define XKB_KEY_Arabic_2 0x1000662 /* U+0662 ARABIC-INDIC DIGIT TWO */ #define XKB_KEY_Arabic_3 0x1000663 /* U+0663 ARABIC-INDIC DIGIT THREE */ #define XKB_KEY_Arabic_4 0x1000664 /* U+0664 ARABIC-INDIC DIGIT FOUR */ #define XKB_KEY_Arabic_5 0x1000665 /* U+0665 ARABIC-INDIC DIGIT FIVE */ #define XKB_KEY_Arabic_6 0x1000666 /* U+0666 ARABIC-INDIC DIGIT SIX */ #define XKB_KEY_Arabic_7 0x1000667 /* U+0667 ARABIC-INDIC DIGIT SEVEN */ #define XKB_KEY_Arabic_8 0x1000668 /* U+0668 ARABIC-INDIC DIGIT EIGHT */ #define XKB_KEY_Arabic_9 0x1000669 /* U+0669 ARABIC-INDIC DIGIT NINE */ #define XKB_KEY_Arabic_semicolon 0x05bb /* U+061B ARABIC SEMICOLON */ #define XKB_KEY_Arabic_question_mark 0x05bf /* U+061F ARABIC QUESTION MARK */ #define XKB_KEY_Arabic_hamza 0x05c1 /* U+0621 ARABIC LETTER HAMZA */ #define XKB_KEY_Arabic_maddaonalef 0x05c2 /* U+0622 ARABIC LETTER ALEF WITH MADDA ABOVE */ #define XKB_KEY_Arabic_hamzaonalef 0x05c3 /* U+0623 ARABIC LETTER ALEF WITH HAMZA ABOVE */ #define XKB_KEY_Arabic_hamzaonwaw 0x05c4 /* U+0624 ARABIC LETTER WAW WITH HAMZA ABOVE */ #define XKB_KEY_Arabic_hamzaunderalef 0x05c5 /* U+0625 ARABIC LETTER ALEF WITH HAMZA BELOW */ #define XKB_KEY_Arabic_hamzaonyeh 0x05c6 /* U+0626 ARABIC LETTER YEH WITH HAMZA ABOVE */ #define XKB_KEY_Arabic_alef 0x05c7 /* U+0627 ARABIC LETTER ALEF */ #define XKB_KEY_Arabic_beh 0x05c8 /* U+0628 ARABIC LETTER BEH */ #define XKB_KEY_Arabic_tehmarbuta 0x05c9 /* U+0629 ARABIC LETTER TEH MARBUTA */ #define XKB_KEY_Arabic_teh 0x05ca /* U+062A ARABIC LETTER TEH */ #define XKB_KEY_Arabic_theh 0x05cb /* U+062B ARABIC LETTER THEH */ #define XKB_KEY_Arabic_jeem 0x05cc /* U+062C ARABIC LETTER JEEM */ #define XKB_KEY_Arabic_hah 0x05cd /* U+062D ARABIC LETTER HAH */ #define XKB_KEY_Arabic_khah 0x05ce /* U+062E ARABIC LETTER KHAH */ #define XKB_KEY_Arabic_dal 0x05cf /* U+062F ARABIC LETTER DAL */ #define XKB_KEY_Arabic_thal 0x05d0 /* U+0630 ARABIC LETTER THAL */ #define XKB_KEY_Arabic_ra 0x05d1 /* U+0631 ARABIC LETTER REH */ #define XKB_KEY_Arabic_zain 0x05d2 /* U+0632 ARABIC LETTER ZAIN */ #define XKB_KEY_Arabic_seen 0x05d3 /* U+0633 ARABIC LETTER SEEN */ #define XKB_KEY_Arabic_sheen 0x05d4 /* U+0634 ARABIC LETTER SHEEN */ #define XKB_KEY_Arabic_sad 0x05d5 /* U+0635 ARABIC LETTER SAD */ #define XKB_KEY_Arabic_dad 0x05d6 /* U+0636 ARABIC LETTER DAD */ #define XKB_KEY_Arabic_tah 0x05d7 /* U+0637 ARABIC LETTER TAH */ #define XKB_KEY_Arabic_zah 0x05d8 /* U+0638 ARABIC LETTER ZAH */ #define XKB_KEY_Arabic_ain 0x05d9 /* U+0639 ARABIC LETTER AIN */ #define XKB_KEY_Arabic_ghain 0x05da /* U+063A ARABIC LETTER GHAIN */ #define XKB_KEY_Arabic_tatweel 0x05e0 /* U+0640 ARABIC TATWEEL */ #define XKB_KEY_Arabic_feh 0x05e1 /* U+0641 ARABIC LETTER FEH */ #define XKB_KEY_Arabic_qaf 0x05e2 /* U+0642 ARABIC LETTER QAF */ #define XKB_KEY_Arabic_kaf 0x05e3 /* U+0643 ARABIC LETTER KAF */ #define XKB_KEY_Arabic_lam 0x05e4 /* U+0644 ARABIC LETTER LAM */ #define XKB_KEY_Arabic_meem 0x05e5 /* U+0645 ARABIC LETTER MEEM */ #define XKB_KEY_Arabic_noon 0x05e6 /* U+0646 ARABIC LETTER NOON */ #define XKB_KEY_Arabic_ha 0x05e7 /* U+0647 ARABIC LETTER HEH */ #define XKB_KEY_Arabic_heh 0x05e7 /* deprecated */ #define XKB_KEY_Arabic_waw 0x05e8 /* U+0648 ARABIC LETTER WAW */ #define XKB_KEY_Arabic_alefmaksura 0x05e9 /* U+0649 ARABIC LETTER ALEF MAKSURA */ #define XKB_KEY_Arabic_yeh 0x05ea /* U+064A ARABIC LETTER YEH */ #define XKB_KEY_Arabic_fathatan 0x05eb /* U+064B ARABIC FATHATAN */ #define XKB_KEY_Arabic_dammatan 0x05ec /* U+064C ARABIC DAMMATAN */ #define XKB_KEY_Arabic_kasratan 0x05ed /* U+064D ARABIC KASRATAN */ #define XKB_KEY_Arabic_fatha 0x05ee /* U+064E ARABIC FATHA */ #define XKB_KEY_Arabic_damma 0x05ef /* U+064F ARABIC DAMMA */ #define XKB_KEY_Arabic_kasra 0x05f0 /* U+0650 ARABIC KASRA */ #define XKB_KEY_Arabic_shadda 0x05f1 /* U+0651 ARABIC SHADDA */ #define XKB_KEY_Arabic_sukun 0x05f2 /* U+0652 ARABIC SUKUN */ #define XKB_KEY_Arabic_madda_above 0x1000653 /* U+0653 ARABIC MADDAH ABOVE */ #define XKB_KEY_Arabic_hamza_above 0x1000654 /* U+0654 ARABIC HAMZA ABOVE */ #define XKB_KEY_Arabic_hamza_below 0x1000655 /* U+0655 ARABIC HAMZA BELOW */ #define XKB_KEY_Arabic_jeh 0x1000698 /* U+0698 ARABIC LETTER JEH */ #define XKB_KEY_Arabic_veh 0x10006a4 /* U+06A4 ARABIC LETTER VEH */ #define XKB_KEY_Arabic_keheh 0x10006a9 /* U+06A9 ARABIC LETTER KEHEH */ #define XKB_KEY_Arabic_gaf 0x10006af /* U+06AF ARABIC LETTER GAF */ #define XKB_KEY_Arabic_noon_ghunna 0x10006ba /* U+06BA ARABIC LETTER NOON GHUNNA */ #define XKB_KEY_Arabic_heh_doachashmee 0x10006be /* U+06BE ARABIC LETTER HEH DOACHASHMEE */ #define XKB_KEY_Farsi_yeh 0x10006cc /* U+06CC ARABIC LETTER FARSI YEH */ #define XKB_KEY_Arabic_farsi_yeh 0x10006cc /* deprecated alias for Farsi_yeh */ #define XKB_KEY_Arabic_yeh_baree 0x10006d2 /* U+06D2 ARABIC LETTER YEH BARREE */ #define XKB_KEY_Arabic_heh_goal 0x10006c1 /* U+06C1 ARABIC LETTER HEH GOAL */ #define XKB_KEY_Arabic_switch 0xff7e /* non-deprecated alias for Mode_switch */ /* * Cyrillic * Byte 3 = 6 */ #define XKB_KEY_Cyrillic_GHE_bar 0x1000492 /* U+0492 CYRILLIC CAPITAL LETTER GHE WITH STROKE */ #define XKB_KEY_Cyrillic_ghe_bar 0x1000493 /* U+0493 CYRILLIC SMALL LETTER GHE WITH STROKE */ #define XKB_KEY_Cyrillic_ZHE_descender 0x1000496 /* U+0496 CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */ #define XKB_KEY_Cyrillic_zhe_descender 0x1000497 /* U+0497 CYRILLIC SMALL LETTER ZHE WITH DESCENDER */ #define XKB_KEY_Cyrillic_KA_descender 0x100049a /* U+049A CYRILLIC CAPITAL LETTER KA WITH DESCENDER */ #define XKB_KEY_Cyrillic_ka_descender 0x100049b /* U+049B CYRILLIC SMALL LETTER KA WITH DESCENDER */ #define XKB_KEY_Cyrillic_KA_vertstroke 0x100049c /* U+049C CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */ #define XKB_KEY_Cyrillic_ka_vertstroke 0x100049d /* U+049D CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE */ #define XKB_KEY_Cyrillic_EN_descender 0x10004a2 /* U+04A2 CYRILLIC CAPITAL LETTER EN WITH DESCENDER */ #define XKB_KEY_Cyrillic_en_descender 0x10004a3 /* U+04A3 CYRILLIC SMALL LETTER EN WITH DESCENDER */ #define XKB_KEY_Cyrillic_U_straight 0x10004ae /* U+04AE CYRILLIC CAPITAL LETTER STRAIGHT U */ #define XKB_KEY_Cyrillic_u_straight 0x10004af /* U+04AF CYRILLIC SMALL LETTER STRAIGHT U */ #define XKB_KEY_Cyrillic_U_straight_bar 0x10004b0 /* U+04B0 CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */ #define XKB_KEY_Cyrillic_u_straight_bar 0x10004b1 /* U+04B1 CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE */ #define XKB_KEY_Cyrillic_HA_descender 0x10004b2 /* U+04B2 CYRILLIC CAPITAL LETTER HA WITH DESCENDER */ #define XKB_KEY_Cyrillic_ha_descender 0x10004b3 /* U+04B3 CYRILLIC SMALL LETTER HA WITH DESCENDER */ #define XKB_KEY_Cyrillic_CHE_descender 0x10004b6 /* U+04B6 CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */ #define XKB_KEY_Cyrillic_che_descender 0x10004b7 /* U+04B7 CYRILLIC SMALL LETTER CHE WITH DESCENDER */ #define XKB_KEY_Cyrillic_CHE_vertstroke 0x10004b8 /* U+04B8 CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */ #define XKB_KEY_Cyrillic_che_vertstroke 0x10004b9 /* U+04B9 CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE */ #define XKB_KEY_Cyrillic_SHHA 0x10004ba /* U+04BA CYRILLIC CAPITAL LETTER SHHA */ #define XKB_KEY_Cyrillic_shha 0x10004bb /* U+04BB CYRILLIC SMALL LETTER SHHA */ #define XKB_KEY_Cyrillic_SCHWA 0x10004d8 /* U+04D8 CYRILLIC CAPITAL LETTER SCHWA */ #define XKB_KEY_Cyrillic_schwa 0x10004d9 /* U+04D9 CYRILLIC SMALL LETTER SCHWA */ #define XKB_KEY_Cyrillic_I_macron 0x10004e2 /* U+04E2 CYRILLIC CAPITAL LETTER I WITH MACRON */ #define XKB_KEY_Cyrillic_i_macron 0x10004e3 /* U+04E3 CYRILLIC SMALL LETTER I WITH MACRON */ #define XKB_KEY_Cyrillic_O_bar 0x10004e8 /* U+04E8 CYRILLIC CAPITAL LETTER BARRED O */ #define XKB_KEY_Cyrillic_o_bar 0x10004e9 /* U+04E9 CYRILLIC SMALL LETTER BARRED O */ #define XKB_KEY_Cyrillic_U_macron 0x10004ee /* U+04EE CYRILLIC CAPITAL LETTER U WITH MACRON */ #define XKB_KEY_Cyrillic_u_macron 0x10004ef /* U+04EF CYRILLIC SMALL LETTER U WITH MACRON */ #define XKB_KEY_Serbian_dje 0x06a1 /* U+0452 CYRILLIC SMALL LETTER DJE */ #define XKB_KEY_Macedonia_gje 0x06a2 /* U+0453 CYRILLIC SMALL LETTER GJE */ #define XKB_KEY_Cyrillic_io 0x06a3 /* U+0451 CYRILLIC SMALL LETTER IO */ #define XKB_KEY_Ukrainian_ie 0x06a4 /* U+0454 CYRILLIC SMALL LETTER UKRAINIAN IE */ #define XKB_KEY_Ukranian_je 0x06a4 /* deprecated */ #define XKB_KEY_Macedonia_dse 0x06a5 /* U+0455 CYRILLIC SMALL LETTER DZE */ #define XKB_KEY_Ukrainian_i 0x06a6 /* U+0456 CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ #define XKB_KEY_Ukranian_i 0x06a6 /* deprecated */ #define XKB_KEY_Ukrainian_yi 0x06a7 /* U+0457 CYRILLIC SMALL LETTER YI */ #define XKB_KEY_Ukranian_yi 0x06a7 /* deprecated */ #define XKB_KEY_Cyrillic_je 0x06a8 /* U+0458 CYRILLIC SMALL LETTER JE */ #define XKB_KEY_Serbian_je 0x06a8 /* deprecated */ #define XKB_KEY_Cyrillic_lje 0x06a9 /* U+0459 CYRILLIC SMALL LETTER LJE */ #define XKB_KEY_Serbian_lje 0x06a9 /* deprecated */ #define XKB_KEY_Cyrillic_nje 0x06aa /* U+045A CYRILLIC SMALL LETTER NJE */ #define XKB_KEY_Serbian_nje 0x06aa /* deprecated */ #define XKB_KEY_Serbian_tshe 0x06ab /* U+045B CYRILLIC SMALL LETTER TSHE */ #define XKB_KEY_Macedonia_kje 0x06ac /* U+045C CYRILLIC SMALL LETTER KJE */ #define XKB_KEY_Ukrainian_ghe_with_upturn 0x06ad /* U+0491 CYRILLIC SMALL LETTER GHE WITH UPTURN */ #define XKB_KEY_Byelorussian_shortu 0x06ae /* U+045E CYRILLIC SMALL LETTER SHORT U */ #define XKB_KEY_Cyrillic_dzhe 0x06af /* U+045F CYRILLIC SMALL LETTER DZHE */ #define XKB_KEY_Serbian_dze 0x06af /* deprecated */ #define XKB_KEY_numerosign 0x06b0 /* U+2116 NUMERO SIGN */ #define XKB_KEY_Serbian_DJE 0x06b1 /* U+0402 CYRILLIC CAPITAL LETTER DJE */ #define XKB_KEY_Macedonia_GJE 0x06b2 /* U+0403 CYRILLIC CAPITAL LETTER GJE */ #define XKB_KEY_Cyrillic_IO 0x06b3 /* U+0401 CYRILLIC CAPITAL LETTER IO */ #define XKB_KEY_Ukrainian_IE 0x06b4 /* U+0404 CYRILLIC CAPITAL LETTER UKRAINIAN IE */ #define XKB_KEY_Ukranian_JE 0x06b4 /* deprecated */ #define XKB_KEY_Macedonia_DSE 0x06b5 /* U+0405 CYRILLIC CAPITAL LETTER DZE */ #define XKB_KEY_Ukrainian_I 0x06b6 /* U+0406 CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ #define XKB_KEY_Ukranian_I 0x06b6 /* deprecated */ #define XKB_KEY_Ukrainian_YI 0x06b7 /* U+0407 CYRILLIC CAPITAL LETTER YI */ #define XKB_KEY_Ukranian_YI 0x06b7 /* deprecated */ #define XKB_KEY_Cyrillic_JE 0x06b8 /* U+0408 CYRILLIC CAPITAL LETTER JE */ #define XKB_KEY_Serbian_JE 0x06b8 /* deprecated */ #define XKB_KEY_Cyrillic_LJE 0x06b9 /* U+0409 CYRILLIC CAPITAL LETTER LJE */ #define XKB_KEY_Serbian_LJE 0x06b9 /* deprecated */ #define XKB_KEY_Cyrillic_NJE 0x06ba /* U+040A CYRILLIC CAPITAL LETTER NJE */ #define XKB_KEY_Serbian_NJE 0x06ba /* deprecated */ #define XKB_KEY_Serbian_TSHE 0x06bb /* U+040B CYRILLIC CAPITAL LETTER TSHE */ #define XKB_KEY_Macedonia_KJE 0x06bc /* U+040C CYRILLIC CAPITAL LETTER KJE */ #define XKB_KEY_Ukrainian_GHE_WITH_UPTURN 0x06bd /* U+0490 CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ #define XKB_KEY_Byelorussian_SHORTU 0x06be /* U+040E CYRILLIC CAPITAL LETTER SHORT U */ #define XKB_KEY_Cyrillic_DZHE 0x06bf /* U+040F CYRILLIC CAPITAL LETTER DZHE */ #define XKB_KEY_Serbian_DZE 0x06bf /* deprecated */ #define XKB_KEY_Cyrillic_yu 0x06c0 /* U+044E CYRILLIC SMALL LETTER YU */ #define XKB_KEY_Cyrillic_a 0x06c1 /* U+0430 CYRILLIC SMALL LETTER A */ #define XKB_KEY_Cyrillic_be 0x06c2 /* U+0431 CYRILLIC SMALL LETTER BE */ #define XKB_KEY_Cyrillic_tse 0x06c3 /* U+0446 CYRILLIC SMALL LETTER TSE */ #define XKB_KEY_Cyrillic_de 0x06c4 /* U+0434 CYRILLIC SMALL LETTER DE */ #define XKB_KEY_Cyrillic_ie 0x06c5 /* U+0435 CYRILLIC SMALL LETTER IE */ #define XKB_KEY_Cyrillic_ef 0x06c6 /* U+0444 CYRILLIC SMALL LETTER EF */ #define XKB_KEY_Cyrillic_ghe 0x06c7 /* U+0433 CYRILLIC SMALL LETTER GHE */ #define XKB_KEY_Cyrillic_ha 0x06c8 /* U+0445 CYRILLIC SMALL LETTER HA */ #define XKB_KEY_Cyrillic_i 0x06c9 /* U+0438 CYRILLIC SMALL LETTER I */ #define XKB_KEY_Cyrillic_shorti 0x06ca /* U+0439 CYRILLIC SMALL LETTER SHORT I */ #define XKB_KEY_Cyrillic_ka 0x06cb /* U+043A CYRILLIC SMALL LETTER KA */ #define XKB_KEY_Cyrillic_el 0x06cc /* U+043B CYRILLIC SMALL LETTER EL */ #define XKB_KEY_Cyrillic_em 0x06cd /* U+043C CYRILLIC SMALL LETTER EM */ #define XKB_KEY_Cyrillic_en 0x06ce /* U+043D CYRILLIC SMALL LETTER EN */ #define XKB_KEY_Cyrillic_o 0x06cf /* U+043E CYRILLIC SMALL LETTER O */ #define XKB_KEY_Cyrillic_pe 0x06d0 /* U+043F CYRILLIC SMALL LETTER PE */ #define XKB_KEY_Cyrillic_ya 0x06d1 /* U+044F CYRILLIC SMALL LETTER YA */ #define XKB_KEY_Cyrillic_er 0x06d2 /* U+0440 CYRILLIC SMALL LETTER ER */ #define XKB_KEY_Cyrillic_es 0x06d3 /* U+0441 CYRILLIC SMALL LETTER ES */ #define XKB_KEY_Cyrillic_te 0x06d4 /* U+0442 CYRILLIC SMALL LETTER TE */ #define XKB_KEY_Cyrillic_u 0x06d5 /* U+0443 CYRILLIC SMALL LETTER U */ #define XKB_KEY_Cyrillic_zhe 0x06d6 /* U+0436 CYRILLIC SMALL LETTER ZHE */ #define XKB_KEY_Cyrillic_ve 0x06d7 /* U+0432 CYRILLIC SMALL LETTER VE */ #define XKB_KEY_Cyrillic_softsign 0x06d8 /* U+044C CYRILLIC SMALL LETTER SOFT SIGN */ #define XKB_KEY_Cyrillic_yeru 0x06d9 /* U+044B CYRILLIC SMALL LETTER YERU */ #define XKB_KEY_Cyrillic_ze 0x06da /* U+0437 CYRILLIC SMALL LETTER ZE */ #define XKB_KEY_Cyrillic_sha 0x06db /* U+0448 CYRILLIC SMALL LETTER SHA */ #define XKB_KEY_Cyrillic_e 0x06dc /* U+044D CYRILLIC SMALL LETTER E */ #define XKB_KEY_Cyrillic_shcha 0x06dd /* U+0449 CYRILLIC SMALL LETTER SHCHA */ #define XKB_KEY_Cyrillic_che 0x06de /* U+0447 CYRILLIC SMALL LETTER CHE */ #define XKB_KEY_Cyrillic_hardsign 0x06df /* U+044A CYRILLIC SMALL LETTER HARD SIGN */ #define XKB_KEY_Cyrillic_YU 0x06e0 /* U+042E CYRILLIC CAPITAL LETTER YU */ #define XKB_KEY_Cyrillic_A 0x06e1 /* U+0410 CYRILLIC CAPITAL LETTER A */ #define XKB_KEY_Cyrillic_BE 0x06e2 /* U+0411 CYRILLIC CAPITAL LETTER BE */ #define XKB_KEY_Cyrillic_TSE 0x06e3 /* U+0426 CYRILLIC CAPITAL LETTER TSE */ #define XKB_KEY_Cyrillic_DE 0x06e4 /* U+0414 CYRILLIC CAPITAL LETTER DE */ #define XKB_KEY_Cyrillic_IE 0x06e5 /* U+0415 CYRILLIC CAPITAL LETTER IE */ #define XKB_KEY_Cyrillic_EF 0x06e6 /* U+0424 CYRILLIC CAPITAL LETTER EF */ #define XKB_KEY_Cyrillic_GHE 0x06e7 /* U+0413 CYRILLIC CAPITAL LETTER GHE */ #define XKB_KEY_Cyrillic_HA 0x06e8 /* U+0425 CYRILLIC CAPITAL LETTER HA */ #define XKB_KEY_Cyrillic_I 0x06e9 /* U+0418 CYRILLIC CAPITAL LETTER I */ #define XKB_KEY_Cyrillic_SHORTI 0x06ea /* U+0419 CYRILLIC CAPITAL LETTER SHORT I */ #define XKB_KEY_Cyrillic_KA 0x06eb /* U+041A CYRILLIC CAPITAL LETTER KA */ #define XKB_KEY_Cyrillic_EL 0x06ec /* U+041B CYRILLIC CAPITAL LETTER EL */ #define XKB_KEY_Cyrillic_EM 0x06ed /* U+041C CYRILLIC CAPITAL LETTER EM */ #define XKB_KEY_Cyrillic_EN 0x06ee /* U+041D CYRILLIC CAPITAL LETTER EN */ #define XKB_KEY_Cyrillic_O 0x06ef /* U+041E CYRILLIC CAPITAL LETTER O */ #define XKB_KEY_Cyrillic_PE 0x06f0 /* U+041F CYRILLIC CAPITAL LETTER PE */ #define XKB_KEY_Cyrillic_YA 0x06f1 /* U+042F CYRILLIC CAPITAL LETTER YA */ #define XKB_KEY_Cyrillic_ER 0x06f2 /* U+0420 CYRILLIC CAPITAL LETTER ER */ #define XKB_KEY_Cyrillic_ES 0x06f3 /* U+0421 CYRILLIC CAPITAL LETTER ES */ #define XKB_KEY_Cyrillic_TE 0x06f4 /* U+0422 CYRILLIC CAPITAL LETTER TE */ #define XKB_KEY_Cyrillic_U 0x06f5 /* U+0423 CYRILLIC CAPITAL LETTER U */ #define XKB_KEY_Cyrillic_ZHE 0x06f6 /* U+0416 CYRILLIC CAPITAL LETTER ZHE */ #define XKB_KEY_Cyrillic_VE 0x06f7 /* U+0412 CYRILLIC CAPITAL LETTER VE */ #define XKB_KEY_Cyrillic_SOFTSIGN 0x06f8 /* U+042C CYRILLIC CAPITAL LETTER SOFT SIGN */ #define XKB_KEY_Cyrillic_YERU 0x06f9 /* U+042B CYRILLIC CAPITAL LETTER YERU */ #define XKB_KEY_Cyrillic_ZE 0x06fa /* U+0417 CYRILLIC CAPITAL LETTER ZE */ #define XKB_KEY_Cyrillic_SHA 0x06fb /* U+0428 CYRILLIC CAPITAL LETTER SHA */ #define XKB_KEY_Cyrillic_E 0x06fc /* U+042D CYRILLIC CAPITAL LETTER E */ #define XKB_KEY_Cyrillic_SHCHA 0x06fd /* U+0429 CYRILLIC CAPITAL LETTER SHCHA */ #define XKB_KEY_Cyrillic_CHE 0x06fe /* U+0427 CYRILLIC CAPITAL LETTER CHE */ #define XKB_KEY_Cyrillic_HARDSIGN 0x06ff /* U+042A CYRILLIC CAPITAL LETTER HARD SIGN */ /* * Greek * (based on an early draft of, and not quite identical to, ISO/IEC 8859-7) * Byte 3 = 7 */ #define XKB_KEY_Greek_ALPHAaccent 0x07a1 /* U+0386 GREEK CAPITAL LETTER ALPHA WITH TONOS */ #define XKB_KEY_Greek_EPSILONaccent 0x07a2 /* U+0388 GREEK CAPITAL LETTER EPSILON WITH TONOS */ #define XKB_KEY_Greek_ETAaccent 0x07a3 /* U+0389 GREEK CAPITAL LETTER ETA WITH TONOS */ #define XKB_KEY_Greek_IOTAaccent 0x07a4 /* U+038A GREEK CAPITAL LETTER IOTA WITH TONOS */ #define XKB_KEY_Greek_IOTAdieresis 0x07a5 /* U+03AA GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ #define XKB_KEY_Greek_IOTAdiaeresis 0x07a5 /* deprecated (old typo) */ #define XKB_KEY_Greek_OMICRONaccent 0x07a7 /* U+038C GREEK CAPITAL LETTER OMICRON WITH TONOS */ #define XKB_KEY_Greek_UPSILONaccent 0x07a8 /* U+038E GREEK CAPITAL LETTER UPSILON WITH TONOS */ #define XKB_KEY_Greek_UPSILONdieresis 0x07a9 /* U+03AB GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ #define XKB_KEY_Greek_OMEGAaccent 0x07ab /* U+038F GREEK CAPITAL LETTER OMEGA WITH TONOS */ #define XKB_KEY_Greek_accentdieresis 0x07ae /* U+0385 GREEK DIALYTIKA TONOS */ #define XKB_KEY_Greek_horizbar 0x07af /* U+2015 HORIZONTAL BAR */ #define XKB_KEY_Greek_alphaaccent 0x07b1 /* U+03AC GREEK SMALL LETTER ALPHA WITH TONOS */ #define XKB_KEY_Greek_epsilonaccent 0x07b2 /* U+03AD GREEK SMALL LETTER EPSILON WITH TONOS */ #define XKB_KEY_Greek_etaaccent 0x07b3 /* U+03AE GREEK SMALL LETTER ETA WITH TONOS */ #define XKB_KEY_Greek_iotaaccent 0x07b4 /* U+03AF GREEK SMALL LETTER IOTA WITH TONOS */ #define XKB_KEY_Greek_iotadieresis 0x07b5 /* U+03CA GREEK SMALL LETTER IOTA WITH DIALYTIKA */ #define XKB_KEY_Greek_iotaaccentdieresis 0x07b6 /* U+0390 GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ #define XKB_KEY_Greek_omicronaccent 0x07b7 /* U+03CC GREEK SMALL LETTER OMICRON WITH TONOS */ #define XKB_KEY_Greek_upsilonaccent 0x07b8 /* U+03CD GREEK SMALL LETTER UPSILON WITH TONOS */ #define XKB_KEY_Greek_upsilondieresis 0x07b9 /* U+03CB GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ #define XKB_KEY_Greek_upsilonaccentdieresis 0x07ba /* U+03B0 GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ #define XKB_KEY_Greek_omegaaccent 0x07bb /* U+03CE GREEK SMALL LETTER OMEGA WITH TONOS */ #define XKB_KEY_Greek_ALPHA 0x07c1 /* U+0391 GREEK CAPITAL LETTER ALPHA */ #define XKB_KEY_Greek_BETA 0x07c2 /* U+0392 GREEK CAPITAL LETTER BETA */ #define XKB_KEY_Greek_GAMMA 0x07c3 /* U+0393 GREEK CAPITAL LETTER GAMMA */ #define XKB_KEY_Greek_DELTA 0x07c4 /* U+0394 GREEK CAPITAL LETTER DELTA */ #define XKB_KEY_Greek_EPSILON 0x07c5 /* U+0395 GREEK CAPITAL LETTER EPSILON */ #define XKB_KEY_Greek_ZETA 0x07c6 /* U+0396 GREEK CAPITAL LETTER ZETA */ #define XKB_KEY_Greek_ETA 0x07c7 /* U+0397 GREEK CAPITAL LETTER ETA */ #define XKB_KEY_Greek_THETA 0x07c8 /* U+0398 GREEK CAPITAL LETTER THETA */ #define XKB_KEY_Greek_IOTA 0x07c9 /* U+0399 GREEK CAPITAL LETTER IOTA */ #define XKB_KEY_Greek_KAPPA 0x07ca /* U+039A GREEK CAPITAL LETTER KAPPA */ #define XKB_KEY_Greek_LAMDA 0x07cb /* U+039B GREEK CAPITAL LETTER LAMDA */ #define XKB_KEY_Greek_LAMBDA 0x07cb /* non-deprecated alias for Greek_LAMDA */ #define XKB_KEY_Greek_MU 0x07cc /* U+039C GREEK CAPITAL LETTER MU */ #define XKB_KEY_Greek_NU 0x07cd /* U+039D GREEK CAPITAL LETTER NU */ #define XKB_KEY_Greek_XI 0x07ce /* U+039E GREEK CAPITAL LETTER XI */ #define XKB_KEY_Greek_OMICRON 0x07cf /* U+039F GREEK CAPITAL LETTER OMICRON */ #define XKB_KEY_Greek_PI 0x07d0 /* U+03A0 GREEK CAPITAL LETTER PI */ #define XKB_KEY_Greek_RHO 0x07d1 /* U+03A1 GREEK CAPITAL LETTER RHO */ #define XKB_KEY_Greek_SIGMA 0x07d2 /* U+03A3 GREEK CAPITAL LETTER SIGMA */ #define XKB_KEY_Greek_TAU 0x07d4 /* U+03A4 GREEK CAPITAL LETTER TAU */ #define XKB_KEY_Greek_UPSILON 0x07d5 /* U+03A5 GREEK CAPITAL LETTER UPSILON */ #define XKB_KEY_Greek_PHI 0x07d6 /* U+03A6 GREEK CAPITAL LETTER PHI */ #define XKB_KEY_Greek_CHI 0x07d7 /* U+03A7 GREEK CAPITAL LETTER CHI */ #define XKB_KEY_Greek_PSI 0x07d8 /* U+03A8 GREEK CAPITAL LETTER PSI */ #define XKB_KEY_Greek_OMEGA 0x07d9 /* U+03A9 GREEK CAPITAL LETTER OMEGA */ #define XKB_KEY_Greek_alpha 0x07e1 /* U+03B1 GREEK SMALL LETTER ALPHA */ #define XKB_KEY_Greek_beta 0x07e2 /* U+03B2 GREEK SMALL LETTER BETA */ #define XKB_KEY_Greek_gamma 0x07e3 /* U+03B3 GREEK SMALL LETTER GAMMA */ #define XKB_KEY_Greek_delta 0x07e4 /* U+03B4 GREEK SMALL LETTER DELTA */ #define XKB_KEY_Greek_epsilon 0x07e5 /* U+03B5 GREEK SMALL LETTER EPSILON */ #define XKB_KEY_Greek_zeta 0x07e6 /* U+03B6 GREEK SMALL LETTER ZETA */ #define XKB_KEY_Greek_eta 0x07e7 /* U+03B7 GREEK SMALL LETTER ETA */ #define XKB_KEY_Greek_theta 0x07e8 /* U+03B8 GREEK SMALL LETTER THETA */ #define XKB_KEY_Greek_iota 0x07e9 /* U+03B9 GREEK SMALL LETTER IOTA */ #define XKB_KEY_Greek_kappa 0x07ea /* U+03BA GREEK SMALL LETTER KAPPA */ #define XKB_KEY_Greek_lamda 0x07eb /* U+03BB GREEK SMALL LETTER LAMDA */ #define XKB_KEY_Greek_lambda 0x07eb /* non-deprecated alias for Greek_lamda */ #define XKB_KEY_Greek_mu 0x07ec /* U+03BC GREEK SMALL LETTER MU */ #define XKB_KEY_Greek_nu 0x07ed /* U+03BD GREEK SMALL LETTER NU */ #define XKB_KEY_Greek_xi 0x07ee /* U+03BE GREEK SMALL LETTER XI */ #define XKB_KEY_Greek_omicron 0x07ef /* U+03BF GREEK SMALL LETTER OMICRON */ #define XKB_KEY_Greek_pi 0x07f0 /* U+03C0 GREEK SMALL LETTER PI */ #define XKB_KEY_Greek_rho 0x07f1 /* U+03C1 GREEK SMALL LETTER RHO */ #define XKB_KEY_Greek_sigma 0x07f2 /* U+03C3 GREEK SMALL LETTER SIGMA */ #define XKB_KEY_Greek_finalsmallsigma 0x07f3 /* U+03C2 GREEK SMALL LETTER FINAL SIGMA */ #define XKB_KEY_Greek_tau 0x07f4 /* U+03C4 GREEK SMALL LETTER TAU */ #define XKB_KEY_Greek_upsilon 0x07f5 /* U+03C5 GREEK SMALL LETTER UPSILON */ #define XKB_KEY_Greek_phi 0x07f6 /* U+03C6 GREEK SMALL LETTER PHI */ #define XKB_KEY_Greek_chi 0x07f7 /* U+03C7 GREEK SMALL LETTER CHI */ #define XKB_KEY_Greek_psi 0x07f8 /* U+03C8 GREEK SMALL LETTER PSI */ #define XKB_KEY_Greek_omega 0x07f9 /* U+03C9 GREEK SMALL LETTER OMEGA */ #define XKB_KEY_Greek_switch 0xff7e /* non-deprecated alias for Mode_switch */ /* * Technical * (from the DEC VT330/VT420 Technical Character Set, http://vt100.net/charsets/technical.html) * Byte 3 = 8 */ #define XKB_KEY_leftradical 0x08a1 /* U+23B7 RADICAL SYMBOL BOTTOM */ #define XKB_KEY_topleftradical 0x08a2 /*(U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT)*/ #define XKB_KEY_horizconnector 0x08a3 /*(U+2500 BOX DRAWINGS LIGHT HORIZONTAL)*/ #define XKB_KEY_topintegral 0x08a4 /* U+2320 TOP HALF INTEGRAL */ #define XKB_KEY_botintegral 0x08a5 /* U+2321 BOTTOM HALF INTEGRAL */ #define XKB_KEY_vertconnector 0x08a6 /*(U+2502 BOX DRAWINGS LIGHT VERTICAL)*/ #define XKB_KEY_topleftsqbracket 0x08a7 /* U+23A1 LEFT SQUARE BRACKET UPPER CORNER */ #define XKB_KEY_botleftsqbracket 0x08a8 /* U+23A3 LEFT SQUARE BRACKET LOWER CORNER */ #define XKB_KEY_toprightsqbracket 0x08a9 /* U+23A4 RIGHT SQUARE BRACKET UPPER CORNER */ #define XKB_KEY_botrightsqbracket 0x08aa /* U+23A6 RIGHT SQUARE BRACKET LOWER CORNER */ #define XKB_KEY_topleftparens 0x08ab /* U+239B LEFT PARENTHESIS UPPER HOOK */ #define XKB_KEY_botleftparens 0x08ac /* U+239D LEFT PARENTHESIS LOWER HOOK */ #define XKB_KEY_toprightparens 0x08ad /* U+239E RIGHT PARENTHESIS UPPER HOOK */ #define XKB_KEY_botrightparens 0x08ae /* U+23A0 RIGHT PARENTHESIS LOWER HOOK */ #define XKB_KEY_leftmiddlecurlybrace 0x08af /* U+23A8 LEFT CURLY BRACKET MIDDLE PIECE */ #define XKB_KEY_rightmiddlecurlybrace 0x08b0 /* U+23AC RIGHT CURLY BRACKET MIDDLE PIECE */ #define XKB_KEY_topleftsummation 0x08b1 #define XKB_KEY_botleftsummation 0x08b2 #define XKB_KEY_topvertsummationconnector 0x08b3 #define XKB_KEY_botvertsummationconnector 0x08b4 #define XKB_KEY_toprightsummation 0x08b5 #define XKB_KEY_botrightsummation 0x08b6 #define XKB_KEY_rightmiddlesummation 0x08b7 #define XKB_KEY_lessthanequal 0x08bc /* U+2264 LESS-THAN OR EQUAL TO */ #define XKB_KEY_notequal 0x08bd /* U+2260 NOT EQUAL TO */ #define XKB_KEY_greaterthanequal 0x08be /* U+2265 GREATER-THAN OR EQUAL TO */ #define XKB_KEY_integral 0x08bf /* U+222B INTEGRAL */ #define XKB_KEY_therefore 0x08c0 /* U+2234 THEREFORE */ #define XKB_KEY_variation 0x08c1 /* U+221D PROPORTIONAL TO */ #define XKB_KEY_infinity 0x08c2 /* U+221E INFINITY */ #define XKB_KEY_nabla 0x08c5 /* U+2207 NABLA */ #define XKB_KEY_approximate 0x08c8 /* U+223C TILDE OPERATOR */ #define XKB_KEY_similarequal 0x08c9 /* U+2243 ASYMPTOTICALLY EQUAL TO */ #define XKB_KEY_ifonlyif 0x08cd /* U+21D4 LEFT RIGHT DOUBLE ARROW */ #define XKB_KEY_implies 0x08ce /* U+21D2 RIGHTWARDS DOUBLE ARROW */ #define XKB_KEY_identical 0x08cf /* U+2261 IDENTICAL TO */ #define XKB_KEY_radical 0x08d6 /* U+221A SQUARE ROOT */ #define XKB_KEY_includedin 0x08da /* U+2282 SUBSET OF */ #define XKB_KEY_includes 0x08db /* U+2283 SUPERSET OF */ #define XKB_KEY_intersection 0x08dc /* U+2229 INTERSECTION */ #define XKB_KEY_union 0x08dd /* U+222A UNION */ #define XKB_KEY_logicaland 0x08de /* U+2227 LOGICAL AND */ #define XKB_KEY_logicalor 0x08df /* U+2228 LOGICAL OR */ #define XKB_KEY_partialderivative 0x08ef /* U+2202 PARTIAL DIFFERENTIAL */ #define XKB_KEY_function 0x08f6 /* U+0192 LATIN SMALL LETTER F WITH HOOK */ #define XKB_KEY_leftarrow 0x08fb /* U+2190 LEFTWARDS ARROW */ #define XKB_KEY_uparrow 0x08fc /* U+2191 UPWARDS ARROW */ #define XKB_KEY_rightarrow 0x08fd /* U+2192 RIGHTWARDS ARROW */ #define XKB_KEY_downarrow 0x08fe /* U+2193 DOWNWARDS ARROW */ /* * Special * (from the DEC VT100 Special Graphics Character Set) * Byte 3 = 9 */ #define XKB_KEY_blank 0x09df #define XKB_KEY_soliddiamond 0x09e0 /* U+25C6 BLACK DIAMOND */ #define XKB_KEY_checkerboard 0x09e1 /* U+2592 MEDIUM SHADE */ #define XKB_KEY_ht 0x09e2 /* U+2409 SYMBOL FOR HORIZONTAL TABULATION */ #define XKB_KEY_ff 0x09e3 /* U+240C SYMBOL FOR FORM FEED */ #define XKB_KEY_cr 0x09e4 /* U+240D SYMBOL FOR CARRIAGE RETURN */ #define XKB_KEY_lf 0x09e5 /* U+240A SYMBOL FOR LINE FEED */ #define XKB_KEY_nl 0x09e8 /* U+2424 SYMBOL FOR NEWLINE */ #define XKB_KEY_vt 0x09e9 /* U+240B SYMBOL FOR VERTICAL TABULATION */ #define XKB_KEY_lowrightcorner 0x09ea /* U+2518 BOX DRAWINGS LIGHT UP AND LEFT */ #define XKB_KEY_uprightcorner 0x09eb /* U+2510 BOX DRAWINGS LIGHT DOWN AND LEFT */ #define XKB_KEY_upleftcorner 0x09ec /* U+250C BOX DRAWINGS LIGHT DOWN AND RIGHT */ #define XKB_KEY_lowleftcorner 0x09ed /* U+2514 BOX DRAWINGS LIGHT UP AND RIGHT */ #define XKB_KEY_crossinglines 0x09ee /* U+253C BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ #define XKB_KEY_horizlinescan1 0x09ef /* U+23BA HORIZONTAL SCAN LINE-1 */ #define XKB_KEY_horizlinescan3 0x09f0 /* U+23BB HORIZONTAL SCAN LINE-3 */ #define XKB_KEY_horizlinescan5 0x09f1 /* U+2500 BOX DRAWINGS LIGHT HORIZONTAL */ #define XKB_KEY_horizlinescan7 0x09f2 /* U+23BC HORIZONTAL SCAN LINE-7 */ #define XKB_KEY_horizlinescan9 0x09f3 /* U+23BD HORIZONTAL SCAN LINE-9 */ #define XKB_KEY_leftt 0x09f4 /* U+251C BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ #define XKB_KEY_rightt 0x09f5 /* U+2524 BOX DRAWINGS LIGHT VERTICAL AND LEFT */ #define XKB_KEY_bott 0x09f6 /* U+2534 BOX DRAWINGS LIGHT UP AND HORIZONTAL */ #define XKB_KEY_topt 0x09f7 /* U+252C BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ #define XKB_KEY_vertbar 0x09f8 /* U+2502 BOX DRAWINGS LIGHT VERTICAL */ /* * Publishing * (these are probably from a long forgotten DEC Publishing * font that once shipped with DECwrite) * Byte 3 = 0x0a */ #define XKB_KEY_emspace 0x0aa1 /* U+2003 EM SPACE */ #define XKB_KEY_enspace 0x0aa2 /* U+2002 EN SPACE */ #define XKB_KEY_em3space 0x0aa3 /* U+2004 THREE-PER-EM SPACE */ #define XKB_KEY_em4space 0x0aa4 /* U+2005 FOUR-PER-EM SPACE */ #define XKB_KEY_digitspace 0x0aa5 /* U+2007 FIGURE SPACE */ #define XKB_KEY_punctspace 0x0aa6 /* U+2008 PUNCTUATION SPACE */ #define XKB_KEY_thinspace 0x0aa7 /* U+2009 THIN SPACE */ #define XKB_KEY_hairspace 0x0aa8 /* U+200A HAIR SPACE */ #define XKB_KEY_emdash 0x0aa9 /* U+2014 EM DASH */ #define XKB_KEY_endash 0x0aaa /* U+2013 EN DASH */ #define XKB_KEY_signifblank 0x0aac /*(U+2423 OPEN BOX)*/ #define XKB_KEY_ellipsis 0x0aae /* U+2026 HORIZONTAL ELLIPSIS */ #define XKB_KEY_doubbaselinedot 0x0aaf /* U+2025 TWO DOT LEADER */ #define XKB_KEY_onethird 0x0ab0 /* U+2153 VULGAR FRACTION ONE THIRD */ #define XKB_KEY_twothirds 0x0ab1 /* U+2154 VULGAR FRACTION TWO THIRDS */ #define XKB_KEY_onefifth 0x0ab2 /* U+2155 VULGAR FRACTION ONE FIFTH */ #define XKB_KEY_twofifths 0x0ab3 /* U+2156 VULGAR FRACTION TWO FIFTHS */ #define XKB_KEY_threefifths 0x0ab4 /* U+2157 VULGAR FRACTION THREE FIFTHS */ #define XKB_KEY_fourfifths 0x0ab5 /* U+2158 VULGAR FRACTION FOUR FIFTHS */ #define XKB_KEY_onesixth 0x0ab6 /* U+2159 VULGAR FRACTION ONE SIXTH */ #define XKB_KEY_fivesixths 0x0ab7 /* U+215A VULGAR FRACTION FIVE SIXTHS */ #define XKB_KEY_careof 0x0ab8 /* U+2105 CARE OF */ #define XKB_KEY_figdash 0x0abb /* U+2012 FIGURE DASH */ #define XKB_KEY_leftanglebracket 0x0abc /*(U+2329 LEFT-POINTING ANGLE BRACKET)*/ #define XKB_KEY_decimalpoint 0x0abd /*(U+002E FULL STOP)*/ #define XKB_KEY_rightanglebracket 0x0abe /*(U+232A RIGHT-POINTING ANGLE BRACKET)*/ #define XKB_KEY_marker 0x0abf #define XKB_KEY_oneeighth 0x0ac3 /* U+215B VULGAR FRACTION ONE EIGHTH */ #define XKB_KEY_threeeighths 0x0ac4 /* U+215C VULGAR FRACTION THREE EIGHTHS */ #define XKB_KEY_fiveeighths 0x0ac5 /* U+215D VULGAR FRACTION FIVE EIGHTHS */ #define XKB_KEY_seveneighths 0x0ac6 /* U+215E VULGAR FRACTION SEVEN EIGHTHS */ #define XKB_KEY_trademark 0x0ac9 /* U+2122 TRADE MARK SIGN */ #define XKB_KEY_signaturemark 0x0aca /*(U+2613 SALTIRE)*/ #define XKB_KEY_trademarkincircle 0x0acb #define XKB_KEY_leftopentriangle 0x0acc /*(U+25C1 WHITE LEFT-POINTING TRIANGLE)*/ #define XKB_KEY_rightopentriangle 0x0acd /*(U+25B7 WHITE RIGHT-POINTING TRIANGLE)*/ #define XKB_KEY_emopencircle 0x0ace /*(U+25CB WHITE CIRCLE)*/ #define XKB_KEY_emopenrectangle 0x0acf /*(U+25AF WHITE VERTICAL RECTANGLE)*/ #define XKB_KEY_leftsinglequotemark 0x0ad0 /* U+2018 LEFT SINGLE QUOTATION MARK */ #define XKB_KEY_rightsinglequotemark 0x0ad1 /* U+2019 RIGHT SINGLE QUOTATION MARK */ #define XKB_KEY_leftdoublequotemark 0x0ad2 /* U+201C LEFT DOUBLE QUOTATION MARK */ #define XKB_KEY_rightdoublequotemark 0x0ad3 /* U+201D RIGHT DOUBLE QUOTATION MARK */ #define XKB_KEY_prescription 0x0ad4 /* U+211E PRESCRIPTION TAKE */ #define XKB_KEY_permille 0x0ad5 /* U+2030 PER MILLE SIGN */ #define XKB_KEY_minutes 0x0ad6 /* U+2032 PRIME */ #define XKB_KEY_seconds 0x0ad7 /* U+2033 DOUBLE PRIME */ #define XKB_KEY_latincross 0x0ad9 /* U+271D LATIN CROSS */ #define XKB_KEY_hexagram 0x0ada #define XKB_KEY_filledrectbullet 0x0adb /*(U+25AC BLACK RECTANGLE)*/ #define XKB_KEY_filledlefttribullet 0x0adc /*(U+25C0 BLACK LEFT-POINTING TRIANGLE)*/ #define XKB_KEY_filledrighttribullet 0x0add /*(U+25B6 BLACK RIGHT-POINTING TRIANGLE)*/ #define XKB_KEY_emfilledcircle 0x0ade /*(U+25CF BLACK CIRCLE)*/ #define XKB_KEY_emfilledrect 0x0adf /*(U+25AE BLACK VERTICAL RECTANGLE)*/ #define XKB_KEY_enopencircbullet 0x0ae0 /*(U+25E6 WHITE BULLET)*/ #define XKB_KEY_enopensquarebullet 0x0ae1 /*(U+25AB WHITE SMALL SQUARE)*/ #define XKB_KEY_openrectbullet 0x0ae2 /*(U+25AD WHITE RECTANGLE)*/ #define XKB_KEY_opentribulletup 0x0ae3 /*(U+25B3 WHITE UP-POINTING TRIANGLE)*/ #define XKB_KEY_opentribulletdown 0x0ae4 /*(U+25BD WHITE DOWN-POINTING TRIANGLE)*/ #define XKB_KEY_openstar 0x0ae5 /*(U+2606 WHITE STAR)*/ #define XKB_KEY_enfilledcircbullet 0x0ae6 /*(U+2022 BULLET)*/ #define XKB_KEY_enfilledsqbullet 0x0ae7 /*(U+25AA BLACK SMALL SQUARE)*/ #define XKB_KEY_filledtribulletup 0x0ae8 /*(U+25B2 BLACK UP-POINTING TRIANGLE)*/ #define XKB_KEY_filledtribulletdown 0x0ae9 /*(U+25BC BLACK DOWN-POINTING TRIANGLE)*/ #define XKB_KEY_leftpointer 0x0aea /*(U+261C WHITE LEFT POINTING INDEX)*/ #define XKB_KEY_rightpointer 0x0aeb /*(U+261E WHITE RIGHT POINTING INDEX)*/ #define XKB_KEY_club 0x0aec /* U+2663 BLACK CLUB SUIT */ #define XKB_KEY_diamond 0x0aed /* U+2666 BLACK DIAMOND SUIT */ #define XKB_KEY_heart 0x0aee /* U+2665 BLACK HEART SUIT */ #define XKB_KEY_maltesecross 0x0af0 /* U+2720 MALTESE CROSS */ #define XKB_KEY_dagger 0x0af1 /* U+2020 DAGGER */ #define XKB_KEY_doubledagger 0x0af2 /* U+2021 DOUBLE DAGGER */ #define XKB_KEY_checkmark 0x0af3 /* U+2713 CHECK MARK */ #define XKB_KEY_ballotcross 0x0af4 /* U+2717 BALLOT X */ #define XKB_KEY_musicalsharp 0x0af5 /* U+266F MUSIC SHARP SIGN */ #define XKB_KEY_musicalflat 0x0af6 /* U+266D MUSIC FLAT SIGN */ #define XKB_KEY_malesymbol 0x0af7 /* U+2642 MALE SIGN */ #define XKB_KEY_femalesymbol 0x0af8 /* U+2640 FEMALE SIGN */ #define XKB_KEY_telephone 0x0af9 /* U+260E BLACK TELEPHONE */ #define XKB_KEY_telephonerecorder 0x0afa /* U+2315 TELEPHONE RECORDER */ #define XKB_KEY_phonographcopyright 0x0afb /* U+2117 SOUND RECORDING COPYRIGHT */ #define XKB_KEY_caret 0x0afc /* U+2038 CARET */ #define XKB_KEY_singlelowquotemark 0x0afd /* U+201A SINGLE LOW-9 QUOTATION MARK */ #define XKB_KEY_doublelowquotemark 0x0afe /* U+201E DOUBLE LOW-9 QUOTATION MARK */ #define XKB_KEY_cursor 0x0aff /* * APL * Byte 3 = 0x0b */ #define XKB_KEY_leftcaret 0x0ba3 /*(U+003C LESS-THAN SIGN)*/ #define XKB_KEY_rightcaret 0x0ba6 /*(U+003E GREATER-THAN SIGN)*/ #define XKB_KEY_downcaret 0x0ba8 /*(U+2228 LOGICAL OR)*/ #define XKB_KEY_upcaret 0x0ba9 /*(U+2227 LOGICAL AND)*/ #define XKB_KEY_overbar 0x0bc0 /*(U+00AF MACRON)*/ #define XKB_KEY_downtack 0x0bc2 /* U+22A4 DOWN TACK */ #define XKB_KEY_upshoe 0x0bc3 /*(U+2229 INTERSECTION)*/ #define XKB_KEY_downstile 0x0bc4 /* U+230A LEFT FLOOR */ #define XKB_KEY_underbar 0x0bc6 /*(U+005F LOW LINE)*/ #define XKB_KEY_jot 0x0bca /* U+2218 RING OPERATOR */ #define XKB_KEY_quad 0x0bcc /* U+2395 APL FUNCTIONAL SYMBOL QUAD */ #define XKB_KEY_uptack 0x0bce /* U+22A5 UP TACK */ #define XKB_KEY_circle 0x0bcf /* U+25CB WHITE CIRCLE */ #define XKB_KEY_upstile 0x0bd3 /* U+2308 LEFT CEILING */ #define XKB_KEY_downshoe 0x0bd6 /*(U+222A UNION)*/ #define XKB_KEY_rightshoe 0x0bd8 /*(U+2283 SUPERSET OF)*/ #define XKB_KEY_leftshoe 0x0bda /*(U+2282 SUBSET OF)*/ #define XKB_KEY_lefttack 0x0bdc /* U+22A3 LEFT TACK */ #define XKB_KEY_righttack 0x0bfc /* U+22A2 RIGHT TACK */ /* * Hebrew * Byte 3 = 0x0c */ #define XKB_KEY_hebrew_doublelowline 0x0cdf /* U+2017 DOUBLE LOW LINE */ #define XKB_KEY_hebrew_aleph 0x0ce0 /* U+05D0 HEBREW LETTER ALEF */ #define XKB_KEY_hebrew_bet 0x0ce1 /* U+05D1 HEBREW LETTER BET */ #define XKB_KEY_hebrew_beth 0x0ce1 /* deprecated */ #define XKB_KEY_hebrew_gimel 0x0ce2 /* U+05D2 HEBREW LETTER GIMEL */ #define XKB_KEY_hebrew_gimmel 0x0ce2 /* deprecated */ #define XKB_KEY_hebrew_dalet 0x0ce3 /* U+05D3 HEBREW LETTER DALET */ #define XKB_KEY_hebrew_daleth 0x0ce3 /* deprecated */ #define XKB_KEY_hebrew_he 0x0ce4 /* U+05D4 HEBREW LETTER HE */ #define XKB_KEY_hebrew_waw 0x0ce5 /* U+05D5 HEBREW LETTER VAV */ #define XKB_KEY_hebrew_zain 0x0ce6 /* U+05D6 HEBREW LETTER ZAYIN */ #define XKB_KEY_hebrew_zayin 0x0ce6 /* deprecated */ #define XKB_KEY_hebrew_chet 0x0ce7 /* U+05D7 HEBREW LETTER HET */ #define XKB_KEY_hebrew_het 0x0ce7 /* deprecated */ #define XKB_KEY_hebrew_tet 0x0ce8 /* U+05D8 HEBREW LETTER TET */ #define XKB_KEY_hebrew_teth 0x0ce8 /* deprecated */ #define XKB_KEY_hebrew_yod 0x0ce9 /* U+05D9 HEBREW LETTER YOD */ #define XKB_KEY_hebrew_finalkaph 0x0cea /* U+05DA HEBREW LETTER FINAL KAF */ #define XKB_KEY_hebrew_kaph 0x0ceb /* U+05DB HEBREW LETTER KAF */ #define XKB_KEY_hebrew_lamed 0x0cec /* U+05DC HEBREW LETTER LAMED */ #define XKB_KEY_hebrew_finalmem 0x0ced /* U+05DD HEBREW LETTER FINAL MEM */ #define XKB_KEY_hebrew_mem 0x0cee /* U+05DE HEBREW LETTER MEM */ #define XKB_KEY_hebrew_finalnun 0x0cef /* U+05DF HEBREW LETTER FINAL NUN */ #define XKB_KEY_hebrew_nun 0x0cf0 /* U+05E0 HEBREW LETTER NUN */ #define XKB_KEY_hebrew_samech 0x0cf1 /* U+05E1 HEBREW LETTER SAMEKH */ #define XKB_KEY_hebrew_samekh 0x0cf1 /* deprecated */ #define XKB_KEY_hebrew_ayin 0x0cf2 /* U+05E2 HEBREW LETTER AYIN */ #define XKB_KEY_hebrew_finalpe 0x0cf3 /* U+05E3 HEBREW LETTER FINAL PE */ #define XKB_KEY_hebrew_pe 0x0cf4 /* U+05E4 HEBREW LETTER PE */ #define XKB_KEY_hebrew_finalzade 0x0cf5 /* U+05E5 HEBREW LETTER FINAL TSADI */ #define XKB_KEY_hebrew_finalzadi 0x0cf5 /* deprecated */ #define XKB_KEY_hebrew_zade 0x0cf6 /* U+05E6 HEBREW LETTER TSADI */ #define XKB_KEY_hebrew_zadi 0x0cf6 /* deprecated */ #define XKB_KEY_hebrew_qoph 0x0cf7 /* U+05E7 HEBREW LETTER QOF */ #define XKB_KEY_hebrew_kuf 0x0cf7 /* deprecated */ #define XKB_KEY_hebrew_resh 0x0cf8 /* U+05E8 HEBREW LETTER RESH */ #define XKB_KEY_hebrew_shin 0x0cf9 /* U+05E9 HEBREW LETTER SHIN */ #define XKB_KEY_hebrew_taw 0x0cfa /* U+05EA HEBREW LETTER TAV */ #define XKB_KEY_hebrew_taf 0x0cfa /* deprecated */ #define XKB_KEY_Hebrew_switch 0xff7e /* non-deprecated alias for Mode_switch */ /* * Thai * Byte 3 = 0x0d */ #define XKB_KEY_Thai_kokai 0x0da1 /* U+0E01 THAI CHARACTER KO KAI */ #define XKB_KEY_Thai_khokhai 0x0da2 /* U+0E02 THAI CHARACTER KHO KHAI */ #define XKB_KEY_Thai_khokhuat 0x0da3 /* U+0E03 THAI CHARACTER KHO KHUAT */ #define XKB_KEY_Thai_khokhwai 0x0da4 /* U+0E04 THAI CHARACTER KHO KHWAI */ #define XKB_KEY_Thai_khokhon 0x0da5 /* U+0E05 THAI CHARACTER KHO KHON */ #define XKB_KEY_Thai_khorakhang 0x0da6 /* U+0E06 THAI CHARACTER KHO RAKHANG */ #define XKB_KEY_Thai_ngongu 0x0da7 /* U+0E07 THAI CHARACTER NGO NGU */ #define XKB_KEY_Thai_chochan 0x0da8 /* U+0E08 THAI CHARACTER CHO CHAN */ #define XKB_KEY_Thai_choching 0x0da9 /* U+0E09 THAI CHARACTER CHO CHING */ #define XKB_KEY_Thai_chochang 0x0daa /* U+0E0A THAI CHARACTER CHO CHANG */ #define XKB_KEY_Thai_soso 0x0dab /* U+0E0B THAI CHARACTER SO SO */ #define XKB_KEY_Thai_chochoe 0x0dac /* U+0E0C THAI CHARACTER CHO CHOE */ #define XKB_KEY_Thai_yoying 0x0dad /* U+0E0D THAI CHARACTER YO YING */ #define XKB_KEY_Thai_dochada 0x0dae /* U+0E0E THAI CHARACTER DO CHADA */ #define XKB_KEY_Thai_topatak 0x0daf /* U+0E0F THAI CHARACTER TO PATAK */ #define XKB_KEY_Thai_thothan 0x0db0 /* U+0E10 THAI CHARACTER THO THAN */ #define XKB_KEY_Thai_thonangmontho 0x0db1 /* U+0E11 THAI CHARACTER THO NANGMONTHO */ #define XKB_KEY_Thai_thophuthao 0x0db2 /* U+0E12 THAI CHARACTER THO PHUTHAO */ #define XKB_KEY_Thai_nonen 0x0db3 /* U+0E13 THAI CHARACTER NO NEN */ #define XKB_KEY_Thai_dodek 0x0db4 /* U+0E14 THAI CHARACTER DO DEK */ #define XKB_KEY_Thai_totao 0x0db5 /* U+0E15 THAI CHARACTER TO TAO */ #define XKB_KEY_Thai_thothung 0x0db6 /* U+0E16 THAI CHARACTER THO THUNG */ #define XKB_KEY_Thai_thothahan 0x0db7 /* U+0E17 THAI CHARACTER THO THAHAN */ #define XKB_KEY_Thai_thothong 0x0db8 /* U+0E18 THAI CHARACTER THO THONG */ #define XKB_KEY_Thai_nonu 0x0db9 /* U+0E19 THAI CHARACTER NO NU */ #define XKB_KEY_Thai_bobaimai 0x0dba /* U+0E1A THAI CHARACTER BO BAIMAI */ #define XKB_KEY_Thai_popla 0x0dbb /* U+0E1B THAI CHARACTER PO PLA */ #define XKB_KEY_Thai_phophung 0x0dbc /* U+0E1C THAI CHARACTER PHO PHUNG */ #define XKB_KEY_Thai_fofa 0x0dbd /* U+0E1D THAI CHARACTER FO FA */ #define XKB_KEY_Thai_phophan 0x0dbe /* U+0E1E THAI CHARACTER PHO PHAN */ #define XKB_KEY_Thai_fofan 0x0dbf /* U+0E1F THAI CHARACTER FO FAN */ #define XKB_KEY_Thai_phosamphao 0x0dc0 /* U+0E20 THAI CHARACTER PHO SAMPHAO */ #define XKB_KEY_Thai_moma 0x0dc1 /* U+0E21 THAI CHARACTER MO MA */ #define XKB_KEY_Thai_yoyak 0x0dc2 /* U+0E22 THAI CHARACTER YO YAK */ #define XKB_KEY_Thai_rorua 0x0dc3 /* U+0E23 THAI CHARACTER RO RUA */ #define XKB_KEY_Thai_ru 0x0dc4 /* U+0E24 THAI CHARACTER RU */ #define XKB_KEY_Thai_loling 0x0dc5 /* U+0E25 THAI CHARACTER LO LING */ #define XKB_KEY_Thai_lu 0x0dc6 /* U+0E26 THAI CHARACTER LU */ #define XKB_KEY_Thai_wowaen 0x0dc7 /* U+0E27 THAI CHARACTER WO WAEN */ #define XKB_KEY_Thai_sosala 0x0dc8 /* U+0E28 THAI CHARACTER SO SALA */ #define XKB_KEY_Thai_sorusi 0x0dc9 /* U+0E29 THAI CHARACTER SO RUSI */ #define XKB_KEY_Thai_sosua 0x0dca /* U+0E2A THAI CHARACTER SO SUA */ #define XKB_KEY_Thai_hohip 0x0dcb /* U+0E2B THAI CHARACTER HO HIP */ #define XKB_KEY_Thai_lochula 0x0dcc /* U+0E2C THAI CHARACTER LO CHULA */ #define XKB_KEY_Thai_oang 0x0dcd /* U+0E2D THAI CHARACTER O ANG */ #define XKB_KEY_Thai_honokhuk 0x0dce /* U+0E2E THAI CHARACTER HO NOKHUK */ #define XKB_KEY_Thai_paiyannoi 0x0dcf /* U+0E2F THAI CHARACTER PAIYANNOI */ #define XKB_KEY_Thai_saraa 0x0dd0 /* U+0E30 THAI CHARACTER SARA A */ #define XKB_KEY_Thai_maihanakat 0x0dd1 /* U+0E31 THAI CHARACTER MAI HAN-AKAT */ #define XKB_KEY_Thai_saraaa 0x0dd2 /* U+0E32 THAI CHARACTER SARA AA */ #define XKB_KEY_Thai_saraam 0x0dd3 /* U+0E33 THAI CHARACTER SARA AM */ #define XKB_KEY_Thai_sarai 0x0dd4 /* U+0E34 THAI CHARACTER SARA I */ #define XKB_KEY_Thai_saraii 0x0dd5 /* U+0E35 THAI CHARACTER SARA II */ #define XKB_KEY_Thai_saraue 0x0dd6 /* U+0E36 THAI CHARACTER SARA UE */ #define XKB_KEY_Thai_sarauee 0x0dd7 /* U+0E37 THAI CHARACTER SARA UEE */ #define XKB_KEY_Thai_sarau 0x0dd8 /* U+0E38 THAI CHARACTER SARA U */ #define XKB_KEY_Thai_sarauu 0x0dd9 /* U+0E39 THAI CHARACTER SARA UU */ #define XKB_KEY_Thai_phinthu 0x0dda /* U+0E3A THAI CHARACTER PHINTHU */ #define XKB_KEY_Thai_maihanakat_maitho 0x0dde /*(U+0E3E Unassigned code point)*/ #define XKB_KEY_Thai_baht 0x0ddf /* U+0E3F THAI CURRENCY SYMBOL BAHT */ #define XKB_KEY_Thai_sarae 0x0de0 /* U+0E40 THAI CHARACTER SARA E */ #define XKB_KEY_Thai_saraae 0x0de1 /* U+0E41 THAI CHARACTER SARA AE */ #define XKB_KEY_Thai_sarao 0x0de2 /* U+0E42 THAI CHARACTER SARA O */ #define XKB_KEY_Thai_saraaimaimuan 0x0de3 /* U+0E43 THAI CHARACTER SARA AI MAIMUAN */ #define XKB_KEY_Thai_saraaimaimalai 0x0de4 /* U+0E44 THAI CHARACTER SARA AI MAIMALAI */ #define XKB_KEY_Thai_lakkhangyao 0x0de5 /* U+0E45 THAI CHARACTER LAKKHANGYAO */ #define XKB_KEY_Thai_maiyamok 0x0de6 /* U+0E46 THAI CHARACTER MAIYAMOK */ #define XKB_KEY_Thai_maitaikhu 0x0de7 /* U+0E47 THAI CHARACTER MAITAIKHU */ #define XKB_KEY_Thai_maiek 0x0de8 /* U+0E48 THAI CHARACTER MAI EK */ #define XKB_KEY_Thai_maitho 0x0de9 /* U+0E49 THAI CHARACTER MAI THO */ #define XKB_KEY_Thai_maitri 0x0dea /* U+0E4A THAI CHARACTER MAI TRI */ #define XKB_KEY_Thai_maichattawa 0x0deb /* U+0E4B THAI CHARACTER MAI CHATTAWA */ #define XKB_KEY_Thai_thanthakhat 0x0dec /* U+0E4C THAI CHARACTER THANTHAKHAT */ #define XKB_KEY_Thai_nikhahit 0x0ded /* U+0E4D THAI CHARACTER NIKHAHIT */ #define XKB_KEY_Thai_leksun 0x0df0 /* U+0E50 THAI DIGIT ZERO */ #define XKB_KEY_Thai_leknung 0x0df1 /* U+0E51 THAI DIGIT ONE */ #define XKB_KEY_Thai_leksong 0x0df2 /* U+0E52 THAI DIGIT TWO */ #define XKB_KEY_Thai_leksam 0x0df3 /* U+0E53 THAI DIGIT THREE */ #define XKB_KEY_Thai_leksi 0x0df4 /* U+0E54 THAI DIGIT FOUR */ #define XKB_KEY_Thai_lekha 0x0df5 /* U+0E55 THAI DIGIT FIVE */ #define XKB_KEY_Thai_lekhok 0x0df6 /* U+0E56 THAI DIGIT SIX */ #define XKB_KEY_Thai_lekchet 0x0df7 /* U+0E57 THAI DIGIT SEVEN */ #define XKB_KEY_Thai_lekpaet 0x0df8 /* U+0E58 THAI DIGIT EIGHT */ #define XKB_KEY_Thai_lekkao 0x0df9 /* U+0E59 THAI DIGIT NINE */ /* * Korean * Byte 3 = 0x0e */ #define XKB_KEY_Hangul 0xff31 /* Hangul start/stop(toggle) */ #define XKB_KEY_Hangul_Start 0xff32 /* Hangul start */ #define XKB_KEY_Hangul_End 0xff33 /* Hangul end, English start */ #define XKB_KEY_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */ #define XKB_KEY_Hangul_Jamo 0xff35 /* Hangul Jamo mode */ #define XKB_KEY_Hangul_Romaja 0xff36 /* Hangul Romaja mode */ #define XKB_KEY_Hangul_Codeinput 0xff37 /* Hangul code input mode */ #define XKB_KEY_Hangul_Jeonja 0xff38 /* Jeonja mode */ #define XKB_KEY_Hangul_Banja 0xff39 /* Banja mode */ #define XKB_KEY_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */ #define XKB_KEY_Hangul_PostHanja 0xff3b /* Post Hanja conversion */ #define XKB_KEY_Hangul_SingleCandidate 0xff3c /* Single candidate */ #define XKB_KEY_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */ #define XKB_KEY_Hangul_PreviousCandidate 0xff3e /* Previous candidate */ #define XKB_KEY_Hangul_Special 0xff3f /* Special symbols */ #define XKB_KEY_Hangul_switch 0xff7e /* non-deprecated alias for Mode_switch */ /* Hangul Consonant Characters */ #define XKB_KEY_Hangul_Kiyeog 0x0ea1 /* U+3131 HANGUL LETTER KIYEOK */ #define XKB_KEY_Hangul_SsangKiyeog 0x0ea2 /* U+3132 HANGUL LETTER SSANGKIYEOK */ #define XKB_KEY_Hangul_KiyeogSios 0x0ea3 /* U+3133 HANGUL LETTER KIYEOK-SIOS */ #define XKB_KEY_Hangul_Nieun 0x0ea4 /* U+3134 HANGUL LETTER NIEUN */ #define XKB_KEY_Hangul_NieunJieuj 0x0ea5 /* U+3135 HANGUL LETTER NIEUN-CIEUC */ #define XKB_KEY_Hangul_NieunHieuh 0x0ea6 /* U+3136 HANGUL LETTER NIEUN-HIEUH */ #define XKB_KEY_Hangul_Dikeud 0x0ea7 /* U+3137 HANGUL LETTER TIKEUT */ #define XKB_KEY_Hangul_SsangDikeud 0x0ea8 /* U+3138 HANGUL LETTER SSANGTIKEUT */ #define XKB_KEY_Hangul_Rieul 0x0ea9 /* U+3139 HANGUL LETTER RIEUL */ #define XKB_KEY_Hangul_RieulKiyeog 0x0eaa /* U+313A HANGUL LETTER RIEUL-KIYEOK */ #define XKB_KEY_Hangul_RieulMieum 0x0eab /* U+313B HANGUL LETTER RIEUL-MIEUM */ #define XKB_KEY_Hangul_RieulPieub 0x0eac /* U+313C HANGUL LETTER RIEUL-PIEUP */ #define XKB_KEY_Hangul_RieulSios 0x0ead /* U+313D HANGUL LETTER RIEUL-SIOS */ #define XKB_KEY_Hangul_RieulTieut 0x0eae /* U+313E HANGUL LETTER RIEUL-THIEUTH */ #define XKB_KEY_Hangul_RieulPhieuf 0x0eaf /* U+313F HANGUL LETTER RIEUL-PHIEUPH */ #define XKB_KEY_Hangul_RieulHieuh 0x0eb0 /* U+3140 HANGUL LETTER RIEUL-HIEUH */ #define XKB_KEY_Hangul_Mieum 0x0eb1 /* U+3141 HANGUL LETTER MIEUM */ #define XKB_KEY_Hangul_Pieub 0x0eb2 /* U+3142 HANGUL LETTER PIEUP */ #define XKB_KEY_Hangul_SsangPieub 0x0eb3 /* U+3143 HANGUL LETTER SSANGPIEUP */ #define XKB_KEY_Hangul_PieubSios 0x0eb4 /* U+3144 HANGUL LETTER PIEUP-SIOS */ #define XKB_KEY_Hangul_Sios 0x0eb5 /* U+3145 HANGUL LETTER SIOS */ #define XKB_KEY_Hangul_SsangSios 0x0eb6 /* U+3146 HANGUL LETTER SSANGSIOS */ #define XKB_KEY_Hangul_Ieung 0x0eb7 /* U+3147 HANGUL LETTER IEUNG */ #define XKB_KEY_Hangul_Jieuj 0x0eb8 /* U+3148 HANGUL LETTER CIEUC */ #define XKB_KEY_Hangul_SsangJieuj 0x0eb9 /* U+3149 HANGUL LETTER SSANGCIEUC */ #define XKB_KEY_Hangul_Cieuc 0x0eba /* U+314A HANGUL LETTER CHIEUCH */ #define XKB_KEY_Hangul_Khieuq 0x0ebb /* U+314B HANGUL LETTER KHIEUKH */ #define XKB_KEY_Hangul_Tieut 0x0ebc /* U+314C HANGUL LETTER THIEUTH */ #define XKB_KEY_Hangul_Phieuf 0x0ebd /* U+314D HANGUL LETTER PHIEUPH */ #define XKB_KEY_Hangul_Hieuh 0x0ebe /* U+314E HANGUL LETTER HIEUH */ /* Hangul Vowel Characters */ #define XKB_KEY_Hangul_A 0x0ebf /* U+314F HANGUL LETTER A */ #define XKB_KEY_Hangul_AE 0x0ec0 /* U+3150 HANGUL LETTER AE */ #define XKB_KEY_Hangul_YA 0x0ec1 /* U+3151 HANGUL LETTER YA */ #define XKB_KEY_Hangul_YAE 0x0ec2 /* U+3152 HANGUL LETTER YAE */ #define XKB_KEY_Hangul_EO 0x0ec3 /* U+3153 HANGUL LETTER EO */ #define XKB_KEY_Hangul_E 0x0ec4 /* U+3154 HANGUL LETTER E */ #define XKB_KEY_Hangul_YEO 0x0ec5 /* U+3155 HANGUL LETTER YEO */ #define XKB_KEY_Hangul_YE 0x0ec6 /* U+3156 HANGUL LETTER YE */ #define XKB_KEY_Hangul_O 0x0ec7 /* U+3157 HANGUL LETTER O */ #define XKB_KEY_Hangul_WA 0x0ec8 /* U+3158 HANGUL LETTER WA */ #define XKB_KEY_Hangul_WAE 0x0ec9 /* U+3159 HANGUL LETTER WAE */ #define XKB_KEY_Hangul_OE 0x0eca /* U+315A HANGUL LETTER OE */ #define XKB_KEY_Hangul_YO 0x0ecb /* U+315B HANGUL LETTER YO */ #define XKB_KEY_Hangul_U 0x0ecc /* U+315C HANGUL LETTER U */ #define XKB_KEY_Hangul_WEO 0x0ecd /* U+315D HANGUL LETTER WEO */ #define XKB_KEY_Hangul_WE 0x0ece /* U+315E HANGUL LETTER WE */ #define XKB_KEY_Hangul_WI 0x0ecf /* U+315F HANGUL LETTER WI */ #define XKB_KEY_Hangul_YU 0x0ed0 /* U+3160 HANGUL LETTER YU */ #define XKB_KEY_Hangul_EU 0x0ed1 /* U+3161 HANGUL LETTER EU */ #define XKB_KEY_Hangul_YI 0x0ed2 /* U+3162 HANGUL LETTER YI */ #define XKB_KEY_Hangul_I 0x0ed3 /* U+3163 HANGUL LETTER I */ /* Hangul syllable-final (JongSeong) Characters */ #define XKB_KEY_Hangul_J_Kiyeog 0x0ed4 /* U+11A8 HANGUL JONGSEONG KIYEOK */ #define XKB_KEY_Hangul_J_SsangKiyeog 0x0ed5 /* U+11A9 HANGUL JONGSEONG SSANGKIYEOK */ #define XKB_KEY_Hangul_J_KiyeogSios 0x0ed6 /* U+11AA HANGUL JONGSEONG KIYEOK-SIOS */ #define XKB_KEY_Hangul_J_Nieun 0x0ed7 /* U+11AB HANGUL JONGSEONG NIEUN */ #define XKB_KEY_Hangul_J_NieunJieuj 0x0ed8 /* U+11AC HANGUL JONGSEONG NIEUN-CIEUC */ #define XKB_KEY_Hangul_J_NieunHieuh 0x0ed9 /* U+11AD HANGUL JONGSEONG NIEUN-HIEUH */ #define XKB_KEY_Hangul_J_Dikeud 0x0eda /* U+11AE HANGUL JONGSEONG TIKEUT */ #define XKB_KEY_Hangul_J_Rieul 0x0edb /* U+11AF HANGUL JONGSEONG RIEUL */ #define XKB_KEY_Hangul_J_RieulKiyeog 0x0edc /* U+11B0 HANGUL JONGSEONG RIEUL-KIYEOK */ #define XKB_KEY_Hangul_J_RieulMieum 0x0edd /* U+11B1 HANGUL JONGSEONG RIEUL-MIEUM */ #define XKB_KEY_Hangul_J_RieulPieub 0x0ede /* U+11B2 HANGUL JONGSEONG RIEUL-PIEUP */ #define XKB_KEY_Hangul_J_RieulSios 0x0edf /* U+11B3 HANGUL JONGSEONG RIEUL-SIOS */ #define XKB_KEY_Hangul_J_RieulTieut 0x0ee0 /* U+11B4 HANGUL JONGSEONG RIEUL-THIEUTH */ #define XKB_KEY_Hangul_J_RieulPhieuf 0x0ee1 /* U+11B5 HANGUL JONGSEONG RIEUL-PHIEUPH */ #define XKB_KEY_Hangul_J_RieulHieuh 0x0ee2 /* U+11B6 HANGUL JONGSEONG RIEUL-HIEUH */ #define XKB_KEY_Hangul_J_Mieum 0x0ee3 /* U+11B7 HANGUL JONGSEONG MIEUM */ #define XKB_KEY_Hangul_J_Pieub 0x0ee4 /* U+11B8 HANGUL JONGSEONG PIEUP */ #define XKB_KEY_Hangul_J_PieubSios 0x0ee5 /* U+11B9 HANGUL JONGSEONG PIEUP-SIOS */ #define XKB_KEY_Hangul_J_Sios 0x0ee6 /* U+11BA HANGUL JONGSEONG SIOS */ #define XKB_KEY_Hangul_J_SsangSios 0x0ee7 /* U+11BB HANGUL JONGSEONG SSANGSIOS */ #define XKB_KEY_Hangul_J_Ieung 0x0ee8 /* U+11BC HANGUL JONGSEONG IEUNG */ #define XKB_KEY_Hangul_J_Jieuj 0x0ee9 /* U+11BD HANGUL JONGSEONG CIEUC */ #define XKB_KEY_Hangul_J_Cieuc 0x0eea /* U+11BE HANGUL JONGSEONG CHIEUCH */ #define XKB_KEY_Hangul_J_Khieuq 0x0eeb /* U+11BF HANGUL JONGSEONG KHIEUKH */ #define XKB_KEY_Hangul_J_Tieut 0x0eec /* U+11C0 HANGUL JONGSEONG THIEUTH */ #define XKB_KEY_Hangul_J_Phieuf 0x0eed /* U+11C1 HANGUL JONGSEONG PHIEUPH */ #define XKB_KEY_Hangul_J_Hieuh 0x0eee /* U+11C2 HANGUL JONGSEONG HIEUH */ /* Ancient Hangul Consonant Characters */ #define XKB_KEY_Hangul_RieulYeorinHieuh 0x0eef /* U+316D HANGUL LETTER RIEUL-YEORINHIEUH */ #define XKB_KEY_Hangul_SunkyeongeumMieum 0x0ef0 /* U+3171 HANGUL LETTER KAPYEOUNMIEUM */ #define XKB_KEY_Hangul_SunkyeongeumPieub 0x0ef1 /* U+3178 HANGUL LETTER KAPYEOUNPIEUP */ #define XKB_KEY_Hangul_PanSios 0x0ef2 /* U+317F HANGUL LETTER PANSIOS */ #define XKB_KEY_Hangul_KkogjiDalrinIeung 0x0ef3 /* U+3181 HANGUL LETTER YESIEUNG */ #define XKB_KEY_Hangul_SunkyeongeumPhieuf 0x0ef4 /* U+3184 HANGUL LETTER KAPYEOUNPHIEUPH */ #define XKB_KEY_Hangul_YeorinHieuh 0x0ef5 /* U+3186 HANGUL LETTER YEORINHIEUH */ /* Ancient Hangul Vowel Characters */ #define XKB_KEY_Hangul_AraeA 0x0ef6 /* U+318D HANGUL LETTER ARAEA */ #define XKB_KEY_Hangul_AraeAE 0x0ef7 /* U+318E HANGUL LETTER ARAEAE */ /* Ancient Hangul syllable-final (JongSeong) Characters */ #define XKB_KEY_Hangul_J_PanSios 0x0ef8 /* U+11EB HANGUL JONGSEONG PANSIOS */ #define XKB_KEY_Hangul_J_KkogjiDalrinIeung 0x0ef9 /* U+11F0 HANGUL JONGSEONG YESIEUNG */ #define XKB_KEY_Hangul_J_YeorinHieuh 0x0efa /* U+11F9 HANGUL JONGSEONG YEORINHIEUH */ /* Korean currency symbol */ #define XKB_KEY_Korean_Won 0x0eff /*(U+20A9 WON SIGN)*/ /* * Armenian */ #define XKB_KEY_Armenian_ligature_ew 0x1000587 /* U+0587 ARMENIAN SMALL LIGATURE ECH YIWN */ #define XKB_KEY_Armenian_full_stop 0x1000589 /* U+0589 ARMENIAN FULL STOP */ #define XKB_KEY_Armenian_verjaket 0x1000589 /* deprecated alias for Armenian_full_stop */ #define XKB_KEY_Armenian_separation_mark 0x100055d /* U+055D ARMENIAN COMMA */ #define XKB_KEY_Armenian_but 0x100055d /* deprecated alias for Armenian_separation_mark */ #define XKB_KEY_Armenian_hyphen 0x100058a /* U+058A ARMENIAN HYPHEN */ #define XKB_KEY_Armenian_yentamna 0x100058a /* deprecated alias for Armenian_hyphen */ #define XKB_KEY_Armenian_exclam 0x100055c /* U+055C ARMENIAN EXCLAMATION MARK */ #define XKB_KEY_Armenian_amanak 0x100055c /* deprecated alias for Armenian_exclam */ #define XKB_KEY_Armenian_accent 0x100055b /* U+055B ARMENIAN EMPHASIS MARK */ #define XKB_KEY_Armenian_shesht 0x100055b /* deprecated alias for Armenian_accent */ #define XKB_KEY_Armenian_question 0x100055e /* U+055E ARMENIAN QUESTION MARK */ #define XKB_KEY_Armenian_paruyk 0x100055e /* deprecated alias for Armenian_question */ #define XKB_KEY_Armenian_AYB 0x1000531 /* U+0531 ARMENIAN CAPITAL LETTER AYB */ #define XKB_KEY_Armenian_ayb 0x1000561 /* U+0561 ARMENIAN SMALL LETTER AYB */ #define XKB_KEY_Armenian_BEN 0x1000532 /* U+0532 ARMENIAN CAPITAL LETTER BEN */ #define XKB_KEY_Armenian_ben 0x1000562 /* U+0562 ARMENIAN SMALL LETTER BEN */ #define XKB_KEY_Armenian_GIM 0x1000533 /* U+0533 ARMENIAN CAPITAL LETTER GIM */ #define XKB_KEY_Armenian_gim 0x1000563 /* U+0563 ARMENIAN SMALL LETTER GIM */ #define XKB_KEY_Armenian_DA 0x1000534 /* U+0534 ARMENIAN CAPITAL LETTER DA */ #define XKB_KEY_Armenian_da 0x1000564 /* U+0564 ARMENIAN SMALL LETTER DA */ #define XKB_KEY_Armenian_YECH 0x1000535 /* U+0535 ARMENIAN CAPITAL LETTER ECH */ #define XKB_KEY_Armenian_yech 0x1000565 /* U+0565 ARMENIAN SMALL LETTER ECH */ #define XKB_KEY_Armenian_ZA 0x1000536 /* U+0536 ARMENIAN CAPITAL LETTER ZA */ #define XKB_KEY_Armenian_za 0x1000566 /* U+0566 ARMENIAN SMALL LETTER ZA */ #define XKB_KEY_Armenian_E 0x1000537 /* U+0537 ARMENIAN CAPITAL LETTER EH */ #define XKB_KEY_Armenian_e 0x1000567 /* U+0567 ARMENIAN SMALL LETTER EH */ #define XKB_KEY_Armenian_AT 0x1000538 /* U+0538 ARMENIAN CAPITAL LETTER ET */ #define XKB_KEY_Armenian_at 0x1000568 /* U+0568 ARMENIAN SMALL LETTER ET */ #define XKB_KEY_Armenian_TO 0x1000539 /* U+0539 ARMENIAN CAPITAL LETTER TO */ #define XKB_KEY_Armenian_to 0x1000569 /* U+0569 ARMENIAN SMALL LETTER TO */ #define XKB_KEY_Armenian_ZHE 0x100053a /* U+053A ARMENIAN CAPITAL LETTER ZHE */ #define XKB_KEY_Armenian_zhe 0x100056a /* U+056A ARMENIAN SMALL LETTER ZHE */ #define XKB_KEY_Armenian_INI 0x100053b /* U+053B ARMENIAN CAPITAL LETTER INI */ #define XKB_KEY_Armenian_ini 0x100056b /* U+056B ARMENIAN SMALL LETTER INI */ #define XKB_KEY_Armenian_LYUN 0x100053c /* U+053C ARMENIAN CAPITAL LETTER LIWN */ #define XKB_KEY_Armenian_lyun 0x100056c /* U+056C ARMENIAN SMALL LETTER LIWN */ #define XKB_KEY_Armenian_KHE 0x100053d /* U+053D ARMENIAN CAPITAL LETTER XEH */ #define XKB_KEY_Armenian_khe 0x100056d /* U+056D ARMENIAN SMALL LETTER XEH */ #define XKB_KEY_Armenian_TSA 0x100053e /* U+053E ARMENIAN CAPITAL LETTER CA */ #define XKB_KEY_Armenian_tsa 0x100056e /* U+056E ARMENIAN SMALL LETTER CA */ #define XKB_KEY_Armenian_KEN 0x100053f /* U+053F ARMENIAN CAPITAL LETTER KEN */ #define XKB_KEY_Armenian_ken 0x100056f /* U+056F ARMENIAN SMALL LETTER KEN */ #define XKB_KEY_Armenian_HO 0x1000540 /* U+0540 ARMENIAN CAPITAL LETTER HO */ #define XKB_KEY_Armenian_ho 0x1000570 /* U+0570 ARMENIAN SMALL LETTER HO */ #define XKB_KEY_Armenian_DZA 0x1000541 /* U+0541 ARMENIAN CAPITAL LETTER JA */ #define XKB_KEY_Armenian_dza 0x1000571 /* U+0571 ARMENIAN SMALL LETTER JA */ #define XKB_KEY_Armenian_GHAT 0x1000542 /* U+0542 ARMENIAN CAPITAL LETTER GHAD */ #define XKB_KEY_Armenian_ghat 0x1000572 /* U+0572 ARMENIAN SMALL LETTER GHAD */ #define XKB_KEY_Armenian_TCHE 0x1000543 /* U+0543 ARMENIAN CAPITAL LETTER CHEH */ #define XKB_KEY_Armenian_tche 0x1000573 /* U+0573 ARMENIAN SMALL LETTER CHEH */ #define XKB_KEY_Armenian_MEN 0x1000544 /* U+0544 ARMENIAN CAPITAL LETTER MEN */ #define XKB_KEY_Armenian_men 0x1000574 /* U+0574 ARMENIAN SMALL LETTER MEN */ #define XKB_KEY_Armenian_HI 0x1000545 /* U+0545 ARMENIAN CAPITAL LETTER YI */ #define XKB_KEY_Armenian_hi 0x1000575 /* U+0575 ARMENIAN SMALL LETTER YI */ #define XKB_KEY_Armenian_NU 0x1000546 /* U+0546 ARMENIAN CAPITAL LETTER NOW */ #define XKB_KEY_Armenian_nu 0x1000576 /* U+0576 ARMENIAN SMALL LETTER NOW */ #define XKB_KEY_Armenian_SHA 0x1000547 /* U+0547 ARMENIAN CAPITAL LETTER SHA */ #define XKB_KEY_Armenian_sha 0x1000577 /* U+0577 ARMENIAN SMALL LETTER SHA */ #define XKB_KEY_Armenian_VO 0x1000548 /* U+0548 ARMENIAN CAPITAL LETTER VO */ #define XKB_KEY_Armenian_vo 0x1000578 /* U+0578 ARMENIAN SMALL LETTER VO */ #define XKB_KEY_Armenian_CHA 0x1000549 /* U+0549 ARMENIAN CAPITAL LETTER CHA */ #define XKB_KEY_Armenian_cha 0x1000579 /* U+0579 ARMENIAN SMALL LETTER CHA */ #define XKB_KEY_Armenian_PE 0x100054a /* U+054A ARMENIAN CAPITAL LETTER PEH */ #define XKB_KEY_Armenian_pe 0x100057a /* U+057A ARMENIAN SMALL LETTER PEH */ #define XKB_KEY_Armenian_JE 0x100054b /* U+054B ARMENIAN CAPITAL LETTER JHEH */ #define XKB_KEY_Armenian_je 0x100057b /* U+057B ARMENIAN SMALL LETTER JHEH */ #define XKB_KEY_Armenian_RA 0x100054c /* U+054C ARMENIAN CAPITAL LETTER RA */ #define XKB_KEY_Armenian_ra 0x100057c /* U+057C ARMENIAN SMALL LETTER RA */ #define XKB_KEY_Armenian_SE 0x100054d /* U+054D ARMENIAN CAPITAL LETTER SEH */ #define XKB_KEY_Armenian_se 0x100057d /* U+057D ARMENIAN SMALL LETTER SEH */ #define XKB_KEY_Armenian_VEV 0x100054e /* U+054E ARMENIAN CAPITAL LETTER VEW */ #define XKB_KEY_Armenian_vev 0x100057e /* U+057E ARMENIAN SMALL LETTER VEW */ #define XKB_KEY_Armenian_TYUN 0x100054f /* U+054F ARMENIAN CAPITAL LETTER TIWN */ #define XKB_KEY_Armenian_tyun 0x100057f /* U+057F ARMENIAN SMALL LETTER TIWN */ #define XKB_KEY_Armenian_RE 0x1000550 /* U+0550 ARMENIAN CAPITAL LETTER REH */ #define XKB_KEY_Armenian_re 0x1000580 /* U+0580 ARMENIAN SMALL LETTER REH */ #define XKB_KEY_Armenian_TSO 0x1000551 /* U+0551 ARMENIAN CAPITAL LETTER CO */ #define XKB_KEY_Armenian_tso 0x1000581 /* U+0581 ARMENIAN SMALL LETTER CO */ #define XKB_KEY_Armenian_VYUN 0x1000552 /* U+0552 ARMENIAN CAPITAL LETTER YIWN */ #define XKB_KEY_Armenian_vyun 0x1000582 /* U+0582 ARMENIAN SMALL LETTER YIWN */ #define XKB_KEY_Armenian_PYUR 0x1000553 /* U+0553 ARMENIAN CAPITAL LETTER PIWR */ #define XKB_KEY_Armenian_pyur 0x1000583 /* U+0583 ARMENIAN SMALL LETTER PIWR */ #define XKB_KEY_Armenian_KE 0x1000554 /* U+0554 ARMENIAN CAPITAL LETTER KEH */ #define XKB_KEY_Armenian_ke 0x1000584 /* U+0584 ARMENIAN SMALL LETTER KEH */ #define XKB_KEY_Armenian_O 0x1000555 /* U+0555 ARMENIAN CAPITAL LETTER OH */ #define XKB_KEY_Armenian_o 0x1000585 /* U+0585 ARMENIAN SMALL LETTER OH */ #define XKB_KEY_Armenian_FE 0x1000556 /* U+0556 ARMENIAN CAPITAL LETTER FEH */ #define XKB_KEY_Armenian_fe 0x1000586 /* U+0586 ARMENIAN SMALL LETTER FEH */ #define XKB_KEY_Armenian_apostrophe 0x100055a /* U+055A ARMENIAN APOSTROPHE */ /* * Georgian */ #define XKB_KEY_Georgian_an 0x10010d0 /* U+10D0 GEORGIAN LETTER AN */ #define XKB_KEY_Georgian_ban 0x10010d1 /* U+10D1 GEORGIAN LETTER BAN */ #define XKB_KEY_Georgian_gan 0x10010d2 /* U+10D2 GEORGIAN LETTER GAN */ #define XKB_KEY_Georgian_don 0x10010d3 /* U+10D3 GEORGIAN LETTER DON */ #define XKB_KEY_Georgian_en 0x10010d4 /* U+10D4 GEORGIAN LETTER EN */ #define XKB_KEY_Georgian_vin 0x10010d5 /* U+10D5 GEORGIAN LETTER VIN */ #define XKB_KEY_Georgian_zen 0x10010d6 /* U+10D6 GEORGIAN LETTER ZEN */ #define XKB_KEY_Georgian_tan 0x10010d7 /* U+10D7 GEORGIAN LETTER TAN */ #define XKB_KEY_Georgian_in 0x10010d8 /* U+10D8 GEORGIAN LETTER IN */ #define XKB_KEY_Georgian_kan 0x10010d9 /* U+10D9 GEORGIAN LETTER KAN */ #define XKB_KEY_Georgian_las 0x10010da /* U+10DA GEORGIAN LETTER LAS */ #define XKB_KEY_Georgian_man 0x10010db /* U+10DB GEORGIAN LETTER MAN */ #define XKB_KEY_Georgian_nar 0x10010dc /* U+10DC GEORGIAN LETTER NAR */ #define XKB_KEY_Georgian_on 0x10010dd /* U+10DD GEORGIAN LETTER ON */ #define XKB_KEY_Georgian_par 0x10010de /* U+10DE GEORGIAN LETTER PAR */ #define XKB_KEY_Georgian_zhar 0x10010df /* U+10DF GEORGIAN LETTER ZHAR */ #define XKB_KEY_Georgian_rae 0x10010e0 /* U+10E0 GEORGIAN LETTER RAE */ #define XKB_KEY_Georgian_san 0x10010e1 /* U+10E1 GEORGIAN LETTER SAN */ #define XKB_KEY_Georgian_tar 0x10010e2 /* U+10E2 GEORGIAN LETTER TAR */ #define XKB_KEY_Georgian_un 0x10010e3 /* U+10E3 GEORGIAN LETTER UN */ #define XKB_KEY_Georgian_phar 0x10010e4 /* U+10E4 GEORGIAN LETTER PHAR */ #define XKB_KEY_Georgian_khar 0x10010e5 /* U+10E5 GEORGIAN LETTER KHAR */ #define XKB_KEY_Georgian_ghan 0x10010e6 /* U+10E6 GEORGIAN LETTER GHAN */ #define XKB_KEY_Georgian_qar 0x10010e7 /* U+10E7 GEORGIAN LETTER QAR */ #define XKB_KEY_Georgian_shin 0x10010e8 /* U+10E8 GEORGIAN LETTER SHIN */ #define XKB_KEY_Georgian_chin 0x10010e9 /* U+10E9 GEORGIAN LETTER CHIN */ #define XKB_KEY_Georgian_can 0x10010ea /* U+10EA GEORGIAN LETTER CAN */ #define XKB_KEY_Georgian_jil 0x10010eb /* U+10EB GEORGIAN LETTER JIL */ #define XKB_KEY_Georgian_cil 0x10010ec /* U+10EC GEORGIAN LETTER CIL */ #define XKB_KEY_Georgian_char 0x10010ed /* U+10ED GEORGIAN LETTER CHAR */ #define XKB_KEY_Georgian_xan 0x10010ee /* U+10EE GEORGIAN LETTER XAN */ #define XKB_KEY_Georgian_jhan 0x10010ef /* U+10EF GEORGIAN LETTER JHAN */ #define XKB_KEY_Georgian_hae 0x10010f0 /* U+10F0 GEORGIAN LETTER HAE */ #define XKB_KEY_Georgian_he 0x10010f1 /* U+10F1 GEORGIAN LETTER HE */ #define XKB_KEY_Georgian_hie 0x10010f2 /* U+10F2 GEORGIAN LETTER HIE */ #define XKB_KEY_Georgian_we 0x10010f3 /* U+10F3 GEORGIAN LETTER WE */ #define XKB_KEY_Georgian_har 0x10010f4 /* U+10F4 GEORGIAN LETTER HAR */ #define XKB_KEY_Georgian_hoe 0x10010f5 /* U+10F5 GEORGIAN LETTER HOE */ #define XKB_KEY_Georgian_fi 0x10010f6 /* U+10F6 GEORGIAN LETTER FI */ /* * Azeri (and other Turkic or Caucasian languages) */ /* latin */ #define XKB_KEY_Xabovedot 0x1001e8a /* U+1E8A LATIN CAPITAL LETTER X WITH DOT ABOVE */ #define XKB_KEY_Ibreve 0x100012c /* U+012C LATIN CAPITAL LETTER I WITH BREVE */ #define XKB_KEY_Zstroke 0x10001b5 /* U+01B5 LATIN CAPITAL LETTER Z WITH STROKE */ #define XKB_KEY_Gcaron 0x10001e6 /* U+01E6 LATIN CAPITAL LETTER G WITH CARON */ #define XKB_KEY_Ocaron 0x10001d1 /* U+01D1 LATIN CAPITAL LETTER O WITH CARON */ #define XKB_KEY_Obarred 0x100019f /* U+019F LATIN CAPITAL LETTER O WITH MIDDLE TILDE */ #define XKB_KEY_xabovedot 0x1001e8b /* U+1E8B LATIN SMALL LETTER X WITH DOT ABOVE */ #define XKB_KEY_ibreve 0x100012d /* U+012D LATIN SMALL LETTER I WITH BREVE */ #define XKB_KEY_zstroke 0x10001b6 /* U+01B6 LATIN SMALL LETTER Z WITH STROKE */ #define XKB_KEY_gcaron 0x10001e7 /* U+01E7 LATIN SMALL LETTER G WITH CARON */ #define XKB_KEY_ocaron 0x10001d2 /* U+01D2 LATIN SMALL LETTER O WITH CARON */ #define XKB_KEY_obarred 0x1000275 /* U+0275 LATIN SMALL LETTER BARRED O */ #define XKB_KEY_SCHWA 0x100018f /* U+018F LATIN CAPITAL LETTER SCHWA */ #define XKB_KEY_schwa 0x1000259 /* U+0259 LATIN SMALL LETTER SCHWA */ #define XKB_KEY_EZH 0x10001b7 /* U+01B7 LATIN CAPITAL LETTER EZH */ #define XKB_KEY_ezh 0x1000292 /* U+0292 LATIN SMALL LETTER EZH */ /* those are not really Caucasus */ /* For Inupiak */ #define XKB_KEY_Lbelowdot 0x1001e36 /* U+1E36 LATIN CAPITAL LETTER L WITH DOT BELOW */ #define XKB_KEY_lbelowdot 0x1001e37 /* U+1E37 LATIN SMALL LETTER L WITH DOT BELOW */ /* * Vietnamese */ #define XKB_KEY_Abelowdot 0x1001ea0 /* U+1EA0 LATIN CAPITAL LETTER A WITH DOT BELOW */ #define XKB_KEY_abelowdot 0x1001ea1 /* U+1EA1 LATIN SMALL LETTER A WITH DOT BELOW */ #define XKB_KEY_Ahook 0x1001ea2 /* U+1EA2 LATIN CAPITAL LETTER A WITH HOOK ABOVE */ #define XKB_KEY_ahook 0x1001ea3 /* U+1EA3 LATIN SMALL LETTER A WITH HOOK ABOVE */ #define XKB_KEY_Acircumflexacute 0x1001ea4 /* U+1EA4 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ #define XKB_KEY_acircumflexacute 0x1001ea5 /* U+1EA5 LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE */ #define XKB_KEY_Acircumflexgrave 0x1001ea6 /* U+1EA6 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ #define XKB_KEY_acircumflexgrave 0x1001ea7 /* U+1EA7 LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE */ #define XKB_KEY_Acircumflexhook 0x1001ea8 /* U+1EA8 LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ #define XKB_KEY_acircumflexhook 0x1001ea9 /* U+1EA9 LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ #define XKB_KEY_Acircumflextilde 0x1001eaa /* U+1EAA LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ #define XKB_KEY_acircumflextilde 0x1001eab /* U+1EAB LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE */ #define XKB_KEY_Acircumflexbelowdot 0x1001eac /* U+1EAC LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ #define XKB_KEY_acircumflexbelowdot 0x1001ead /* U+1EAD LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ #define XKB_KEY_Abreveacute 0x1001eae /* U+1EAE LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ #define XKB_KEY_abreveacute 0x1001eaf /* U+1EAF LATIN SMALL LETTER A WITH BREVE AND ACUTE */ #define XKB_KEY_Abrevegrave 0x1001eb0 /* U+1EB0 LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ #define XKB_KEY_abrevegrave 0x1001eb1 /* U+1EB1 LATIN SMALL LETTER A WITH BREVE AND GRAVE */ #define XKB_KEY_Abrevehook 0x1001eb2 /* U+1EB2 LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ #define XKB_KEY_abrevehook 0x1001eb3 /* U+1EB3 LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE */ #define XKB_KEY_Abrevetilde 0x1001eb4 /* U+1EB4 LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ #define XKB_KEY_abrevetilde 0x1001eb5 /* U+1EB5 LATIN SMALL LETTER A WITH BREVE AND TILDE */ #define XKB_KEY_Abrevebelowdot 0x1001eb6 /* U+1EB6 LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ #define XKB_KEY_abrevebelowdot 0x1001eb7 /* U+1EB7 LATIN SMALL LETTER A WITH BREVE AND DOT BELOW */ #define XKB_KEY_Ebelowdot 0x1001eb8 /* U+1EB8 LATIN CAPITAL LETTER E WITH DOT BELOW */ #define XKB_KEY_ebelowdot 0x1001eb9 /* U+1EB9 LATIN SMALL LETTER E WITH DOT BELOW */ #define XKB_KEY_Ehook 0x1001eba /* U+1EBA LATIN CAPITAL LETTER E WITH HOOK ABOVE */ #define XKB_KEY_ehook 0x1001ebb /* U+1EBB LATIN SMALL LETTER E WITH HOOK ABOVE */ #define XKB_KEY_Etilde 0x1001ebc /* U+1EBC LATIN CAPITAL LETTER E WITH TILDE */ #define XKB_KEY_etilde 0x1001ebd /* U+1EBD LATIN SMALL LETTER E WITH TILDE */ #define XKB_KEY_Ecircumflexacute 0x1001ebe /* U+1EBE LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ #define XKB_KEY_ecircumflexacute 0x1001ebf /* U+1EBF LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE */ #define XKB_KEY_Ecircumflexgrave 0x1001ec0 /* U+1EC0 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ #define XKB_KEY_ecircumflexgrave 0x1001ec1 /* U+1EC1 LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE */ #define XKB_KEY_Ecircumflexhook 0x1001ec2 /* U+1EC2 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ #define XKB_KEY_ecircumflexhook 0x1001ec3 /* U+1EC3 LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ #define XKB_KEY_Ecircumflextilde 0x1001ec4 /* U+1EC4 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ #define XKB_KEY_ecircumflextilde 0x1001ec5 /* U+1EC5 LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE */ #define XKB_KEY_Ecircumflexbelowdot 0x1001ec6 /* U+1EC6 LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ #define XKB_KEY_ecircumflexbelowdot 0x1001ec7 /* U+1EC7 LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ #define XKB_KEY_Ihook 0x1001ec8 /* U+1EC8 LATIN CAPITAL LETTER I WITH HOOK ABOVE */ #define XKB_KEY_ihook 0x1001ec9 /* U+1EC9 LATIN SMALL LETTER I WITH HOOK ABOVE */ #define XKB_KEY_Ibelowdot 0x1001eca /* U+1ECA LATIN CAPITAL LETTER I WITH DOT BELOW */ #define XKB_KEY_ibelowdot 0x1001ecb /* U+1ECB LATIN SMALL LETTER I WITH DOT BELOW */ #define XKB_KEY_Obelowdot 0x1001ecc /* U+1ECC LATIN CAPITAL LETTER O WITH DOT BELOW */ #define XKB_KEY_obelowdot 0x1001ecd /* U+1ECD LATIN SMALL LETTER O WITH DOT BELOW */ #define XKB_KEY_Ohook 0x1001ece /* U+1ECE LATIN CAPITAL LETTER O WITH HOOK ABOVE */ #define XKB_KEY_ohook 0x1001ecf /* U+1ECF LATIN SMALL LETTER O WITH HOOK ABOVE */ #define XKB_KEY_Ocircumflexacute 0x1001ed0 /* U+1ED0 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ #define XKB_KEY_ocircumflexacute 0x1001ed1 /* U+1ED1 LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE */ #define XKB_KEY_Ocircumflexgrave 0x1001ed2 /* U+1ED2 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ #define XKB_KEY_ocircumflexgrave 0x1001ed3 /* U+1ED3 LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE */ #define XKB_KEY_Ocircumflexhook 0x1001ed4 /* U+1ED4 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ #define XKB_KEY_ocircumflexhook 0x1001ed5 /* U+1ED5 LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ #define XKB_KEY_Ocircumflextilde 0x1001ed6 /* U+1ED6 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ #define XKB_KEY_ocircumflextilde 0x1001ed7 /* U+1ED7 LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE */ #define XKB_KEY_Ocircumflexbelowdot 0x1001ed8 /* U+1ED8 LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ #define XKB_KEY_ocircumflexbelowdot 0x1001ed9 /* U+1ED9 LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ #define XKB_KEY_Ohornacute 0x1001eda /* U+1EDA LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ #define XKB_KEY_ohornacute 0x1001edb /* U+1EDB LATIN SMALL LETTER O WITH HORN AND ACUTE */ #define XKB_KEY_Ohorngrave 0x1001edc /* U+1EDC LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ #define XKB_KEY_ohorngrave 0x1001edd /* U+1EDD LATIN SMALL LETTER O WITH HORN AND GRAVE */ #define XKB_KEY_Ohornhook 0x1001ede /* U+1EDE LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ #define XKB_KEY_ohornhook 0x1001edf /* U+1EDF LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE */ #define XKB_KEY_Ohorntilde 0x1001ee0 /* U+1EE0 LATIN CAPITAL LETTER O WITH HORN AND TILDE */ #define XKB_KEY_ohorntilde 0x1001ee1 /* U+1EE1 LATIN SMALL LETTER O WITH HORN AND TILDE */ #define XKB_KEY_Ohornbelowdot 0x1001ee2 /* U+1EE2 LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ #define XKB_KEY_ohornbelowdot 0x1001ee3 /* U+1EE3 LATIN SMALL LETTER O WITH HORN AND DOT BELOW */ #define XKB_KEY_Ubelowdot 0x1001ee4 /* U+1EE4 LATIN CAPITAL LETTER U WITH DOT BELOW */ #define XKB_KEY_ubelowdot 0x1001ee5 /* U+1EE5 LATIN SMALL LETTER U WITH DOT BELOW */ #define XKB_KEY_Uhook 0x1001ee6 /* U+1EE6 LATIN CAPITAL LETTER U WITH HOOK ABOVE */ #define XKB_KEY_uhook 0x1001ee7 /* U+1EE7 LATIN SMALL LETTER U WITH HOOK ABOVE */ #define XKB_KEY_Uhornacute 0x1001ee8 /* U+1EE8 LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ #define XKB_KEY_uhornacute 0x1001ee9 /* U+1EE9 LATIN SMALL LETTER U WITH HORN AND ACUTE */ #define XKB_KEY_Uhorngrave 0x1001eea /* U+1EEA LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ #define XKB_KEY_uhorngrave 0x1001eeb /* U+1EEB LATIN SMALL LETTER U WITH HORN AND GRAVE */ #define XKB_KEY_Uhornhook 0x1001eec /* U+1EEC LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ #define XKB_KEY_uhornhook 0x1001eed /* U+1EED LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE */ #define XKB_KEY_Uhorntilde 0x1001eee /* U+1EEE LATIN CAPITAL LETTER U WITH HORN AND TILDE */ #define XKB_KEY_uhorntilde 0x1001eef /* U+1EEF LATIN SMALL LETTER U WITH HORN AND TILDE */ #define XKB_KEY_Uhornbelowdot 0x1001ef0 /* U+1EF0 LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ #define XKB_KEY_uhornbelowdot 0x1001ef1 /* U+1EF1 LATIN SMALL LETTER U WITH HORN AND DOT BELOW */ #define XKB_KEY_Ybelowdot 0x1001ef4 /* U+1EF4 LATIN CAPITAL LETTER Y WITH DOT BELOW */ #define XKB_KEY_ybelowdot 0x1001ef5 /* U+1EF5 LATIN SMALL LETTER Y WITH DOT BELOW */ #define XKB_KEY_Yhook 0x1001ef6 /* U+1EF6 LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ #define XKB_KEY_yhook 0x1001ef7 /* U+1EF7 LATIN SMALL LETTER Y WITH HOOK ABOVE */ #define XKB_KEY_Ytilde 0x1001ef8 /* U+1EF8 LATIN CAPITAL LETTER Y WITH TILDE */ #define XKB_KEY_ytilde 0x1001ef9 /* U+1EF9 LATIN SMALL LETTER Y WITH TILDE */ #define XKB_KEY_Ohorn 0x10001a0 /* U+01A0 LATIN CAPITAL LETTER O WITH HORN */ #define XKB_KEY_ohorn 0x10001a1 /* U+01A1 LATIN SMALL LETTER O WITH HORN */ #define XKB_KEY_Uhorn 0x10001af /* U+01AF LATIN CAPITAL LETTER U WITH HORN */ #define XKB_KEY_uhorn 0x10001b0 /* U+01B0 LATIN SMALL LETTER U WITH HORN */ #define XKB_KEY_combining_tilde 0x1000303 /* U+0303 COMBINING TILDE */ #define XKB_KEY_combining_grave 0x1000300 /* U+0300 COMBINING GRAVE ACCENT */ #define XKB_KEY_combining_acute 0x1000301 /* U+0301 COMBINING ACUTE ACCENT */ #define XKB_KEY_combining_hook 0x1000309 /* U+0309 COMBINING HOOK ABOVE */ #define XKB_KEY_combining_belowdot 0x1000323 /* U+0323 COMBINING DOT BELOW */ #define XKB_KEY_EcuSign 0x10020a0 /* U+20A0 EURO-CURRENCY SIGN */ #define XKB_KEY_ColonSign 0x10020a1 /* U+20A1 COLON SIGN */ #define XKB_KEY_CruzeiroSign 0x10020a2 /* U+20A2 CRUZEIRO SIGN */ #define XKB_KEY_FFrancSign 0x10020a3 /* U+20A3 FRENCH FRANC SIGN */ #define XKB_KEY_LiraSign 0x10020a4 /* U+20A4 LIRA SIGN */ #define XKB_KEY_MillSign 0x10020a5 /* U+20A5 MILL SIGN */ #define XKB_KEY_NairaSign 0x10020a6 /* U+20A6 NAIRA SIGN */ #define XKB_KEY_PesetaSign 0x10020a7 /* U+20A7 PESETA SIGN */ #define XKB_KEY_RupeeSign 0x10020a8 /* U+20A8 RUPEE SIGN */ #define XKB_KEY_WonSign 0x10020a9 /* U+20A9 WON SIGN */ #define XKB_KEY_NewSheqelSign 0x10020aa /* U+20AA NEW SHEQEL SIGN */ #define XKB_KEY_DongSign 0x10020ab /* U+20AB DONG SIGN */ #define XKB_KEY_EuroSign 0x20ac /* U+20AC EURO SIGN */ /* one, two and three are defined above. */ #define XKB_KEY_zerosuperior 0x1002070 /* U+2070 SUPERSCRIPT ZERO */ #define XKB_KEY_foursuperior 0x1002074 /* U+2074 SUPERSCRIPT FOUR */ #define XKB_KEY_fivesuperior 0x1002075 /* U+2075 SUPERSCRIPT FIVE */ #define XKB_KEY_sixsuperior 0x1002076 /* U+2076 SUPERSCRIPT SIX */ #define XKB_KEY_sevensuperior 0x1002077 /* U+2077 SUPERSCRIPT SEVEN */ #define XKB_KEY_eightsuperior 0x1002078 /* U+2078 SUPERSCRIPT EIGHT */ #define XKB_KEY_ninesuperior 0x1002079 /* U+2079 SUPERSCRIPT NINE */ #define XKB_KEY_zerosubscript 0x1002080 /* U+2080 SUBSCRIPT ZERO */ #define XKB_KEY_onesubscript 0x1002081 /* U+2081 SUBSCRIPT ONE */ #define XKB_KEY_twosubscript 0x1002082 /* U+2082 SUBSCRIPT TWO */ #define XKB_KEY_threesubscript 0x1002083 /* U+2083 SUBSCRIPT THREE */ #define XKB_KEY_foursubscript 0x1002084 /* U+2084 SUBSCRIPT FOUR */ #define XKB_KEY_fivesubscript 0x1002085 /* U+2085 SUBSCRIPT FIVE */ #define XKB_KEY_sixsubscript 0x1002086 /* U+2086 SUBSCRIPT SIX */ #define XKB_KEY_sevensubscript 0x1002087 /* U+2087 SUBSCRIPT SEVEN */ #define XKB_KEY_eightsubscript 0x1002088 /* U+2088 SUBSCRIPT EIGHT */ #define XKB_KEY_ninesubscript 0x1002089 /* U+2089 SUBSCRIPT NINE */ #define XKB_KEY_partdifferential 0x1002202 /* U+2202 PARTIAL DIFFERENTIAL */ #define XKB_KEY_emptyset 0x1002205 /* U+2205 EMPTY SET */ #define XKB_KEY_elementof 0x1002208 /* U+2208 ELEMENT OF */ #define XKB_KEY_notelementof 0x1002209 /* U+2209 NOT AN ELEMENT OF */ #define XKB_KEY_containsas 0x100220b /* U+220B CONTAINS AS MEMBER */ #define XKB_KEY_squareroot 0x100221a /* U+221A SQUARE ROOT */ #define XKB_KEY_cuberoot 0x100221b /* U+221B CUBE ROOT */ #define XKB_KEY_fourthroot 0x100221c /* U+221C FOURTH ROOT */ #define XKB_KEY_dintegral 0x100222c /* U+222C DOUBLE INTEGRAL */ #define XKB_KEY_tintegral 0x100222d /* U+222D TRIPLE INTEGRAL */ #define XKB_KEY_because 0x1002235 /* U+2235 BECAUSE */ #define XKB_KEY_approxeq 0x1002248 /*(U+2248 ALMOST EQUAL TO)*/ #define XKB_KEY_notapproxeq 0x1002247 /*(U+2247 NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO)*/ #define XKB_KEY_notidentical 0x1002262 /* U+2262 NOT IDENTICAL TO */ #define XKB_KEY_stricteq 0x1002263 /* U+2263 STRICTLY EQUIVALENT TO */ #define XKB_KEY_braille_dot_1 0xfff1 #define XKB_KEY_braille_dot_2 0xfff2 #define XKB_KEY_braille_dot_3 0xfff3 #define XKB_KEY_braille_dot_4 0xfff4 #define XKB_KEY_braille_dot_5 0xfff5 #define XKB_KEY_braille_dot_6 0xfff6 #define XKB_KEY_braille_dot_7 0xfff7 #define XKB_KEY_braille_dot_8 0xfff8 #define XKB_KEY_braille_dot_9 0xfff9 #define XKB_KEY_braille_dot_10 0xfffa #define XKB_KEY_braille_blank 0x1002800 /* U+2800 BRAILLE PATTERN BLANK */ #define XKB_KEY_braille_dots_1 0x1002801 /* U+2801 BRAILLE PATTERN DOTS-1 */ #define XKB_KEY_braille_dots_2 0x1002802 /* U+2802 BRAILLE PATTERN DOTS-2 */ #define XKB_KEY_braille_dots_12 0x1002803 /* U+2803 BRAILLE PATTERN DOTS-12 */ #define XKB_KEY_braille_dots_3 0x1002804 /* U+2804 BRAILLE PATTERN DOTS-3 */ #define XKB_KEY_braille_dots_13 0x1002805 /* U+2805 BRAILLE PATTERN DOTS-13 */ #define XKB_KEY_braille_dots_23 0x1002806 /* U+2806 BRAILLE PATTERN DOTS-23 */ #define XKB_KEY_braille_dots_123 0x1002807 /* U+2807 BRAILLE PATTERN DOTS-123 */ #define XKB_KEY_braille_dots_4 0x1002808 /* U+2808 BRAILLE PATTERN DOTS-4 */ #define XKB_KEY_braille_dots_14 0x1002809 /* U+2809 BRAILLE PATTERN DOTS-14 */ #define XKB_KEY_braille_dots_24 0x100280a /* U+280A BRAILLE PATTERN DOTS-24 */ #define XKB_KEY_braille_dots_124 0x100280b /* U+280B BRAILLE PATTERN DOTS-124 */ #define XKB_KEY_braille_dots_34 0x100280c /* U+280C BRAILLE PATTERN DOTS-34 */ #define XKB_KEY_braille_dots_134 0x100280d /* U+280D BRAILLE PATTERN DOTS-134 */ #define XKB_KEY_braille_dots_234 0x100280e /* U+280E BRAILLE PATTERN DOTS-234 */ #define XKB_KEY_braille_dots_1234 0x100280f /* U+280F BRAILLE PATTERN DOTS-1234 */ #define XKB_KEY_braille_dots_5 0x1002810 /* U+2810 BRAILLE PATTERN DOTS-5 */ #define XKB_KEY_braille_dots_15 0x1002811 /* U+2811 BRAILLE PATTERN DOTS-15 */ #define XKB_KEY_braille_dots_25 0x1002812 /* U+2812 BRAILLE PATTERN DOTS-25 */ #define XKB_KEY_braille_dots_125 0x1002813 /* U+2813 BRAILLE PATTERN DOTS-125 */ #define XKB_KEY_braille_dots_35 0x1002814 /* U+2814 BRAILLE PATTERN DOTS-35 */ #define XKB_KEY_braille_dots_135 0x1002815 /* U+2815 BRAILLE PATTERN DOTS-135 */ #define XKB_KEY_braille_dots_235 0x1002816 /* U+2816 BRAILLE PATTERN DOTS-235 */ #define XKB_KEY_braille_dots_1235 0x1002817 /* U+2817 BRAILLE PATTERN DOTS-1235 */ #define XKB_KEY_braille_dots_45 0x1002818 /* U+2818 BRAILLE PATTERN DOTS-45 */ #define XKB_KEY_braille_dots_145 0x1002819 /* U+2819 BRAILLE PATTERN DOTS-145 */ #define XKB_KEY_braille_dots_245 0x100281a /* U+281A BRAILLE PATTERN DOTS-245 */ #define XKB_KEY_braille_dots_1245 0x100281b /* U+281B BRAILLE PATTERN DOTS-1245 */ #define XKB_KEY_braille_dots_345 0x100281c /* U+281C BRAILLE PATTERN DOTS-345 */ #define XKB_KEY_braille_dots_1345 0x100281d /* U+281D BRAILLE PATTERN DOTS-1345 */ #define XKB_KEY_braille_dots_2345 0x100281e /* U+281E BRAILLE PATTERN DOTS-2345 */ #define XKB_KEY_braille_dots_12345 0x100281f /* U+281F BRAILLE PATTERN DOTS-12345 */ #define XKB_KEY_braille_dots_6 0x1002820 /* U+2820 BRAILLE PATTERN DOTS-6 */ #define XKB_KEY_braille_dots_16 0x1002821 /* U+2821 BRAILLE PATTERN DOTS-16 */ #define XKB_KEY_braille_dots_26 0x1002822 /* U+2822 BRAILLE PATTERN DOTS-26 */ #define XKB_KEY_braille_dots_126 0x1002823 /* U+2823 BRAILLE PATTERN DOTS-126 */ #define XKB_KEY_braille_dots_36 0x1002824 /* U+2824 BRAILLE PATTERN DOTS-36 */ #define XKB_KEY_braille_dots_136 0x1002825 /* U+2825 BRAILLE PATTERN DOTS-136 */ #define XKB_KEY_braille_dots_236 0x1002826 /* U+2826 BRAILLE PATTERN DOTS-236 */ #define XKB_KEY_braille_dots_1236 0x1002827 /* U+2827 BRAILLE PATTERN DOTS-1236 */ #define XKB_KEY_braille_dots_46 0x1002828 /* U+2828 BRAILLE PATTERN DOTS-46 */ #define XKB_KEY_braille_dots_146 0x1002829 /* U+2829 BRAILLE PATTERN DOTS-146 */ #define XKB_KEY_braille_dots_246 0x100282a /* U+282A BRAILLE PATTERN DOTS-246 */ #define XKB_KEY_braille_dots_1246 0x100282b /* U+282B BRAILLE PATTERN DOTS-1246 */ #define XKB_KEY_braille_dots_346 0x100282c /* U+282C BRAILLE PATTERN DOTS-346 */ #define XKB_KEY_braille_dots_1346 0x100282d /* U+282D BRAILLE PATTERN DOTS-1346 */ #define XKB_KEY_braille_dots_2346 0x100282e /* U+282E BRAILLE PATTERN DOTS-2346 */ #define XKB_KEY_braille_dots_12346 0x100282f /* U+282F BRAILLE PATTERN DOTS-12346 */ #define XKB_KEY_braille_dots_56 0x1002830 /* U+2830 BRAILLE PATTERN DOTS-56 */ #define XKB_KEY_braille_dots_156 0x1002831 /* U+2831 BRAILLE PATTERN DOTS-156 */ #define XKB_KEY_braille_dots_256 0x1002832 /* U+2832 BRAILLE PATTERN DOTS-256 */ #define XKB_KEY_braille_dots_1256 0x1002833 /* U+2833 BRAILLE PATTERN DOTS-1256 */ #define XKB_KEY_braille_dots_356 0x1002834 /* U+2834 BRAILLE PATTERN DOTS-356 */ #define XKB_KEY_braille_dots_1356 0x1002835 /* U+2835 BRAILLE PATTERN DOTS-1356 */ #define XKB_KEY_braille_dots_2356 0x1002836 /* U+2836 BRAILLE PATTERN DOTS-2356 */ #define XKB_KEY_braille_dots_12356 0x1002837 /* U+2837 BRAILLE PATTERN DOTS-12356 */ #define XKB_KEY_braille_dots_456 0x1002838 /* U+2838 BRAILLE PATTERN DOTS-456 */ #define XKB_KEY_braille_dots_1456 0x1002839 /* U+2839 BRAILLE PATTERN DOTS-1456 */ #define XKB_KEY_braille_dots_2456 0x100283a /* U+283A BRAILLE PATTERN DOTS-2456 */ #define XKB_KEY_braille_dots_12456 0x100283b /* U+283B BRAILLE PATTERN DOTS-12456 */ #define XKB_KEY_braille_dots_3456 0x100283c /* U+283C BRAILLE PATTERN DOTS-3456 */ #define XKB_KEY_braille_dots_13456 0x100283d /* U+283D BRAILLE PATTERN DOTS-13456 */ #define XKB_KEY_braille_dots_23456 0x100283e /* U+283E BRAILLE PATTERN DOTS-23456 */ #define XKB_KEY_braille_dots_123456 0x100283f /* U+283F BRAILLE PATTERN DOTS-123456 */ #define XKB_KEY_braille_dots_7 0x1002840 /* U+2840 BRAILLE PATTERN DOTS-7 */ #define XKB_KEY_braille_dots_17 0x1002841 /* U+2841 BRAILLE PATTERN DOTS-17 */ #define XKB_KEY_braille_dots_27 0x1002842 /* U+2842 BRAILLE PATTERN DOTS-27 */ #define XKB_KEY_braille_dots_127 0x1002843 /* U+2843 BRAILLE PATTERN DOTS-127 */ #define XKB_KEY_braille_dots_37 0x1002844 /* U+2844 BRAILLE PATTERN DOTS-37 */ #define XKB_KEY_braille_dots_137 0x1002845 /* U+2845 BRAILLE PATTERN DOTS-137 */ #define XKB_KEY_braille_dots_237 0x1002846 /* U+2846 BRAILLE PATTERN DOTS-237 */ #define XKB_KEY_braille_dots_1237 0x1002847 /* U+2847 BRAILLE PATTERN DOTS-1237 */ #define XKB_KEY_braille_dots_47 0x1002848 /* U+2848 BRAILLE PATTERN DOTS-47 */ #define XKB_KEY_braille_dots_147 0x1002849 /* U+2849 BRAILLE PATTERN DOTS-147 */ #define XKB_KEY_braille_dots_247 0x100284a /* U+284A BRAILLE PATTERN DOTS-247 */ #define XKB_KEY_braille_dots_1247 0x100284b /* U+284B BRAILLE PATTERN DOTS-1247 */ #define XKB_KEY_braille_dots_347 0x100284c /* U+284C BRAILLE PATTERN DOTS-347 */ #define XKB_KEY_braille_dots_1347 0x100284d /* U+284D BRAILLE PATTERN DOTS-1347 */ #define XKB_KEY_braille_dots_2347 0x100284e /* U+284E BRAILLE PATTERN DOTS-2347 */ #define XKB_KEY_braille_dots_12347 0x100284f /* U+284F BRAILLE PATTERN DOTS-12347 */ #define XKB_KEY_braille_dots_57 0x1002850 /* U+2850 BRAILLE PATTERN DOTS-57 */ #define XKB_KEY_braille_dots_157 0x1002851 /* U+2851 BRAILLE PATTERN DOTS-157 */ #define XKB_KEY_braille_dots_257 0x1002852 /* U+2852 BRAILLE PATTERN DOTS-257 */ #define XKB_KEY_braille_dots_1257 0x1002853 /* U+2853 BRAILLE PATTERN DOTS-1257 */ #define XKB_KEY_braille_dots_357 0x1002854 /* U+2854 BRAILLE PATTERN DOTS-357 */ #define XKB_KEY_braille_dots_1357 0x1002855 /* U+2855 BRAILLE PATTERN DOTS-1357 */ #define XKB_KEY_braille_dots_2357 0x1002856 /* U+2856 BRAILLE PATTERN DOTS-2357 */ #define XKB_KEY_braille_dots_12357 0x1002857 /* U+2857 BRAILLE PATTERN DOTS-12357 */ #define XKB_KEY_braille_dots_457 0x1002858 /* U+2858 BRAILLE PATTERN DOTS-457 */ #define XKB_KEY_braille_dots_1457 0x1002859 /* U+2859 BRAILLE PATTERN DOTS-1457 */ #define XKB_KEY_braille_dots_2457 0x100285a /* U+285A BRAILLE PATTERN DOTS-2457 */ #define XKB_KEY_braille_dots_12457 0x100285b /* U+285B BRAILLE PATTERN DOTS-12457 */ #define XKB_KEY_braille_dots_3457 0x100285c /* U+285C BRAILLE PATTERN DOTS-3457 */ #define XKB_KEY_braille_dots_13457 0x100285d /* U+285D BRAILLE PATTERN DOTS-13457 */ #define XKB_KEY_braille_dots_23457 0x100285e /* U+285E BRAILLE PATTERN DOTS-23457 */ #define XKB_KEY_braille_dots_123457 0x100285f /* U+285F BRAILLE PATTERN DOTS-123457 */ #define XKB_KEY_braille_dots_67 0x1002860 /* U+2860 BRAILLE PATTERN DOTS-67 */ #define XKB_KEY_braille_dots_167 0x1002861 /* U+2861 BRAILLE PATTERN DOTS-167 */ #define XKB_KEY_braille_dots_267 0x1002862 /* U+2862 BRAILLE PATTERN DOTS-267 */ #define XKB_KEY_braille_dots_1267 0x1002863 /* U+2863 BRAILLE PATTERN DOTS-1267 */ #define XKB_KEY_braille_dots_367 0x1002864 /* U+2864 BRAILLE PATTERN DOTS-367 */ #define XKB_KEY_braille_dots_1367 0x1002865 /* U+2865 BRAILLE PATTERN DOTS-1367 */ #define XKB_KEY_braille_dots_2367 0x1002866 /* U+2866 BRAILLE PATTERN DOTS-2367 */ #define XKB_KEY_braille_dots_12367 0x1002867 /* U+2867 BRAILLE PATTERN DOTS-12367 */ #define XKB_KEY_braille_dots_467 0x1002868 /* U+2868 BRAILLE PATTERN DOTS-467 */ #define XKB_KEY_braille_dots_1467 0x1002869 /* U+2869 BRAILLE PATTERN DOTS-1467 */ #define XKB_KEY_braille_dots_2467 0x100286a /* U+286A BRAILLE PATTERN DOTS-2467 */ #define XKB_KEY_braille_dots_12467 0x100286b /* U+286B BRAILLE PATTERN DOTS-12467 */ #define XKB_KEY_braille_dots_3467 0x100286c /* U+286C BRAILLE PATTERN DOTS-3467 */ #define XKB_KEY_braille_dots_13467 0x100286d /* U+286D BRAILLE PATTERN DOTS-13467 */ #define XKB_KEY_braille_dots_23467 0x100286e /* U+286E BRAILLE PATTERN DOTS-23467 */ #define XKB_KEY_braille_dots_123467 0x100286f /* U+286F BRAILLE PATTERN DOTS-123467 */ #define XKB_KEY_braille_dots_567 0x1002870 /* U+2870 BRAILLE PATTERN DOTS-567 */ #define XKB_KEY_braille_dots_1567 0x1002871 /* U+2871 BRAILLE PATTERN DOTS-1567 */ #define XKB_KEY_braille_dots_2567 0x1002872 /* U+2872 BRAILLE PATTERN DOTS-2567 */ #define XKB_KEY_braille_dots_12567 0x1002873 /* U+2873 BRAILLE PATTERN DOTS-12567 */ #define XKB_KEY_braille_dots_3567 0x1002874 /* U+2874 BRAILLE PATTERN DOTS-3567 */ #define XKB_KEY_braille_dots_13567 0x1002875 /* U+2875 BRAILLE PATTERN DOTS-13567 */ #define XKB_KEY_braille_dots_23567 0x1002876 /* U+2876 BRAILLE PATTERN DOTS-23567 */ #define XKB_KEY_braille_dots_123567 0x1002877 /* U+2877 BRAILLE PATTERN DOTS-123567 */ #define XKB_KEY_braille_dots_4567 0x1002878 /* U+2878 BRAILLE PATTERN DOTS-4567 */ #define XKB_KEY_braille_dots_14567 0x1002879 /* U+2879 BRAILLE PATTERN DOTS-14567 */ #define XKB_KEY_braille_dots_24567 0x100287a /* U+287A BRAILLE PATTERN DOTS-24567 */ #define XKB_KEY_braille_dots_124567 0x100287b /* U+287B BRAILLE PATTERN DOTS-124567 */ #define XKB_KEY_braille_dots_34567 0x100287c /* U+287C BRAILLE PATTERN DOTS-34567 */ #define XKB_KEY_braille_dots_134567 0x100287d /* U+287D BRAILLE PATTERN DOTS-134567 */ #define XKB_KEY_braille_dots_234567 0x100287e /* U+287E BRAILLE PATTERN DOTS-234567 */ #define XKB_KEY_braille_dots_1234567 0x100287f /* U+287F BRAILLE PATTERN DOTS-1234567 */ #define XKB_KEY_braille_dots_8 0x1002880 /* U+2880 BRAILLE PATTERN DOTS-8 */ #define XKB_KEY_braille_dots_18 0x1002881 /* U+2881 BRAILLE PATTERN DOTS-18 */ #define XKB_KEY_braille_dots_28 0x1002882 /* U+2882 BRAILLE PATTERN DOTS-28 */ #define XKB_KEY_braille_dots_128 0x1002883 /* U+2883 BRAILLE PATTERN DOTS-128 */ #define XKB_KEY_braille_dots_38 0x1002884 /* U+2884 BRAILLE PATTERN DOTS-38 */ #define XKB_KEY_braille_dots_138 0x1002885 /* U+2885 BRAILLE PATTERN DOTS-138 */ #define XKB_KEY_braille_dots_238 0x1002886 /* U+2886 BRAILLE PATTERN DOTS-238 */ #define XKB_KEY_braille_dots_1238 0x1002887 /* U+2887 BRAILLE PATTERN DOTS-1238 */ #define XKB_KEY_braille_dots_48 0x1002888 /* U+2888 BRAILLE PATTERN DOTS-48 */ #define XKB_KEY_braille_dots_148 0x1002889 /* U+2889 BRAILLE PATTERN DOTS-148 */ #define XKB_KEY_braille_dots_248 0x100288a /* U+288A BRAILLE PATTERN DOTS-248 */ #define XKB_KEY_braille_dots_1248 0x100288b /* U+288B BRAILLE PATTERN DOTS-1248 */ #define XKB_KEY_braille_dots_348 0x100288c /* U+288C BRAILLE PATTERN DOTS-348 */ #define XKB_KEY_braille_dots_1348 0x100288d /* U+288D BRAILLE PATTERN DOTS-1348 */ #define XKB_KEY_braille_dots_2348 0x100288e /* U+288E BRAILLE PATTERN DOTS-2348 */ #define XKB_KEY_braille_dots_12348 0x100288f /* U+288F BRAILLE PATTERN DOTS-12348 */ #define XKB_KEY_braille_dots_58 0x1002890 /* U+2890 BRAILLE PATTERN DOTS-58 */ #define XKB_KEY_braille_dots_158 0x1002891 /* U+2891 BRAILLE PATTERN DOTS-158 */ #define XKB_KEY_braille_dots_258 0x1002892 /* U+2892 BRAILLE PATTERN DOTS-258 */ #define XKB_KEY_braille_dots_1258 0x1002893 /* U+2893 BRAILLE PATTERN DOTS-1258 */ #define XKB_KEY_braille_dots_358 0x1002894 /* U+2894 BRAILLE PATTERN DOTS-358 */ #define XKB_KEY_braille_dots_1358 0x1002895 /* U+2895 BRAILLE PATTERN DOTS-1358 */ #define XKB_KEY_braille_dots_2358 0x1002896 /* U+2896 BRAILLE PATTERN DOTS-2358 */ #define XKB_KEY_braille_dots_12358 0x1002897 /* U+2897 BRAILLE PATTERN DOTS-12358 */ #define XKB_KEY_braille_dots_458 0x1002898 /* U+2898 BRAILLE PATTERN DOTS-458 */ #define XKB_KEY_braille_dots_1458 0x1002899 /* U+2899 BRAILLE PATTERN DOTS-1458 */ #define XKB_KEY_braille_dots_2458 0x100289a /* U+289A BRAILLE PATTERN DOTS-2458 */ #define XKB_KEY_braille_dots_12458 0x100289b /* U+289B BRAILLE PATTERN DOTS-12458 */ #define XKB_KEY_braille_dots_3458 0x100289c /* U+289C BRAILLE PATTERN DOTS-3458 */ #define XKB_KEY_braille_dots_13458 0x100289d /* U+289D BRAILLE PATTERN DOTS-13458 */ #define XKB_KEY_braille_dots_23458 0x100289e /* U+289E BRAILLE PATTERN DOTS-23458 */ #define XKB_KEY_braille_dots_123458 0x100289f /* U+289F BRAILLE PATTERN DOTS-123458 */ #define XKB_KEY_braille_dots_68 0x10028a0 /* U+28A0 BRAILLE PATTERN DOTS-68 */ #define XKB_KEY_braille_dots_168 0x10028a1 /* U+28A1 BRAILLE PATTERN DOTS-168 */ #define XKB_KEY_braille_dots_268 0x10028a2 /* U+28A2 BRAILLE PATTERN DOTS-268 */ #define XKB_KEY_braille_dots_1268 0x10028a3 /* U+28A3 BRAILLE PATTERN DOTS-1268 */ #define XKB_KEY_braille_dots_368 0x10028a4 /* U+28A4 BRAILLE PATTERN DOTS-368 */ #define XKB_KEY_braille_dots_1368 0x10028a5 /* U+28A5 BRAILLE PATTERN DOTS-1368 */ #define XKB_KEY_braille_dots_2368 0x10028a6 /* U+28A6 BRAILLE PATTERN DOTS-2368 */ #define XKB_KEY_braille_dots_12368 0x10028a7 /* U+28A7 BRAILLE PATTERN DOTS-12368 */ #define XKB_KEY_braille_dots_468 0x10028a8 /* U+28A8 BRAILLE PATTERN DOTS-468 */ #define XKB_KEY_braille_dots_1468 0x10028a9 /* U+28A9 BRAILLE PATTERN DOTS-1468 */ #define XKB_KEY_braille_dots_2468 0x10028aa /* U+28AA BRAILLE PATTERN DOTS-2468 */ #define XKB_KEY_braille_dots_12468 0x10028ab /* U+28AB BRAILLE PATTERN DOTS-12468 */ #define XKB_KEY_braille_dots_3468 0x10028ac /* U+28AC BRAILLE PATTERN DOTS-3468 */ #define XKB_KEY_braille_dots_13468 0x10028ad /* U+28AD BRAILLE PATTERN DOTS-13468 */ #define XKB_KEY_braille_dots_23468 0x10028ae /* U+28AE BRAILLE PATTERN DOTS-23468 */ #define XKB_KEY_braille_dots_123468 0x10028af /* U+28AF BRAILLE PATTERN DOTS-123468 */ #define XKB_KEY_braille_dots_568 0x10028b0 /* U+28B0 BRAILLE PATTERN DOTS-568 */ #define XKB_KEY_braille_dots_1568 0x10028b1 /* U+28B1 BRAILLE PATTERN DOTS-1568 */ #define XKB_KEY_braille_dots_2568 0x10028b2 /* U+28B2 BRAILLE PATTERN DOTS-2568 */ #define XKB_KEY_braille_dots_12568 0x10028b3 /* U+28B3 BRAILLE PATTERN DOTS-12568 */ #define XKB_KEY_braille_dots_3568 0x10028b4 /* U+28B4 BRAILLE PATTERN DOTS-3568 */ #define XKB_KEY_braille_dots_13568 0x10028b5 /* U+28B5 BRAILLE PATTERN DOTS-13568 */ #define XKB_KEY_braille_dots_23568 0x10028b6 /* U+28B6 BRAILLE PATTERN DOTS-23568 */ #define XKB_KEY_braille_dots_123568 0x10028b7 /* U+28B7 BRAILLE PATTERN DOTS-123568 */ #define XKB_KEY_braille_dots_4568 0x10028b8 /* U+28B8 BRAILLE PATTERN DOTS-4568 */ #define XKB_KEY_braille_dots_14568 0x10028b9 /* U+28B9 BRAILLE PATTERN DOTS-14568 */ #define XKB_KEY_braille_dots_24568 0x10028ba /* U+28BA BRAILLE PATTERN DOTS-24568 */ #define XKB_KEY_braille_dots_124568 0x10028bb /* U+28BB BRAILLE PATTERN DOTS-124568 */ #define XKB_KEY_braille_dots_34568 0x10028bc /* U+28BC BRAILLE PATTERN DOTS-34568 */ #define XKB_KEY_braille_dots_134568 0x10028bd /* U+28BD BRAILLE PATTERN DOTS-134568 */ #define XKB_KEY_braille_dots_234568 0x10028be /* U+28BE BRAILLE PATTERN DOTS-234568 */ #define XKB_KEY_braille_dots_1234568 0x10028bf /* U+28BF BRAILLE PATTERN DOTS-1234568 */ #define XKB_KEY_braille_dots_78 0x10028c0 /* U+28C0 BRAILLE PATTERN DOTS-78 */ #define XKB_KEY_braille_dots_178 0x10028c1 /* U+28C1 BRAILLE PATTERN DOTS-178 */ #define XKB_KEY_braille_dots_278 0x10028c2 /* U+28C2 BRAILLE PATTERN DOTS-278 */ #define XKB_KEY_braille_dots_1278 0x10028c3 /* U+28C3 BRAILLE PATTERN DOTS-1278 */ #define XKB_KEY_braille_dots_378 0x10028c4 /* U+28C4 BRAILLE PATTERN DOTS-378 */ #define XKB_KEY_braille_dots_1378 0x10028c5 /* U+28C5 BRAILLE PATTERN DOTS-1378 */ #define XKB_KEY_braille_dots_2378 0x10028c6 /* U+28C6 BRAILLE PATTERN DOTS-2378 */ #define XKB_KEY_braille_dots_12378 0x10028c7 /* U+28C7 BRAILLE PATTERN DOTS-12378 */ #define XKB_KEY_braille_dots_478 0x10028c8 /* U+28C8 BRAILLE PATTERN DOTS-478 */ #define XKB_KEY_braille_dots_1478 0x10028c9 /* U+28C9 BRAILLE PATTERN DOTS-1478 */ #define XKB_KEY_braille_dots_2478 0x10028ca /* U+28CA BRAILLE PATTERN DOTS-2478 */ #define XKB_KEY_braille_dots_12478 0x10028cb /* U+28CB BRAILLE PATTERN DOTS-12478 */ #define XKB_KEY_braille_dots_3478 0x10028cc /* U+28CC BRAILLE PATTERN DOTS-3478 */ #define XKB_KEY_braille_dots_13478 0x10028cd /* U+28CD BRAILLE PATTERN DOTS-13478 */ #define XKB_KEY_braille_dots_23478 0x10028ce /* U+28CE BRAILLE PATTERN DOTS-23478 */ #define XKB_KEY_braille_dots_123478 0x10028cf /* U+28CF BRAILLE PATTERN DOTS-123478 */ #define XKB_KEY_braille_dots_578 0x10028d0 /* U+28D0 BRAILLE PATTERN DOTS-578 */ #define XKB_KEY_braille_dots_1578 0x10028d1 /* U+28D1 BRAILLE PATTERN DOTS-1578 */ #define XKB_KEY_braille_dots_2578 0x10028d2 /* U+28D2 BRAILLE PATTERN DOTS-2578 */ #define XKB_KEY_braille_dots_12578 0x10028d3 /* U+28D3 BRAILLE PATTERN DOTS-12578 */ #define XKB_KEY_braille_dots_3578 0x10028d4 /* U+28D4 BRAILLE PATTERN DOTS-3578 */ #define XKB_KEY_braille_dots_13578 0x10028d5 /* U+28D5 BRAILLE PATTERN DOTS-13578 */ #define XKB_KEY_braille_dots_23578 0x10028d6 /* U+28D6 BRAILLE PATTERN DOTS-23578 */ #define XKB_KEY_braille_dots_123578 0x10028d7 /* U+28D7 BRAILLE PATTERN DOTS-123578 */ #define XKB_KEY_braille_dots_4578 0x10028d8 /* U+28D8 BRAILLE PATTERN DOTS-4578 */ #define XKB_KEY_braille_dots_14578 0x10028d9 /* U+28D9 BRAILLE PATTERN DOTS-14578 */ #define XKB_KEY_braille_dots_24578 0x10028da /* U+28DA BRAILLE PATTERN DOTS-24578 */ #define XKB_KEY_braille_dots_124578 0x10028db /* U+28DB BRAILLE PATTERN DOTS-124578 */ #define XKB_KEY_braille_dots_34578 0x10028dc /* U+28DC BRAILLE PATTERN DOTS-34578 */ #define XKB_KEY_braille_dots_134578 0x10028dd /* U+28DD BRAILLE PATTERN DOTS-134578 */ #define XKB_KEY_braille_dots_234578 0x10028de /* U+28DE BRAILLE PATTERN DOTS-234578 */ #define XKB_KEY_braille_dots_1234578 0x10028df /* U+28DF BRAILLE PATTERN DOTS-1234578 */ #define XKB_KEY_braille_dots_678 0x10028e0 /* U+28E0 BRAILLE PATTERN DOTS-678 */ #define XKB_KEY_braille_dots_1678 0x10028e1 /* U+28E1 BRAILLE PATTERN DOTS-1678 */ #define XKB_KEY_braille_dots_2678 0x10028e2 /* U+28E2 BRAILLE PATTERN DOTS-2678 */ #define XKB_KEY_braille_dots_12678 0x10028e3 /* U+28E3 BRAILLE PATTERN DOTS-12678 */ #define XKB_KEY_braille_dots_3678 0x10028e4 /* U+28E4 BRAILLE PATTERN DOTS-3678 */ #define XKB_KEY_braille_dots_13678 0x10028e5 /* U+28E5 BRAILLE PATTERN DOTS-13678 */ #define XKB_KEY_braille_dots_23678 0x10028e6 /* U+28E6 BRAILLE PATTERN DOTS-23678 */ #define XKB_KEY_braille_dots_123678 0x10028e7 /* U+28E7 BRAILLE PATTERN DOTS-123678 */ #define XKB_KEY_braille_dots_4678 0x10028e8 /* U+28E8 BRAILLE PATTERN DOTS-4678 */ #define XKB_KEY_braille_dots_14678 0x10028e9 /* U+28E9 BRAILLE PATTERN DOTS-14678 */ #define XKB_KEY_braille_dots_24678 0x10028ea /* U+28EA BRAILLE PATTERN DOTS-24678 */ #define XKB_KEY_braille_dots_124678 0x10028eb /* U+28EB BRAILLE PATTERN DOTS-124678 */ #define XKB_KEY_braille_dots_34678 0x10028ec /* U+28EC BRAILLE PATTERN DOTS-34678 */ #define XKB_KEY_braille_dots_134678 0x10028ed /* U+28ED BRAILLE PATTERN DOTS-134678 */ #define XKB_KEY_braille_dots_234678 0x10028ee /* U+28EE BRAILLE PATTERN DOTS-234678 */ #define XKB_KEY_braille_dots_1234678 0x10028ef /* U+28EF BRAILLE PATTERN DOTS-1234678 */ #define XKB_KEY_braille_dots_5678 0x10028f0 /* U+28F0 BRAILLE PATTERN DOTS-5678 */ #define XKB_KEY_braille_dots_15678 0x10028f1 /* U+28F1 BRAILLE PATTERN DOTS-15678 */ #define XKB_KEY_braille_dots_25678 0x10028f2 /* U+28F2 BRAILLE PATTERN DOTS-25678 */ #define XKB_KEY_braille_dots_125678 0x10028f3 /* U+28F3 BRAILLE PATTERN DOTS-125678 */ #define XKB_KEY_braille_dots_35678 0x10028f4 /* U+28F4 BRAILLE PATTERN DOTS-35678 */ #define XKB_KEY_braille_dots_135678 0x10028f5 /* U+28F5 BRAILLE PATTERN DOTS-135678 */ #define XKB_KEY_braille_dots_235678 0x10028f6 /* U+28F6 BRAILLE PATTERN DOTS-235678 */ #define XKB_KEY_braille_dots_1235678 0x10028f7 /* U+28F7 BRAILLE PATTERN DOTS-1235678 */ #define XKB_KEY_braille_dots_45678 0x10028f8 /* U+28F8 BRAILLE PATTERN DOTS-45678 */ #define XKB_KEY_braille_dots_145678 0x10028f9 /* U+28F9 BRAILLE PATTERN DOTS-145678 */ #define XKB_KEY_braille_dots_245678 0x10028fa /* U+28FA BRAILLE PATTERN DOTS-245678 */ #define XKB_KEY_braille_dots_1245678 0x10028fb /* U+28FB BRAILLE PATTERN DOTS-1245678 */ #define XKB_KEY_braille_dots_345678 0x10028fc /* U+28FC BRAILLE PATTERN DOTS-345678 */ #define XKB_KEY_braille_dots_1345678 0x10028fd /* U+28FD BRAILLE PATTERN DOTS-1345678 */ #define XKB_KEY_braille_dots_2345678 0x10028fe /* U+28FE BRAILLE PATTERN DOTS-2345678 */ #define XKB_KEY_braille_dots_12345678 0x10028ff /* U+28FF BRAILLE PATTERN DOTS-12345678 */ /* * Sinhala (http://unicode.org/charts/PDF/U0D80.pdf) * http://www.nongnu.org/sinhala/doc/transliteration/sinhala-transliteration_6.html */ #define XKB_KEY_Sinh_ng 0x1000d82 /* U+0D82 SINHALA SIGN ANUSVARAYA */ #define XKB_KEY_Sinh_h2 0x1000d83 /* U+0D83 SINHALA SIGN VISARGAYA */ #define XKB_KEY_Sinh_a 0x1000d85 /* U+0D85 SINHALA LETTER AYANNA */ #define XKB_KEY_Sinh_aa 0x1000d86 /* U+0D86 SINHALA LETTER AAYANNA */ #define XKB_KEY_Sinh_ae 0x1000d87 /* U+0D87 SINHALA LETTER AEYANNA */ #define XKB_KEY_Sinh_aee 0x1000d88 /* U+0D88 SINHALA LETTER AEEYANNA */ #define XKB_KEY_Sinh_i 0x1000d89 /* U+0D89 SINHALA LETTER IYANNA */ #define XKB_KEY_Sinh_ii 0x1000d8a /* U+0D8A SINHALA LETTER IIYANNA */ #define XKB_KEY_Sinh_u 0x1000d8b /* U+0D8B SINHALA LETTER UYANNA */ #define XKB_KEY_Sinh_uu 0x1000d8c /* U+0D8C SINHALA LETTER UUYANNA */ #define XKB_KEY_Sinh_ri 0x1000d8d /* U+0D8D SINHALA LETTER IRUYANNA */ #define XKB_KEY_Sinh_rii 0x1000d8e /* U+0D8E SINHALA LETTER IRUUYANNA */ #define XKB_KEY_Sinh_lu 0x1000d8f /* U+0D8F SINHALA LETTER ILUYANNA */ #define XKB_KEY_Sinh_luu 0x1000d90 /* U+0D90 SINHALA LETTER ILUUYANNA */ #define XKB_KEY_Sinh_e 0x1000d91 /* U+0D91 SINHALA LETTER EYANNA */ #define XKB_KEY_Sinh_ee 0x1000d92 /* U+0D92 SINHALA LETTER EEYANNA */ #define XKB_KEY_Sinh_ai 0x1000d93 /* U+0D93 SINHALA LETTER AIYANNA */ #define XKB_KEY_Sinh_o 0x1000d94 /* U+0D94 SINHALA LETTER OYANNA */ #define XKB_KEY_Sinh_oo 0x1000d95 /* U+0D95 SINHALA LETTER OOYANNA */ #define XKB_KEY_Sinh_au 0x1000d96 /* U+0D96 SINHALA LETTER AUYANNA */ #define XKB_KEY_Sinh_ka 0x1000d9a /* U+0D9A SINHALA LETTER ALPAPRAANA KAYANNA */ #define XKB_KEY_Sinh_kha 0x1000d9b /* U+0D9B SINHALA LETTER MAHAAPRAANA KAYANNA */ #define XKB_KEY_Sinh_ga 0x1000d9c /* U+0D9C SINHALA LETTER ALPAPRAANA GAYANNA */ #define XKB_KEY_Sinh_gha 0x1000d9d /* U+0D9D SINHALA LETTER MAHAAPRAANA GAYANNA */ #define XKB_KEY_Sinh_ng2 0x1000d9e /* U+0D9E SINHALA LETTER KANTAJA NAASIKYAYA */ #define XKB_KEY_Sinh_nga 0x1000d9f /* U+0D9F SINHALA LETTER SANYAKA GAYANNA */ #define XKB_KEY_Sinh_ca 0x1000da0 /* U+0DA0 SINHALA LETTER ALPAPRAANA CAYANNA */ #define XKB_KEY_Sinh_cha 0x1000da1 /* U+0DA1 SINHALA LETTER MAHAAPRAANA CAYANNA */ #define XKB_KEY_Sinh_ja 0x1000da2 /* U+0DA2 SINHALA LETTER ALPAPRAANA JAYANNA */ #define XKB_KEY_Sinh_jha 0x1000da3 /* U+0DA3 SINHALA LETTER MAHAAPRAANA JAYANNA */ #define XKB_KEY_Sinh_nya 0x1000da4 /* U+0DA4 SINHALA LETTER TAALUJA NAASIKYAYA */ #define XKB_KEY_Sinh_jnya 0x1000da5 /* U+0DA5 SINHALA LETTER TAALUJA SANYOOGA NAAKSIKYAYA */ #define XKB_KEY_Sinh_nja 0x1000da6 /* U+0DA6 SINHALA LETTER SANYAKA JAYANNA */ #define XKB_KEY_Sinh_tta 0x1000da7 /* U+0DA7 SINHALA LETTER ALPAPRAANA TTAYANNA */ #define XKB_KEY_Sinh_ttha 0x1000da8 /* U+0DA8 SINHALA LETTER MAHAAPRAANA TTAYANNA */ #define XKB_KEY_Sinh_dda 0x1000da9 /* U+0DA9 SINHALA LETTER ALPAPRAANA DDAYANNA */ #define XKB_KEY_Sinh_ddha 0x1000daa /* U+0DAA SINHALA LETTER MAHAAPRAANA DDAYANNA */ #define XKB_KEY_Sinh_nna 0x1000dab /* U+0DAB SINHALA LETTER MUURDHAJA NAYANNA */ #define XKB_KEY_Sinh_ndda 0x1000dac /* U+0DAC SINHALA LETTER SANYAKA DDAYANNA */ #define XKB_KEY_Sinh_tha 0x1000dad /* U+0DAD SINHALA LETTER ALPAPRAANA TAYANNA */ #define XKB_KEY_Sinh_thha 0x1000dae /* U+0DAE SINHALA LETTER MAHAAPRAANA TAYANNA */ #define XKB_KEY_Sinh_dha 0x1000daf /* U+0DAF SINHALA LETTER ALPAPRAANA DAYANNA */ #define XKB_KEY_Sinh_dhha 0x1000db0 /* U+0DB0 SINHALA LETTER MAHAAPRAANA DAYANNA */ #define XKB_KEY_Sinh_na 0x1000db1 /* U+0DB1 SINHALA LETTER DANTAJA NAYANNA */ #define XKB_KEY_Sinh_ndha 0x1000db3 /* U+0DB3 SINHALA LETTER SANYAKA DAYANNA */ #define XKB_KEY_Sinh_pa 0x1000db4 /* U+0DB4 SINHALA LETTER ALPAPRAANA PAYANNA */ #define XKB_KEY_Sinh_pha 0x1000db5 /* U+0DB5 SINHALA LETTER MAHAAPRAANA PAYANNA */ #define XKB_KEY_Sinh_ba 0x1000db6 /* U+0DB6 SINHALA LETTER ALPAPRAANA BAYANNA */ #define XKB_KEY_Sinh_bha 0x1000db7 /* U+0DB7 SINHALA LETTER MAHAAPRAANA BAYANNA */ #define XKB_KEY_Sinh_ma 0x1000db8 /* U+0DB8 SINHALA LETTER MAYANNA */ #define XKB_KEY_Sinh_mba 0x1000db9 /* U+0DB9 SINHALA LETTER AMBA BAYANNA */ #define XKB_KEY_Sinh_ya 0x1000dba /* U+0DBA SINHALA LETTER YAYANNA */ #define XKB_KEY_Sinh_ra 0x1000dbb /* U+0DBB SINHALA LETTER RAYANNA */ #define XKB_KEY_Sinh_la 0x1000dbd /* U+0DBD SINHALA LETTER DANTAJA LAYANNA */ #define XKB_KEY_Sinh_va 0x1000dc0 /* U+0DC0 SINHALA LETTER VAYANNA */ #define XKB_KEY_Sinh_sha 0x1000dc1 /* U+0DC1 SINHALA LETTER TAALUJA SAYANNA */ #define XKB_KEY_Sinh_ssha 0x1000dc2 /* U+0DC2 SINHALA LETTER MUURDHAJA SAYANNA */ #define XKB_KEY_Sinh_sa 0x1000dc3 /* U+0DC3 SINHALA LETTER DANTAJA SAYANNA */ #define XKB_KEY_Sinh_ha 0x1000dc4 /* U+0DC4 SINHALA LETTER HAYANNA */ #define XKB_KEY_Sinh_lla 0x1000dc5 /* U+0DC5 SINHALA LETTER MUURDHAJA LAYANNA */ #define XKB_KEY_Sinh_fa 0x1000dc6 /* U+0DC6 SINHALA LETTER FAYANNA */ #define XKB_KEY_Sinh_al 0x1000dca /* U+0DCA SINHALA SIGN AL-LAKUNA */ #define XKB_KEY_Sinh_aa2 0x1000dcf /* U+0DCF SINHALA VOWEL SIGN AELA-PILLA */ #define XKB_KEY_Sinh_ae2 0x1000dd0 /* U+0DD0 SINHALA VOWEL SIGN KETTI AEDA-PILLA */ #define XKB_KEY_Sinh_aee2 0x1000dd1 /* U+0DD1 SINHALA VOWEL SIGN DIGA AEDA-PILLA */ #define XKB_KEY_Sinh_i2 0x1000dd2 /* U+0DD2 SINHALA VOWEL SIGN KETTI IS-PILLA */ #define XKB_KEY_Sinh_ii2 0x1000dd3 /* U+0DD3 SINHALA VOWEL SIGN DIGA IS-PILLA */ #define XKB_KEY_Sinh_u2 0x1000dd4 /* U+0DD4 SINHALA VOWEL SIGN KETTI PAA-PILLA */ #define XKB_KEY_Sinh_uu2 0x1000dd6 /* U+0DD6 SINHALA VOWEL SIGN DIGA PAA-PILLA */ #define XKB_KEY_Sinh_ru2 0x1000dd8 /* U+0DD8 SINHALA VOWEL SIGN GAETTA-PILLA */ #define XKB_KEY_Sinh_e2 0x1000dd9 /* U+0DD9 SINHALA VOWEL SIGN KOMBUVA */ #define XKB_KEY_Sinh_ee2 0x1000dda /* U+0DDA SINHALA VOWEL SIGN DIGA KOMBUVA */ #define XKB_KEY_Sinh_ai2 0x1000ddb /* U+0DDB SINHALA VOWEL SIGN KOMBU DEKA */ #define XKB_KEY_Sinh_o2 0x1000ddc /* U+0DDC SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA */ #define XKB_KEY_Sinh_oo2 0x1000ddd /* U+0DDD SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA */ #define XKB_KEY_Sinh_au2 0x1000dde /* U+0DDE SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA */ #define XKB_KEY_Sinh_lu2 0x1000ddf /* U+0DDF SINHALA VOWEL SIGN GAYANUKITTA */ #define XKB_KEY_Sinh_ruu2 0x1000df2 /* U+0DF2 SINHALA VOWEL SIGN DIGA GAETTA-PILLA */ #define XKB_KEY_Sinh_luu2 0x1000df3 /* U+0DF3 SINHALA VOWEL SIGN DIGA GAYANUKITTA */ #define XKB_KEY_Sinh_kunddaliya 0x1000df4 /* U+0DF4 SINHALA PUNCTUATION KUNDDALIYA */ /* * XFree86 vendor specific keysyms. * * The XFree86 keysym range is 0x10080001 - 0x1008ffff. * * The XF86 set of keysyms is a catch-all set of defines for keysyms found * on various multimedia keyboards. Originally specific to XFree86 they have * been been adopted over time and are considered a "standard" part of X * keysym definitions. * XFree86 never properly commented these keysyms, so we have done our * best to explain the semantic meaning of these keys. * * XFree86 has removed their mail archives of the period, that might have * shed more light on some of these definitions. Until/unless we resurrect * these archives, these are from memory and usage. */ /* * ModeLock * * This one is old, and not really used any more since XKB offers this * functionality. */ #define XKB_KEY_XF86ModeLock 0x1008ff01 /* Mode Switch Lock */ /* Backlight controls. */ #define XKB_KEY_XF86MonBrightnessUp 0x1008ff02 /* Monitor/panel brightness */ #define XKB_KEY_XF86MonBrightnessDown 0x1008ff03 /* Monitor/panel brightness */ #define XKB_KEY_XF86KbdLightOnOff 0x1008ff04 /* Keyboards may be lit */ #define XKB_KEY_XF86KbdBrightnessUp 0x1008ff05 /* Keyboards may be lit */ #define XKB_KEY_XF86KbdBrightnessDown 0x1008ff06 /* Keyboards may be lit */ #define XKB_KEY_XF86MonBrightnessCycle 0x1008ff07 /* Monitor/panel brightness */ /* * Keys found on some "Internet" keyboards. */ #define XKB_KEY_XF86Standby 0x1008ff10 /* System into standby mode */ #define XKB_KEY_XF86AudioLowerVolume 0x1008ff11 /* Volume control down */ #define XKB_KEY_XF86AudioMute 0x1008ff12 /* Mute sound from the system */ #define XKB_KEY_XF86AudioRaiseVolume 0x1008ff13 /* Volume control up */ #define XKB_KEY_XF86AudioPlay 0x1008ff14 /* Start playing of audio > */ #define XKB_KEY_XF86AudioStop 0x1008ff15 /* Stop playing audio */ #define XKB_KEY_XF86AudioPrev 0x1008ff16 /* Previous track */ #define XKB_KEY_XF86AudioNext 0x1008ff17 /* Next track */ #define XKB_KEY_XF86HomePage 0x1008ff18 /* Display user's home page */ #define XKB_KEY_XF86Mail 0x1008ff19 /* Invoke user's mail program */ #define XKB_KEY_XF86Start 0x1008ff1a /* Start application */ #define XKB_KEY_XF86Search 0x1008ff1b /* Search */ #define XKB_KEY_XF86AudioRecord 0x1008ff1c /* Record audio application */ /* These are sometimes found on PDA's (e.g. Palm, PocketPC or elsewhere) */ #define XKB_KEY_XF86Calculator 0x1008ff1d /* Invoke calculator program */ #define XKB_KEY_XF86Memo 0x1008ff1e /* Invoke Memo taking program */ #define XKB_KEY_XF86ToDoList 0x1008ff1f /* Invoke To Do List program */ #define XKB_KEY_XF86Calendar 0x1008ff20 /* Invoke Calendar program */ #define XKB_KEY_XF86PowerDown 0x1008ff21 /* Deep sleep the system */ #define XKB_KEY_XF86ContrastAdjust 0x1008ff22 /* Adjust screen contrast */ #define XKB_KEY_XF86RockerUp 0x1008ff23 /* Rocker switches exist up */ #define XKB_KEY_XF86RockerDown 0x1008ff24 /* and down */ #define XKB_KEY_XF86RockerEnter 0x1008ff25 /* and let you press them */ /* Some more "Internet" keyboard symbols */ #define XKB_KEY_XF86Back 0x1008ff26 /* Like back on a browser */ #define XKB_KEY_XF86Forward 0x1008ff27 /* Like forward on a browser */ #define XKB_KEY_XF86Stop 0x1008ff28 /* Stop current operation */ #define XKB_KEY_XF86Refresh 0x1008ff29 /* Refresh the page */ #define XKB_KEY_XF86PowerOff 0x1008ff2a /* Power off system entirely */ #define XKB_KEY_XF86WakeUp 0x1008ff2b /* Wake up system from sleep */ #define XKB_KEY_XF86Eject 0x1008ff2c /* Eject device (e.g. DVD) */ #define XKB_KEY_XF86ScreenSaver 0x1008ff2d /* Invoke screensaver */ #define XKB_KEY_XF86WWW 0x1008ff2e /* Invoke web browser */ #define XKB_KEY_XF86Sleep 0x1008ff2f /* Put system to sleep */ #define XKB_KEY_XF86Favorites 0x1008ff30 /* Show favorite locations */ #define XKB_KEY_XF86AudioPause 0x1008ff31 /* Pause audio playing */ #define XKB_KEY_XF86AudioMedia 0x1008ff32 /* Launch media collection app */ #define XKB_KEY_XF86MyComputer 0x1008ff33 /* Display "My Computer" window */ #define XKB_KEY_XF86VendorHome 0x1008ff34 /* Display vendor home web site */ #define XKB_KEY_XF86LightBulb 0x1008ff35 /* Light bulb keys exist */ #define XKB_KEY_XF86Shop 0x1008ff36 /* Display shopping web site */ #define XKB_KEY_XF86History 0x1008ff37 /* Show history of web surfing */ #define XKB_KEY_XF86OpenURL 0x1008ff38 /* Open selected URL */ #define XKB_KEY_XF86AddFavorite 0x1008ff39 /* Add URL to favorites list */ #define XKB_KEY_XF86HotLinks 0x1008ff3a /* Show "hot" links */ #define XKB_KEY_XF86BrightnessAdjust 0x1008ff3b /* Invoke brightness adj. UI */ #define XKB_KEY_XF86Finance 0x1008ff3c /* Display financial site */ #define XKB_KEY_XF86Community 0x1008ff3d /* Display user's community */ #define XKB_KEY_XF86AudioRewind 0x1008ff3e /* "rewind" audio track */ #define XKB_KEY_XF86BackForward 0x1008ff3f /* ??? */ #define XKB_KEY_XF86Launch0 0x1008ff40 /* Launch Application */ #define XKB_KEY_XF86Launch1 0x1008ff41 /* Launch Application */ #define XKB_KEY_XF86Launch2 0x1008ff42 /* Launch Application */ #define XKB_KEY_XF86Launch3 0x1008ff43 /* Launch Application */ #define XKB_KEY_XF86Launch4 0x1008ff44 /* Launch Application */ #define XKB_KEY_XF86Launch5 0x1008ff45 /* Launch Application */ #define XKB_KEY_XF86Launch6 0x1008ff46 /* Launch Application */ #define XKB_KEY_XF86Launch7 0x1008ff47 /* Launch Application */ #define XKB_KEY_XF86Launch8 0x1008ff48 /* Launch Application */ #define XKB_KEY_XF86Launch9 0x1008ff49 /* Launch Application */ #define XKB_KEY_XF86LaunchA 0x1008ff4a /* Launch Application */ #define XKB_KEY_XF86LaunchB 0x1008ff4b /* Launch Application */ #define XKB_KEY_XF86LaunchC 0x1008ff4c /* Launch Application */ #define XKB_KEY_XF86LaunchD 0x1008ff4d /* Launch Application */ #define XKB_KEY_XF86LaunchE 0x1008ff4e /* Launch Application */ #define XKB_KEY_XF86LaunchF 0x1008ff4f /* Launch Application */ #define XKB_KEY_XF86ApplicationLeft 0x1008ff50 /* switch to application, left */ #define XKB_KEY_XF86ApplicationRight 0x1008ff51 /* switch to application, right*/ #define XKB_KEY_XF86Book 0x1008ff52 /* Launch bookreader */ #define XKB_KEY_XF86CD 0x1008ff53 /* Launch CD/DVD player */ #define XKB_KEY_XF86MediaSelectCD 0x1008ff53 /* Alias for XF86CD */ #define XKB_KEY_XF86Calculater 0x1008ff54 /* Launch Calculater */ #define XKB_KEY_XF86Clear 0x1008ff55 /* Clear window, screen */ #define XKB_KEY_XF86Close 0x1008ff56 /* Close window */ #define XKB_KEY_XF86Copy 0x1008ff57 /* Copy selection */ #define XKB_KEY_XF86Cut 0x1008ff58 /* Cut selection */ #define XKB_KEY_XF86Display 0x1008ff59 /* Output switch key */ #define XKB_KEY_XF86DOS 0x1008ff5a /* Launch DOS (emulation) */ #define XKB_KEY_XF86Documents 0x1008ff5b /* Open documents window */ #define XKB_KEY_XF86Excel 0x1008ff5c /* Launch spread sheet */ #define XKB_KEY_XF86Explorer 0x1008ff5d /* Launch file explorer */ #define XKB_KEY_XF86Game 0x1008ff5e /* Launch game */ #define XKB_KEY_XF86Go 0x1008ff5f /* Go to URL */ #define XKB_KEY_XF86iTouch 0x1008ff60 /* Logitech iTouch- don't use */ #define XKB_KEY_XF86LogOff 0x1008ff61 /* Log off system */ #define XKB_KEY_XF86Market 0x1008ff62 /* ?? */ #define XKB_KEY_XF86Meeting 0x1008ff63 /* enter meeting in calendar */ #define XKB_KEY_XF86MenuKB 0x1008ff65 /* distinguish keyboard from PB */ #define XKB_KEY_XF86MenuPB 0x1008ff66 /* distinguish PB from keyboard */ #define XKB_KEY_XF86MySites 0x1008ff67 /* Favourites */ #define XKB_KEY_XF86New 0x1008ff68 /* New (folder, document... */ #define XKB_KEY_XF86News 0x1008ff69 /* News */ #define XKB_KEY_XF86OfficeHome 0x1008ff6a /* Office home (old Staroffice)*/ #define XKB_KEY_XF86Open 0x1008ff6b /* Open */ #define XKB_KEY_XF86Option 0x1008ff6c /* ?? */ #define XKB_KEY_XF86Paste 0x1008ff6d /* Paste */ #define XKB_KEY_XF86Phone 0x1008ff6e /* Launch phone; dial number */ #define XKB_KEY_XF86Q 0x1008ff70 /* Compaq's Q - don't use */ #define XKB_KEY_XF86Reply 0x1008ff72 /* Reply e.g., mail */ #define XKB_KEY_XF86Reload 0x1008ff73 /* Reload web page, file, etc. */ #define XKB_KEY_XF86RotateWindows 0x1008ff74 /* Rotate windows e.g. xrandr */ #define XKB_KEY_XF86RotationPB 0x1008ff75 /* don't use */ #define XKB_KEY_XF86RotationKB 0x1008ff76 /* don't use */ #define XKB_KEY_XF86Save 0x1008ff77 /* Save (file, document, state */ #define XKB_KEY_XF86ScrollUp 0x1008ff78 /* Scroll window/contents up */ #define XKB_KEY_XF86ScrollDown 0x1008ff79 /* Scrool window/contentd down */ #define XKB_KEY_XF86ScrollClick 0x1008ff7a /* Use XKB mousekeys instead */ #define XKB_KEY_XF86Send 0x1008ff7b /* Send mail, file, object */ #define XKB_KEY_XF86Spell 0x1008ff7c /* Spell checker */ #define XKB_KEY_XF86SplitScreen 0x1008ff7d /* Split window or screen */ #define XKB_KEY_XF86Support 0x1008ff7e /* Get support (??) */ #define XKB_KEY_XF86TaskPane 0x1008ff7f /* Show tasks */ #define XKB_KEY_XF86Terminal 0x1008ff80 /* Launch terminal emulator */ #define XKB_KEY_XF86Tools 0x1008ff81 /* toolbox of desktop/app. */ #define XKB_KEY_XF86Travel 0x1008ff82 /* ?? */ #define XKB_KEY_XF86UserPB 0x1008ff84 /* ?? */ #define XKB_KEY_XF86User1KB 0x1008ff85 /* ?? */ #define XKB_KEY_XF86User2KB 0x1008ff86 /* ?? */ #define XKB_KEY_XF86Video 0x1008ff87 /* Launch video player */ #define XKB_KEY_XF86WheelButton 0x1008ff88 /* button from a mouse wheel */ #define XKB_KEY_XF86Word 0x1008ff89 /* Launch word processor */ #define XKB_KEY_XF86Xfer 0x1008ff8a #define XKB_KEY_XF86ZoomIn 0x1008ff8b /* zoom in view, map, etc. */ #define XKB_KEY_XF86ZoomOut 0x1008ff8c /* zoom out view, map, etc. */ #define XKB_KEY_XF86Away 0x1008ff8d /* mark yourself as away */ #define XKB_KEY_XF86Messenger 0x1008ff8e /* as in instant messaging */ #define XKB_KEY_XF86WebCam 0x1008ff8f /* Launch web camera app. */ #define XKB_KEY_XF86MailForward 0x1008ff90 /* Forward in mail */ #define XKB_KEY_XF86Pictures 0x1008ff91 /* Show pictures */ #define XKB_KEY_XF86Music 0x1008ff92 /* Launch music application */ #define XKB_KEY_XF86Battery 0x1008ff93 /* Display battery information */ #define XKB_KEY_XF86Bluetooth 0x1008ff94 /* Enable/disable Bluetooth */ #define XKB_KEY_XF86WLAN 0x1008ff95 /* Enable/disable WLAN */ #define XKB_KEY_XF86UWB 0x1008ff96 /* Enable/disable UWB */ #define XKB_KEY_XF86AudioForward 0x1008ff97 /* fast-forward audio track */ #define XKB_KEY_XF86AudioRepeat 0x1008ff98 /* toggle repeat mode */ #define XKB_KEY_XF86AudioRandomPlay 0x1008ff99 /* toggle shuffle mode */ #define XKB_KEY_XF86Subtitle 0x1008ff9a /* cycle through subtitle */ #define XKB_KEY_XF86AudioCycleTrack 0x1008ff9b /* cycle through audio tracks */ #define XKB_KEY_XF86CycleAngle 0x1008ff9c /* cycle through angles */ #define XKB_KEY_XF86FrameBack 0x1008ff9d /* video: go one frame back */ #define XKB_KEY_XF86FrameForward 0x1008ff9e /* video: go one frame forward */ #define XKB_KEY_XF86Time 0x1008ff9f /* display, or shows an entry for time seeking */ #define XKB_KEY_XF86Select 0x1008ffa0 /* Select button on joypads and remotes */ #define XKB_KEY_XF86View 0x1008ffa1 /* Show a view options/properties */ #define XKB_KEY_XF86TopMenu 0x1008ffa2 /* Go to a top-level menu in a video */ #define XKB_KEY_XF86Red 0x1008ffa3 /* Red button */ #define XKB_KEY_XF86Green 0x1008ffa4 /* Green button */ #define XKB_KEY_XF86Yellow 0x1008ffa5 /* Yellow button */ #define XKB_KEY_XF86Blue 0x1008ffa6 /* Blue button */ #define XKB_KEY_XF86Suspend 0x1008ffa7 /* Sleep to RAM */ #define XKB_KEY_XF86Hibernate 0x1008ffa8 /* Sleep to disk */ #define XKB_KEY_XF86TouchpadToggle 0x1008ffa9 /* Toggle between touchpad/trackstick */ #define XKB_KEY_XF86TouchpadOn 0x1008ffb0 /* The touchpad got switched on */ #define XKB_KEY_XF86TouchpadOff 0x1008ffb1 /* The touchpad got switched off */ #define XKB_KEY_XF86AudioMicMute 0x1008ffb2 /* Mute the Mic from the system */ #define XKB_KEY_XF86Keyboard 0x1008ffb3 /* User defined keyboard related action */ #define XKB_KEY_XF86WWAN 0x1008ffb4 /* Toggle WWAN (LTE, UMTS, etc.) radio */ #define XKB_KEY_XF86RFKill 0x1008ffb5 /* Toggle radios on/off */ #define XKB_KEY_XF86AudioPreset 0x1008ffb6 /* Select equalizer preset, e.g. theatre-mode */ #define XKB_KEY_XF86RotationLockToggle 0x1008ffb7 /* Toggle screen rotation lock on/off */ #define XKB_KEY_XF86FullScreen 0x1008ffb8 /* Toggle fullscreen */ /* Keys for special action keys (hot keys) */ /* Virtual terminals on some operating systems */ #define XKB_KEY_XF86Switch_VT_1 0x1008fe01 #define XKB_KEY_XF86Switch_VT_2 0x1008fe02 #define XKB_KEY_XF86Switch_VT_3 0x1008fe03 #define XKB_KEY_XF86Switch_VT_4 0x1008fe04 #define XKB_KEY_XF86Switch_VT_5 0x1008fe05 #define XKB_KEY_XF86Switch_VT_6 0x1008fe06 #define XKB_KEY_XF86Switch_VT_7 0x1008fe07 #define XKB_KEY_XF86Switch_VT_8 0x1008fe08 #define XKB_KEY_XF86Switch_VT_9 0x1008fe09 #define XKB_KEY_XF86Switch_VT_10 0x1008fe0a #define XKB_KEY_XF86Switch_VT_11 0x1008fe0b #define XKB_KEY_XF86Switch_VT_12 0x1008fe0c #define XKB_KEY_XF86Ungrab 0x1008fe20 /* force ungrab */ #define XKB_KEY_XF86ClearGrab 0x1008fe21 /* kill application with grab */ #define XKB_KEY_XF86Next_VMode 0x1008fe22 /* next video mode available */ #define XKB_KEY_XF86Prev_VMode 0x1008fe23 /* prev. video mode available */ #define XKB_KEY_XF86LogWindowTree 0x1008fe24 /* print window tree to log */ #define XKB_KEY_XF86LogGrabInfo 0x1008fe25 /* print all active grabs to log */ /* * Reserved range for evdev symbols: 0x10081000-0x10081FFF * * Key symbols within this range are intended for a 1:1 mapping to the * Linux kernel input-event-codes.h file: * - Keysym value: `_EVDEVK(kernel value)` * - Keysym name: it must be prefixed by `XKB_KEY_XF86`. The recommended *default* * name uses the following pattern: `XKB_KEY_XF86CamelCaseKernelName`. CamelCasing * is done with a human control as last authority, e.g. see VOD instead of Vod * for the Video on Demand key. In case that the kernel key name is too * ambiguous, it is recommended to create a more explicit name with the * following guidelines: * 1. Names should be mnemonic. * 2. Names should avoid acronyms, unless sufficiently common and documented * in a comment. * 3. Names should identify a function. * 4. Keysyms share a common namespace, so keys with a generic name should * denote a generic function, otherwise it should be renamed to add context. * E.g. `KEY_OK` has the associated keysym `XKB_KEY_XF86OK`, while `KEY_TITLE` * (used to open a menu to select a chapter of a media) is associated to * the keysym `XKB_KEY_XF86MediaTitleMenu` to avoid ambiguity. * 5. Keysyms should support designing *portable* applications, therefore * their names should be self-explaining to facilitate finding them and * to avoid misuse. * 6. The “HID usage tables for USB” can be used if there is an unambiguous * mapping. See: * - Reference document: https://usb.org/document-library/hid-usage-tables-16 * - Mapping in the Linux source file: `drivers/hid/hid-input.c` as of 2025-07 * * For example, the kernel * #define KEY_MACRO_RECORD_START 0x2b0 * effectively ends up as: * #define XKB_KEY_XF86MacroRecordStart 0x100812b0 * * For historical reasons, some keysyms within the reserved range will be * missing, most notably all "normal" keys that are mapped through default * XKB layouts (e.g. KEY_Q). * * The format for #defines is strict: * * #define XKB_KEY_XF86Foo_EVDEVK(0xABC) |* kver KEY_FOO *| * #define XKB_KEY_XF86Foo_EVDEVK(0xABC) |* Alias for XF86Bar *| * #define XKB_KEY_XF86Foo_EVDEVK(0xABC) |* Deprecated alias for XF86Bar *| * * Where * - alignment by spaces * - the _EVDEVK macro must be used * - the hex code must be in uppercase hex * - the kernel version (kver) is in the form v5.10 * - kver and key name are within a slash-star comment (a pipe is used in * this example for technical reasons) * These #defines are parsed by scripts. Do not stray from the given format. * * Where the evdev keycode is mapped to a different symbol, please add a * comment line starting with Use: but otherwise the same format, e.g. * Use: XKB_KEY_XF86RotationLockToggle _EVDEVK(0x231) v4.16 KEY_ROTATE_LOCK_TOGGLE * */ /* Use: XKB_KEY_XF86Eject _EVDEVK(0x0a2) KEY_EJECTCLOSECD */ /* TODO: Use XKB_KEY_XF86AudioNext? _EVDEVK(0x0a3) KEY_NEXTSONG */ /* TODO: XKB_KEY_XF86MediaPlayPause? _EVDEVK(0x0a4) KEY_PLAYPAUSE */ /* TODO: Use XKB_KEY_XF86AudioPrev? _EVDEVK(0x0a5) KEY_PREVIOUSSONG */ /* TODO: Use XKB_KEY_XF86AudioStop? _EVDEVK(0x0a6) KEY_STOPCD */ /* TODO: Use XKB_KEY_XF86AudioRecord? _EVDEVK(0x0a7) KEY_RECORD */ /* TODO: Use XKB_KEY_XF86AudioRewind? _EVDEVK(0x0a8) KEY_REWIND */ /* Use: XKB_KEY_XF86Phone _EVDEVK(0x0a9) KEY_PHONE */ /* TODO: unclear function _EVDEVK(0x0aa) KEY_ISO */ /* TODO: unclear function _EVDEVK(0x0ab) KEY_CONFIG */ /* Use: XKB_KEY_XF86HomePage _EVDEVK(0x0ac) KEY_HOMEPAGE */ /* Use: XKB_KEY_XF86Refresh _EVDEVK(0x0ad) KEY_REFRESH */ /* TODO: unclear function _EVDEVK(0x0ae) KEY_EXIT */ /* TODO: unclear function _EVDEVK(0x0af) KEY_MOVE */ /* TODO: unclear function _EVDEVK(0x0b0) KEY_EDIT */ /* Use: XKB_KEY_XF86ScrollUp _EVDEVK(0x0b1) KEY_SCROLLUP */ /* Use: XKB_KEY_XF86ScrollDown _EVDEVK(0x0b2) KEY_SCROLLDOWN */ /* NOTE: Unless there are special actions bound to the keys KEY_KPLEFTPAREN and * KEY_KPRIGHTPAREN, there is no reason to introduce keypad-specific keysyms */ /* Use: XKB_KEY_parenleft _EVDEVK(0x0b3) KEY_KPLEFTPAREN */ /* Use: XKB_KEY_parenright _EVDEVK(0x0b4) KEY_KPRIGHTPAREN */ /* Use: XKB_KEY_XF86New _EVDEVK(0x0b5) v2.6.14 KEY_NEW */ /* Use: XKB_KEY_Redo _EVDEVK(0x0b6) v2.6.14 KEY_REDO */ /* Use: XKB_KEY_F13 _EVDEVK(0x0b7) KEY_F13 */ /* Use: XKB_KEY_F14 _EVDEVK(0x0b8) KEY_F14 */ /* Use: XKB_KEY_F15 _EVDEVK(0x0b9) KEY_F15 */ /* Use: XKB_KEY_F16 _EVDEVK(0x0ba) KEY_F16 */ /* Use: XKB_KEY_F17 _EVDEVK(0x0bb) KEY_F17 */ /* Use: XKB_KEY_F18 _EVDEVK(0x0bc) KEY_F18 */ /* Use: XKB_KEY_F19 _EVDEVK(0x0bd) KEY_F19 */ /* Use: XKB_KEY_F20 _EVDEVK(0x0be) KEY_F20 */ /* Use: XKB_KEY_F21 _EVDEVK(0x0bf) KEY_F21 */ /* Use: XKB_KEY_F22 _EVDEVK(0x0c0) KEY_F22 */ /* Use: XKB_KEY_F23 _EVDEVK(0x0c1) KEY_F23 */ /* Use: XKB_KEY_F24 _EVDEVK(0x0c2) KEY_F24 */ /* TODO: Use XKB_KEY_XF86AudioPlay? _EVDEVK(0x0c8) KEY_PLAYCD */ /* TODO: Use XKB_KEY_XF86AudioPause? _EVDEVK(0x0c9) KEY_PAUSECD */ /* Use: XKB_KEY_XF86Launch3 _EVDEVK(0x0ca) KEY_PROG3 */ /* Use: XKB_KEY_XF86Launch4 _EVDEVK(0x0cb) KEY_PROG4 */ /* NOTE: KEY_DASHBOARD has been mapped to LaunchB in xkeyboard-config since 2011 */ /* Use: XKB_KEY_XF86LaunchB _EVDEVK(0x0cc) v2.6.28 KEY_DASHBOARD */ /* Use: XKB_KEY_XF86Suspend _EVDEVK(0x0cd) KEY_SUSPEND */ /* Use: XKB_KEY_XF86Close _EVDEVK(0x0ce) KEY_CLOSE */ /* TODO: Use XKB_KEY_XF86AudioPlay? _EVDEVK(0x0cf) KEY_PLAY */ /* TODO: Use XKB_KEY_XF86AudioForward? _EVDEVK(0x0d0) KEY_FASTFORWARD */ /* TODO: XKB_KEY_XF86AudioBassBoost? _EVDEVK(0x0d1) KEY_BASSBOOST */ /* Use: XKB_KEY_Print _EVDEVK(0x0d2) KEY_PRINT */ /* TODO: headphone or vendor key? _EVDEVK(0x0d3) KEY_HP */ /* Use: XKB_KEY_XF86WebCam _EVDEVK(0x0d4) KEY_CAMERA */ /* TODO: unclear function _EVDEVK(0x0d5) KEY_SOUND */ /* TODO: unclear function _EVDEVK(0x0d6) KEY_QUESTION */ /* Use: XKB_KEY_XF86Mail _EVDEVK(0x0d7) KEY_EMAIL */ /* Use: XKB_KEY_XF86Messenger _EVDEVK(0x0d8) KEY_CHAT */ /* Use: XKB_KEY_XF86Search _EVDEVK(0x0d9) KEY_SEARCH */ /* TODO: unclear function _EVDEVK(0x0da) KEY_CONNECT */ /* Use: XKB_KEY_XF86Finance _EVDEVK(0x0db) KEY_FINANCE */ #define XKB_KEY_XF86Sport 0x100810dc /* KEY_SPORT */ /* Use: XKB_KEY_XF86Shop _EVDEVK(0x0dd) KEY_SHOP */ /* TODO: unclear function _EVDEVK(0x0de) KEY_ALTERASE */ /* Use: XKB_KEY_Cancel _EVDEVK(0x0df) KEY_CANCEL */ /* Use: XKB_KEY_XF86MonBrightnessDown _EVDEVK(0x0e0) KEY_BRIGHTNESSDOWN */ /* Use: XKB_KEY_XF86MonBrightnessUp _EVDEVK(0x0e1) KEY_BRIGHTNESSUP */ /* Use: XKB_KEY_XF86AudioMedia _EVDEVK(0x0e2) KEY_MEDIA */ /* Use: XKB_KEY_XF86Display _EVDEVK(0x0e3) v2.6.12 KEY_SWITCHVIDEOMODE */ /* Use: XKB_KEY_XF86KbdLightOnOff _EVDEVK(0x0e4) v2.6.12 KEY_KBDILLUMTOGGLE */ /* Use: XKB_KEY_XF86KbdBrightnessDown _EVDEVK(0x0e5) v2.6.12 KEY_KBDILLUMDOWN */ /* Use: XKB_KEY_XF86KbdBrightnessUp _EVDEVK(0x0e6) v2.6.12 KEY_KBDILLUMUP */ /* Use: XKB_KEY_XF86Send _EVDEVK(0x0e7) v2.6.14 KEY_SEND */ /* Use: XKB_KEY_XF86Reply _EVDEVK(0x0e8) v2.6.14 KEY_REPLY */ /* Use: XKB_KEY_XF86MailForward _EVDEVK(0x0e9) v2.6.14 KEY_FORWARDMAIL */ /* Use: XKB_KEY_XF86Save _EVDEVK(0x0ea) v2.6.14 KEY_SAVE */ /* Use: XKB_KEY_XF86Documents _EVDEVK(0x0eb) v2.6.14 KEY_DOCUMENTS */ /* Use: XKB_KEY_XF86Battery _EVDEVK(0x0ec) v2.6.17 KEY_BATTERY */ /* Use: XKB_KEY_XF86Bluetooth _EVDEVK(0x0ed) v2.6.19 KEY_BLUETOOTH */ /* Use: XKB_KEY_XF86WLAN _EVDEVK(0x0ee) v2.6.19 KEY_WLAN */ /* Use: XKB_KEY_XF86UWB _EVDEVK(0x0ef) v2.6.24 KEY_UWB */ /* Use: NoSymbol _EVDEVK(0x0f0) KEY_UNKNOWN */ /* Use: XKB_KEY_XF86Next_VMode _EVDEVK(0x0f1) v2.6.23 KEY_VIDEO_NEXT */ /* Use: XKB_KEY_XF86Prev_VMode _EVDEVK(0x0f2) v2.6.23 KEY_VIDEO_PREV */ /* Use: XKB_KEY_XF86MonBrightnessCycle _EVDEVK(0x0f3) v2.6.23 KEY_BRIGHTNESS_CYCLE */ #define XKB_KEY_XF86BrightnessAuto 0x100810f4 /* Deprecated alias for XF86MonBrightnessAuto */ #define XKB_KEY_XF86MonBrightnessAuto 0x100810f4 /* v3.16 KEY_BRIGHTNESS_AUTO */ #define XKB_KEY_XF86DisplayOff 0x100810f5 /* v2.6.23 KEY_DISPLAY_OFF */ /* Use: XKB_KEY_XF86WWAN _EVDEVK(0x0f6) v3.13 KEY_WWAN */ /* Use: XKB_KEY_XF86RFKill _EVDEVK(0x0f7) v2.6.33 KEY_RFKILL */ /* Use: XKB_KEY_XF86AudioMicMute _EVDEVK(0x0f8) v3.1 KEY_MICMUTE */ #define XKB_KEY_XF86OK 0x10081160 /* v2.5.26 KEY_OK */ /* Use: XKB_KEY_XF86Select _EVDEVK(0x161) v2.5.26 KEY_SELECT */ #define XKB_KEY_XF86GoTo 0x10081162 /* v2.5.26 KEY_GOTO */ /* Use: XKB_KEY_XF86Clear _EVDEVK(0x163) v2.5.26 KEY_CLEAR */ /* TODO: Unclear function _EVDEVK(0x164) v2.5.26 KEY_POWER2 */ /* Use: XKB_KEY_XF86Option _EVDEVK(0x165) v2.5.26 KEY_OPTION */ #define XKB_KEY_XF86Info 0x10081166 /* v2.5.26 KEY_INFO */ /* Use: XKB_KEY_XF86Time _EVDEVK(0x167) v2.5.26 KEY_TIME */ #define XKB_KEY_XF86VendorLogo 0x10081168 /* v2.5.26 KEY_VENDOR */ /* TODO: unclear function _EVDEVK(0x169) v2.5.26 KEY_ARCHIVE */ #define XKB_KEY_XF86MediaSelectProgramGuide 0x1008116a /* v2.5.26 KEY_PROGRAM */ /* Use: XKB_KEY_XF86NextFavorite _EVDEVK(0x16b) v2.5.26 KEY_CHANNEL */ /* Use: XKB_KEY_XF86Favorites _EVDEVK(0x16c) v2.5.26 KEY_FAVORITES */ /* Use: XKB_KEY_XF86MediaSelectProgramGuide _EVDEVK(0x16d) v2.5.26 KEY_EPG */ #define XKB_KEY_XF86MediaSelectHome 0x1008116e /* v2.5.26 KEY_PVR */ /* TODO: Multimedia Home Platform _EVDEVK(0x16f) v2.5.26 KEY_MHP */ #define XKB_KEY_XF86MediaLanguageMenu 0x10081170 /* v2.5.26 KEY_LANGUAGE */ #define XKB_KEY_XF86MediaTitleMenu 0x10081171 /* v2.5.26 KEY_TITLE */ /* Use: XKB_KEY_XF86Subtitle _EVDEVK(0x172) v2.5.26 KEY_SUBTITLE */ /* Use: XKB_KEY_XF86CycleAngle _EVDEVK(0x173) v2.5.26 KEY_ANGLE */ /* Use: XKB_KEY_XF86FullScreen _EVDEVK(0x174) v5.1 KEY_FULL_SCREEN */ #define XKB_KEY_XF86AudioChannelMode 0x10081175 /* v2.5.26 KEY_MODE */ /* Use: XKB_KEY_XF86Keyboard _EVDEVK(0x176) v2.5.26 KEY_KEYBOARD */ #define XKB_KEY_XF86AspectRatio 0x10081177 /* v5.1 KEY_ASPECT_RATIO */ #define XKB_KEY_XF86MediaSelectPC 0x10081178 /* v2.5.26 KEY_PC */ #define XKB_KEY_XF86MediaSelectTV 0x10081179 /* v2.5.26 KEY_TV */ #define XKB_KEY_XF86MediaSelectCable 0x1008117a /* v2.5.26 KEY_TV2 */ #define XKB_KEY_XF86MediaSelectVCR 0x1008117b /* v2.5.26 KEY_VCR */ #define XKB_KEY_XF86MediaSelectVCRPlus 0x1008117c /* v2.5.26 KEY_VCR2 */ #define XKB_KEY_XF86MediaSelectSatellite 0x1008117d /* v2.5.26 KEY_SAT */ /* TODO: unclear media selector _EVDEVK(0x17e) v2.5.26 KEY_SAT2 */ /* Use: XKB_KEY_XF86MediaSelectCD _EVDEVK(0x17f) v2.5.26 KEY_CD */ #define XKB_KEY_XF86MediaSelectTape 0x10081180 /* v2.5.26 KEY_TAPE */ #define XKB_KEY_XF86MediaSelectRadio 0x10081181 /* v2.5.26 KEY_RADIO */ #define XKB_KEY_XF86MediaSelectTuner 0x10081182 /* v2.5.26 KEY_TUNER */ #define XKB_KEY_XF86MediaPlayer 0x10081183 /* v2.5.26 KEY_PLAYER */ #define XKB_KEY_XF86MediaSelectTeletext 0x10081184 /* v2.5.26 KEY_TEXT */ #define XKB_KEY_XF86DVD 0x10081185 /* v2.5.26 KEY_DVD */ #define XKB_KEY_XF86MediaSelectDVD 0x10081185 /* Alias for XF86DVD */ #define XKB_KEY_XF86MediaSelectAuxiliary 0x10081186 /* v2.5.26 KEY_AUX */ /* TODO: unclear media selector _EVDEVK(0x187) v2.5.26 KEY_MP3 */ #define XKB_KEY_XF86Audio 0x10081188 /* v2.5.26 KEY_AUDIO */ /* Use: XKB_KEY_XF86Video _EVDEVK(0x189) v2.5.26 KEY_VIDEO */ /* TODO: unclear function _EVDEVK(0x18a) v2.5.26 KEY_DIRECTORY */ /* TODO: unclear function _EVDEVK(0x18b) v2.5.26 KEY_LIST */ /* Use: XKB_KEY_XF86Memo _EVDEVK(0x18c) v2.5.26 KEY_MEMO */ /* Use: XKB_KEY_XF86Calendar _EVDEVK(0x18d) v2.5.26 KEY_CALENDAR */ /* Use: XKB_KEY_XF86Red _EVDEVK(0x18e) v2.5.26 KEY_RED */ /* Use: XKB_KEY_XF86Green _EVDEVK(0x18f) v2.5.26 KEY_GREEN */ /* Use: XKB_KEY_XF86Yellow _EVDEVK(0x190) v2.5.26 KEY_YELLOW */ /* Use: XKB_KEY_XF86Blue _EVDEVK(0x191) v2.5.26 KEY_BLUE */ #define XKB_KEY_XF86ChannelUp 0x10081192 /* v2.5.26 KEY_CHANNELUP */ #define XKB_KEY_XF86ChannelDown 0x10081193 /* v2.5.26 KEY_CHANNELDOWN */ /* TODO: unclear function _EVDEVK(0x194) v2.5.26 KEY_FIRST */ /* TODO: unclear function _EVDEVK(0x195) v2.5.26 KEY_LAST */ /* TODO: unclear function _EVDEVK(0x196) v2.5.26 KEY_AB */ /* TODO: unclear function _EVDEVK(0x197) v2.5.26 KEY_NEXT */ /* TODO: unclear function _EVDEVK(0x198) v2.5.26 KEY_RESTART */ #define XKB_KEY_XF86MediaPlaySlow 0x10081199 /* v2.5.26 KEY_SLOW */ /* Use: XKB_KEY_XF86AudioRandomPlay _EVDEVK(0x19a) v2.5.26 KEY_SHUFFLE */ #define XKB_KEY_XF86Break 0x1008119b /* v2.5.26 KEY_BREAK */ /* TODO: unclear function _EVDEVK(0x19c) v2.5.26 KEY_PREVIOUS */ #define XKB_KEY_XF86NumberEntryMode 0x1008119d /* v2.5.26 KEY_DIGITS */ /* TODO: unclear function _EVDEVK(0x19e) v2.5.26 KEY_TEEN */ /* TODO: unclear function (Twenties?) _EVDEVK(0x19f) v2.5.26 KEY_TWEN */ #define XKB_KEY_XF86VideoPhone 0x100811a0 /* v2.6.20 KEY_VIDEOPHONE */ /* Use: XKB_KEY_XF86Game _EVDEVK(0x1a1) v2.6.20 KEY_GAMES */ /* Use: XKB_KEY_XF86ZoomIn _EVDEVK(0x1a2) v2.6.20 KEY_ZOOMIN */ /* Use: XKB_KEY_XF86ZoomOut _EVDEVK(0x1a3) v2.6.20 KEY_ZOOMOUT */ #define XKB_KEY_XF86ZoomReset 0x100811a4 /* v2.6.20 KEY_ZOOMRESET */ /* Use: XKB_KEY_XF86Word _EVDEVK(0x1a5) v2.6.20 KEY_WORDPROCESSOR */ #define XKB_KEY_XF86Editor 0x100811a6 /* v2.6.20 KEY_EDITOR */ /* Use: XKB_KEY_XF86Excel _EVDEVK(0x1a7) v2.6.20 KEY_SPREADSHEET */ #define XKB_KEY_XF86GraphicsEditor 0x100811a8 /* v2.6.20 KEY_GRAPHICSEDITOR */ #define XKB_KEY_XF86Presentation 0x100811a9 /* v2.6.20 KEY_PRESENTATION */ #define XKB_KEY_XF86Database 0x100811aa /* v2.6.20 KEY_DATABASE */ /* Use: XKB_KEY_XF86News _EVDEVK(0x1ab) v2.6.20 KEY_NEWS */ #define XKB_KEY_XF86Voicemail 0x100811ac /* v2.6.20 KEY_VOICEMAIL */ #define XKB_KEY_XF86Addressbook 0x100811ad /* v2.6.20 KEY_ADDRESSBOOK */ /* Use: XKB_KEY_XF86Messenger _EVDEVK(0x1ae) v2.6.20 KEY_MESSENGER */ #define XKB_KEY_XF86DisplayToggle 0x100811af /* v2.6.20 KEY_DISPLAYTOGGLE */ #define XKB_KEY_XF86SpellCheck 0x100811b0 /* v2.6.24 KEY_SPELLCHECK */ /* Use: XKB_KEY_XF86LogOff _EVDEVK(0x1b1) v2.6.24 KEY_LOGOFF */ /* Use: XKB_KEY_dollar _EVDEVK(0x1b2) v2.6.24 KEY_DOLLAR */ /* Use: XKB_KEY_EuroSign _EVDEVK(0x1b3) v2.6.24 KEY_EURO */ /* Use: XKB_KEY_XF86FrameBack _EVDEVK(0x1b4) v2.6.24 KEY_FRAMEBACK */ /* Use: XKB_KEY_XF86FrameForward _EVDEVK(0x1b5) v2.6.24 KEY_FRAMEFORWARD */ #define XKB_KEY_XF86ContextMenu 0x100811b6 /* v2.6.24 KEY_CONTEXT_MENU */ #define XKB_KEY_XF86MediaRepeat 0x100811b7 /* v2.6.26 KEY_MEDIA_REPEAT */ #define XKB_KEY_XF8610ChannelsUp 0x100811b8 /* v2.6.38 KEY_10CHANNELSUP */ #define XKB_KEY_XF8610ChannelsDown 0x100811b9 /* v2.6.38 KEY_10CHANNELSDOWN */ #define XKB_KEY_XF86Images 0x100811ba /* v2.6.39 KEY_IMAGES */ #define XKB_KEY_XF86NotificationCenter 0x100811bc /* v5.10 KEY_NOTIFICATION_CENTER */ #define XKB_KEY_XF86PickupPhone 0x100811bd /* v5.10 KEY_PICKUP_PHONE */ #define XKB_KEY_XF86HangupPhone 0x100811be /* v5.10 KEY_HANGUP_PHONE */ #define XKB_KEY_XF86LinkPhone 0x100811bf /* v6.14 KEY_LINK_PHONE */ /* TODO: XKB_KEY_XF86DeleteToEndOfLine? _EVDEVK(0x1c0) KEY_DEL_EOL */ /* TODO: XKB_KEY_XF86DeleteToEndOfScreen? _EVDEVK(0x1c1) KEY_DEL_EOS */ /* TODO: XKB_KEY_XF86InsertLine? _EVDEVK(0x1c2) KEY_INS_LINE */ /* TODO: XKB_KEY_XF86DeleteLine? _EVDEVK(0x1c3) KEY_DEL_LINE */ #define XKB_KEY_XF86Fn 0x100811d0 /* KEY_FN */ #define XKB_KEY_XF86Fn_Esc 0x100811d1 /* KEY_FN_ESC */ #define XKB_KEY_XF86Fn_F1 0x100811d2 /* KEY_FN_F1 */ #define XKB_KEY_XF86Fn_F2 0x100811d3 /* KEY_FN_F2 */ #define XKB_KEY_XF86Fn_F3 0x100811d4 /* KEY_FN_F3 */ #define XKB_KEY_XF86Fn_F4 0x100811d5 /* KEY_FN_F4 */ #define XKB_KEY_XF86Fn_F5 0x100811d6 /* KEY_FN_F5 */ #define XKB_KEY_XF86Fn_F6 0x100811d7 /* KEY_FN_F6 */ #define XKB_KEY_XF86Fn_F7 0x100811d8 /* KEY_FN_F7 */ #define XKB_KEY_XF86Fn_F8 0x100811d9 /* KEY_FN_F8 */ #define XKB_KEY_XF86Fn_F9 0x100811da /* KEY_FN_F9 */ #define XKB_KEY_XF86Fn_F10 0x100811db /* KEY_FN_F10 */ #define XKB_KEY_XF86Fn_F11 0x100811dc /* KEY_FN_F11 */ #define XKB_KEY_XF86Fn_F12 0x100811dd /* KEY_FN_F12 */ #define XKB_KEY_XF86Fn_1 0x100811de /* KEY_FN_1 */ #define XKB_KEY_XF86Fn_2 0x100811df /* KEY_FN_2 */ #define XKB_KEY_XF86Fn_D 0x100811e0 /* KEY_FN_D */ #define XKB_KEY_XF86Fn_E 0x100811e1 /* KEY_FN_E */ #define XKB_KEY_XF86Fn_F 0x100811e2 /* KEY_FN_F */ #define XKB_KEY_XF86Fn_S 0x100811e3 /* KEY_FN_S */ #define XKB_KEY_XF86Fn_B 0x100811e4 /* KEY_FN_B */ #define XKB_KEY_XF86FnRightShift 0x100811e5 /* v5.10 KEY_FN_RIGHT_SHIFT */ /* Use: XKB_KEY_braille_dot_1 _EVDEVK(0x1f1) v2.6.17 KEY_BRL_DOT1 */ /* Use: XKB_KEY_braille_dot_2 _EVDEVK(0x1f2) v2.6.17 KEY_BRL_DOT2 */ /* Use: XKB_KEY_braille_dot_3 _EVDEVK(0x1f3) v2.6.17 KEY_BRL_DOT3 */ /* Use: XKB_KEY_braille_dot_4 _EVDEVK(0x1f4) v2.6.17 KEY_BRL_DOT4 */ /* Use: XKB_KEY_braille_dot_5 _EVDEVK(0x1f5) v2.6.17 KEY_BRL_DOT5 */ /* Use: XKB_KEY_braille_dot_6 _EVDEVK(0x1f6) v2.6.17 KEY_BRL_DOT6 */ /* Use: XKB_KEY_braille_dot_7 _EVDEVK(0x1f7) v2.6.17 KEY_BRL_DOT7 */ /* Use: XKB_KEY_braille_dot_8 _EVDEVK(0x1f8) v2.6.17 KEY_BRL_DOT8 */ /* Use: XKB_KEY_braille_dot_9 _EVDEVK(0x1f9) v2.6.23 KEY_BRL_DOT9 */ /* Use: XKB_KEY_braille_dot_1 _EVDEVK(0x1fa) v2.6.23 KEY_BRL_DOT10 */ #define XKB_KEY_XF86Numeric0 0x10081200 /* v2.6.28 KEY_NUMERIC_0 */ #define XKB_KEY_XF86Numeric1 0x10081201 /* v2.6.28 KEY_NUMERIC_1 */ #define XKB_KEY_XF86Numeric2 0x10081202 /* v2.6.28 KEY_NUMERIC_2 */ #define XKB_KEY_XF86Numeric3 0x10081203 /* v2.6.28 KEY_NUMERIC_3 */ #define XKB_KEY_XF86Numeric4 0x10081204 /* v2.6.28 KEY_NUMERIC_4 */ #define XKB_KEY_XF86Numeric5 0x10081205 /* v2.6.28 KEY_NUMERIC_5 */ #define XKB_KEY_XF86Numeric6 0x10081206 /* v2.6.28 KEY_NUMERIC_6 */ #define XKB_KEY_XF86Numeric7 0x10081207 /* v2.6.28 KEY_NUMERIC_7 */ #define XKB_KEY_XF86Numeric8 0x10081208 /* v2.6.28 KEY_NUMERIC_8 */ #define XKB_KEY_XF86Numeric9 0x10081209 /* v2.6.28 KEY_NUMERIC_9 */ #define XKB_KEY_XF86NumericStar 0x1008120a /* v2.6.28 KEY_NUMERIC_STAR */ #define XKB_KEY_XF86NumericPound 0x1008120b /* v2.6.28 KEY_NUMERIC_POUND */ #define XKB_KEY_XF86NumericA 0x1008120c /* v4.1 KEY_NUMERIC_A */ #define XKB_KEY_XF86NumericB 0x1008120d /* v4.1 KEY_NUMERIC_B */ #define XKB_KEY_XF86NumericC 0x1008120e /* v4.1 KEY_NUMERIC_C */ #define XKB_KEY_XF86NumericD 0x1008120f /* v4.1 KEY_NUMERIC_D */ #define XKB_KEY_XF86CameraFocus 0x10081210 /* v2.6.33 KEY_CAMERA_FOCUS */ #define XKB_KEY_XF86WPSButton 0x10081211 /* v2.6.34 KEY_WPS_BUTTON */ /* Use: XKB_KEY_XF86TouchpadToggle _EVDEVK(0x212) v2.6.37 KEY_TOUCHPAD_TOGGLE */ /* Use: XKB_KEY_XF86TouchpadOn _EVDEVK(0x213) v2.6.37 KEY_TOUCHPAD_ON */ /* Use: XKB_KEY_XF86TouchpadOff _EVDEVK(0x214) v2.6.37 KEY_TOUCHPAD_OFF */ #define XKB_KEY_XF86CameraZoomIn 0x10081215 /* v2.6.39 KEY_CAMERA_ZOOMIN */ #define XKB_KEY_XF86CameraZoomOut 0x10081216 /* v2.6.39 KEY_CAMERA_ZOOMOUT */ #define XKB_KEY_XF86CameraUp 0x10081217 /* v2.6.39 KEY_CAMERA_UP */ #define XKB_KEY_XF86CameraDown 0x10081218 /* v2.6.39 KEY_CAMERA_DOWN */ #define XKB_KEY_XF86CameraLeft 0x10081219 /* v2.6.39 KEY_CAMERA_LEFT */ #define XKB_KEY_XF86CameraRight 0x1008121a /* v2.6.39 KEY_CAMERA_RIGHT */ #define XKB_KEY_XF86AttendantOn 0x1008121b /* v3.10 KEY_ATTENDANT_ON */ #define XKB_KEY_XF86AttendantOff 0x1008121c /* v3.10 KEY_ATTENDANT_OFF */ #define XKB_KEY_XF86AttendantToggle 0x1008121d /* v3.10 KEY_ATTENDANT_TOGGLE */ #define XKB_KEY_XF86LightsToggle 0x1008121e /* v3.10 KEY_LIGHTS_TOGGLE */ #define XKB_KEY_XF86ALSToggle 0x10081230 /* v3.13 KEY_ALS_TOGGLE */ /* Use: XKB_KEY_XF86RotationLockToggle _EVDEVK(0x231) v4.16 KEY_ROTATE_LOCK_TOGGLE */ #define XKB_KEY_XF86RefreshRateToggle 0x10081232 /* v6.9 KEY_REFRESH_RATE_TOGGLE */ #define XKB_KEY_XF86Buttonconfig 0x10081240 /* v3.16 KEY_BUTTONCONFIG */ #define XKB_KEY_XF86Taskmanager 0x10081241 /* v3.16 KEY_TASKMANAGER */ #define XKB_KEY_XF86Journal 0x10081242 /* v3.16 KEY_JOURNAL */ #define XKB_KEY_XF86ControlPanel 0x10081243 /* v3.16 KEY_CONTROLPANEL */ #define XKB_KEY_XF86AppSelect 0x10081244 /* v3.16 KEY_APPSELECT */ #define XKB_KEY_XF86Screensaver 0x10081245 /* v3.16 KEY_SCREENSAVER */ #define XKB_KEY_XF86VoiceCommand 0x10081246 /* v3.16 KEY_VOICECOMMAND */ #define XKB_KEY_XF86Assistant 0x10081247 /* v4.13 KEY_ASSISTANT */ /* Use: XKB_KEY_ISO_Next_Group _EVDEVK(0x248) v5.2 KEY_KBD_LAYOUT_NEXT */ #define XKB_KEY_XF86EmojiPicker 0x10081249 /* v5.13 KEY_EMOJI_PICKER */ #define XKB_KEY_XF86Dictate 0x1008124a /* v5.17 KEY_DICTATE */ #define XKB_KEY_XF86CameraAccessEnable 0x1008124b /* v6.2 KEY_CAMERA_ACCESS_ENABLE */ #define XKB_KEY_XF86CameraAccessDisable 0x1008124c /* v6.2 KEY_CAMERA_ACCESS_DISABLE */ #define XKB_KEY_XF86CameraAccessToggle 0x1008124d /* v6.2 KEY_CAMERA_ACCESS_TOGGLE */ #define XKB_KEY_XF86Accessibility 0x1008124e /* v6.10 KEY_ACCESSIBILITY */ #define XKB_KEY_XF86DoNotDisturb 0x1008124f /* v6.10 KEY_DO_NOT_DISTURB */ #define XKB_KEY_XF86BrightnessMin 0x10081250 /* v3.16 KEY_BRIGHTNESS_MIN */ #define XKB_KEY_XF86BrightnessMax 0x10081251 /* v3.16 KEY_BRIGHTNESS_MAX */ #define XKB_KEY_XF86KbdInputAssistPrev 0x10081260 /* v3.18 KEY_KBDINPUTASSIST_PREV */ #define XKB_KEY_XF86KbdInputAssistNext 0x10081261 /* v3.18 KEY_KBDINPUTASSIST_NEXT */ #define XKB_KEY_XF86KbdInputAssistPrevgroup 0x10081262 /* v3.18 KEY_KBDINPUTASSIST_PREVGROUP */ #define XKB_KEY_XF86KbdInputAssistNextgroup 0x10081263 /* v3.18 KEY_KBDINPUTASSIST_NEXTGROUP */ #define XKB_KEY_XF86KbdInputAssistAccept 0x10081264 /* v3.18 KEY_KBDINPUTASSIST_ACCEPT */ #define XKB_KEY_XF86KbdInputAssistCancel 0x10081265 /* v3.18 KEY_KBDINPUTASSIST_CANCEL */ #define XKB_KEY_XF86RightUp 0x10081266 /* v4.7 KEY_RIGHT_UP */ #define XKB_KEY_XF86RightDown 0x10081267 /* v4.7 KEY_RIGHT_DOWN */ #define XKB_KEY_XF86LeftUp 0x10081268 /* v4.7 KEY_LEFT_UP */ #define XKB_KEY_XF86LeftDown 0x10081269 /* v4.7 KEY_LEFT_DOWN */ #define XKB_KEY_XF86RootMenu 0x1008126a /* v4.7 KEY_ROOT_MENU */ #define XKB_KEY_XF86MediaTopMenu 0x1008126b /* v4.7 KEY_MEDIA_TOP_MENU */ #define XKB_KEY_XF86Numeric11 0x1008126c /* v4.7 KEY_NUMERIC_11 */ #define XKB_KEY_XF86Numeric12 0x1008126d /* v4.7 KEY_NUMERIC_12 */ #define XKB_KEY_XF86AudioDesc 0x1008126e /* v4.7 KEY_AUDIO_DESC */ #define XKB_KEY_XF863DMode 0x1008126f /* v4.7 KEY_3D_MODE */ #define XKB_KEY_XF86NextFavorite 0x10081270 /* v4.7 KEY_NEXT_FAVORITE */ #define XKB_KEY_XF86StopRecord 0x10081271 /* v4.7 KEY_STOP_RECORD */ #define XKB_KEY_XF86PauseRecord 0x10081272 /* v4.7 KEY_PAUSE_RECORD */ #define XKB_KEY_XF86VOD 0x10081273 /* v4.7 KEY_VOD */ #define XKB_KEY_XF86Unmute 0x10081274 /* v4.7 KEY_UNMUTE */ #define XKB_KEY_XF86FastReverse 0x10081275 /* v4.7 KEY_FASTREVERSE */ #define XKB_KEY_XF86SlowReverse 0x10081276 /* v4.7 KEY_SLOWREVERSE */ #define XKB_KEY_XF86Data 0x10081277 /* v4.7 KEY_DATA */ #define XKB_KEY_XF86OnScreenKeyboard 0x10081278 /* v4.12 KEY_ONSCREEN_KEYBOARD */ #define XKB_KEY_XF86PrivacyScreenToggle 0x10081279 /* v5.5 KEY_PRIVACY_SCREEN_TOGGLE */ #define XKB_KEY_XF86SelectiveScreenshot 0x1008127a /* v5.6 KEY_SELECTIVE_SCREENSHOT */ #define XKB_KEY_XF86NextElement 0x1008127b /* v5.18 KEY_NEXT_ELEMENT */ #define XKB_KEY_XF86PreviousElement 0x1008127c /* v5.18 KEY_PREVIOUS_ELEMENT */ #define XKB_KEY_XF86AutopilotEngageToggle 0x1008127d /* v5.18 KEY_AUTOPILOT_ENGAGE_TOGGLE */ #define XKB_KEY_XF86MarkWaypoint 0x1008127e /* v5.18 KEY_MARK_WAYPOINT */ #define XKB_KEY_XF86Sos 0x1008127f /* v5.18 KEY_SOS */ #define XKB_KEY_XF86NavChart 0x10081280 /* v5.18 KEY_NAV_CHART */ #define XKB_KEY_XF86FishingChart 0x10081281 /* v5.18 KEY_FISHING_CHART */ #define XKB_KEY_XF86SingleRangeRadar 0x10081282 /* v5.18 KEY_SINGLE_RANGE_RADAR */ #define XKB_KEY_XF86DualRangeRadar 0x10081283 /* v5.18 KEY_DUAL_RANGE_RADAR */ #define XKB_KEY_XF86RadarOverlay 0x10081284 /* v5.18 KEY_RADAR_OVERLAY */ #define XKB_KEY_XF86TraditionalSonar 0x10081285 /* v5.18 KEY_TRADITIONAL_SONAR */ #define XKB_KEY_XF86ClearvuSonar 0x10081286 /* v5.18 KEY_CLEARVU_SONAR */ #define XKB_KEY_XF86SidevuSonar 0x10081287 /* v5.18 KEY_SIDEVU_SONAR */ #define XKB_KEY_XF86NavInfo 0x10081288 /* v5.18 KEY_NAV_INFO */ /* Use: XKB_KEY_XF86BrightnessAdjust _EVDEVK(0x289) v5.18 KEY_BRIGHTNESS_MENU */ #define XKB_KEY_XF86Macro1 0x10081290 /* v5.5 KEY_MACRO1 */ #define XKB_KEY_XF86Macro2 0x10081291 /* v5.5 KEY_MACRO2 */ #define XKB_KEY_XF86Macro3 0x10081292 /* v5.5 KEY_MACRO3 */ #define XKB_KEY_XF86Macro4 0x10081293 /* v5.5 KEY_MACRO4 */ #define XKB_KEY_XF86Macro5 0x10081294 /* v5.5 KEY_MACRO5 */ #define XKB_KEY_XF86Macro6 0x10081295 /* v5.5 KEY_MACRO6 */ #define XKB_KEY_XF86Macro7 0x10081296 /* v5.5 KEY_MACRO7 */ #define XKB_KEY_XF86Macro8 0x10081297 /* v5.5 KEY_MACRO8 */ #define XKB_KEY_XF86Macro9 0x10081298 /* v5.5 KEY_MACRO9 */ #define XKB_KEY_XF86Macro10 0x10081299 /* v5.5 KEY_MACRO10 */ #define XKB_KEY_XF86Macro11 0x1008129a /* v5.5 KEY_MACRO11 */ #define XKB_KEY_XF86Macro12 0x1008129b /* v5.5 KEY_MACRO12 */ #define XKB_KEY_XF86Macro13 0x1008129c /* v5.5 KEY_MACRO13 */ #define XKB_KEY_XF86Macro14 0x1008129d /* v5.5 KEY_MACRO14 */ #define XKB_KEY_XF86Macro15 0x1008129e /* v5.5 KEY_MACRO15 */ #define XKB_KEY_XF86Macro16 0x1008129f /* v5.5 KEY_MACRO16 */ #define XKB_KEY_XF86Macro17 0x100812a0 /* v5.5 KEY_MACRO17 */ #define XKB_KEY_XF86Macro18 0x100812a1 /* v5.5 KEY_MACRO18 */ #define XKB_KEY_XF86Macro19 0x100812a2 /* v5.5 KEY_MACRO19 */ #define XKB_KEY_XF86Macro20 0x100812a3 /* v5.5 KEY_MACRO20 */ #define XKB_KEY_XF86Macro21 0x100812a4 /* v5.5 KEY_MACRO21 */ #define XKB_KEY_XF86Macro22 0x100812a5 /* v5.5 KEY_MACRO22 */ #define XKB_KEY_XF86Macro23 0x100812a6 /* v5.5 KEY_MACRO23 */ #define XKB_KEY_XF86Macro24 0x100812a7 /* v5.5 KEY_MACRO24 */ #define XKB_KEY_XF86Macro25 0x100812a8 /* v5.5 KEY_MACRO25 */ #define XKB_KEY_XF86Macro26 0x100812a9 /* v5.5 KEY_MACRO26 */ #define XKB_KEY_XF86Macro27 0x100812aa /* v5.5 KEY_MACRO27 */ #define XKB_KEY_XF86Macro28 0x100812ab /* v5.5 KEY_MACRO28 */ #define XKB_KEY_XF86Macro29 0x100812ac /* v5.5 KEY_MACRO29 */ #define XKB_KEY_XF86Macro30 0x100812ad /* v5.5 KEY_MACRO30 */ #define XKB_KEY_XF86MacroRecordStart 0x100812b0 /* v5.5 KEY_MACRO_RECORD_START */ #define XKB_KEY_XF86MacroRecordStop 0x100812b1 /* v5.5 KEY_MACRO_RECORD_STOP */ #define XKB_KEY_XF86MacroPresetCycle 0x100812b2 /* v5.5 KEY_MACRO_PRESET_CYCLE */ #define XKB_KEY_XF86MacroPreset1 0x100812b3 /* v5.5 KEY_MACRO_PRESET1 */ #define XKB_KEY_XF86MacroPreset2 0x100812b4 /* v5.5 KEY_MACRO_PRESET2 */ #define XKB_KEY_XF86MacroPreset3 0x100812b5 /* v5.5 KEY_MACRO_PRESET3 */ #define XKB_KEY_XF86KbdLcdMenu1 0x100812b8 /* v5.5 KEY_KBD_LCD_MENU1 */ #define XKB_KEY_XF86KbdLcdMenu2 0x100812b9 /* v5.5 KEY_KBD_LCD_MENU2 */ #define XKB_KEY_XF86KbdLcdMenu3 0x100812ba /* v5.5 KEY_KBD_LCD_MENU3 */ #define XKB_KEY_XF86KbdLcdMenu4 0x100812bb /* v5.5 KEY_KBD_LCD_MENU4 */ #define XKB_KEY_XF86KbdLcdMenu5 0x100812bc /* v5.5 KEY_KBD_LCD_MENU5 */ #define XKB_KEY_XF86PerformanceMode 0x100812bd /* v6.17 KEY_PERFORMANCE */ /* * Copyright (c) 1991, Oracle and/or its affiliates. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /************************************************************ Copyright 1991, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. ***********************************************************/ /* * Floating Accent */ #define XKB_KEY_SunFA_Grave 0x1005ff00 #define XKB_KEY_SunFA_Circum 0x1005ff01 #define XKB_KEY_SunFA_Tilde 0x1005ff02 #define XKB_KEY_SunFA_Acute 0x1005ff03 #define XKB_KEY_SunFA_Diaeresis 0x1005ff04 #define XKB_KEY_SunFA_Cedilla 0x1005ff05 /* * Miscellaneous Functions */ #define XKB_KEY_SunF36 0x1005ff10 /* Labeled F11 */ #define XKB_KEY_SunF37 0x1005ff11 /* Labeled F12 */ #define XKB_KEY_SunSys_Req 0x1005ff60 #define XKB_KEY_SunPrint_Screen 0x0000ff61 /* Same as XKB_KEY_Print */ /* * International & Multi-Key Character Composition */ #define XKB_KEY_SunCompose 0x0000ff20 /* Same as XKB_KEY_Multi_key */ #define XKB_KEY_SunAltGraph 0x0000ff7e /* Same as XKB_KEY_Mode_switch */ /* * Cursor Control */ #define XKB_KEY_SunPageUp 0x0000ff55 /* Same as XKB_KEY_Prior */ #define XKB_KEY_SunPageDown 0x0000ff56 /* Same as XKB_KEY_Next */ /* * Open Look Functions */ #define XKB_KEY_SunUndo 0x0000ff65 /* Same as XKB_KEY_Undo */ #define XKB_KEY_SunAgain 0x0000ff66 /* Same as XKB_KEY_Redo */ #define XKB_KEY_SunFind 0x0000ff68 /* Same as XKB_KEY_Find */ #define XKB_KEY_SunStop 0x0000ff69 /* Same as XKB_KEY_Cancel */ #define XKB_KEY_SunProps 0x1005ff70 #define XKB_KEY_SunFront 0x1005ff71 #define XKB_KEY_SunCopy 0x1005ff72 #define XKB_KEY_SunOpen 0x1005ff73 #define XKB_KEY_SunPaste 0x1005ff74 #define XKB_KEY_SunCut 0x1005ff75 #define XKB_KEY_SunPowerSwitch 0x1005ff76 #define XKB_KEY_SunAudioLowerVolume 0x1005ff77 #define XKB_KEY_SunAudioMute 0x1005ff78 #define XKB_KEY_SunAudioRaiseVolume 0x1005ff79 #define XKB_KEY_SunVideoDegauss 0x1005ff7a #define XKB_KEY_SunVideoLowerBrightness 0x1005ff7b #define XKB_KEY_SunVideoRaiseBrightness 0x1005ff7c #define XKB_KEY_SunPowerSwitchShift 0x1005ff7d /*********************************************************** Copyright 1988, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. Copyright 1988 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ /* * DEC private keysyms * (29th bit set) */ /* two-key compose sequence initiators, chosen to map to Latin1 characters */ #define XKB_KEY_Dring_accent 0x1000feb0 #define XKB_KEY_Dcircumflex_accent 0x1000fe5e #define XKB_KEY_Dcedilla_accent 0x1000fe2c #define XKB_KEY_Dacute_accent 0x1000fe27 #define XKB_KEY_Dgrave_accent 0x1000fe60 #define XKB_KEY_Dtilde 0x1000fe7e #define XKB_KEY_Ddiaeresis 0x1000fe22 /* special keysym for LK2** "Remove" key on editing keypad */ #define XKB_KEY_DRemove 0x1000ff00 /* Remove */ /* Copyright 1987, 1998 The Open Group Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted without fee, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Except as contained in this notice, the name of The Open Group shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from The Open Group. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Hewlett Packard or Digital not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THIS SOFTWARE, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Hewlett-Packard shall not be liable for errors contained herein or direct, indirect, special, incidental or consequential damages in connection with the furnishing, performance, or use of this material. */ #define XKB_KEY_hpClearLine 0x1000ff6f #define XKB_KEY_hpInsertLine 0x1000ff70 #define XKB_KEY_hpDeleteLine 0x1000ff71 #define XKB_KEY_hpInsertChar 0x1000ff72 #define XKB_KEY_hpDeleteChar 0x1000ff73 #define XKB_KEY_hpBackTab 0x1000ff74 #define XKB_KEY_hpKP_BackTab 0x1000ff75 #define XKB_KEY_hpModelock1 0x1000ff48 #define XKB_KEY_hpModelock2 0x1000ff49 #define XKB_KEY_hpReset 0x1000ff6c #define XKB_KEY_hpSystem 0x1000ff6d #define XKB_KEY_hpUser 0x1000ff6e #define XKB_KEY_hpmute_acute 0x100000a8 #define XKB_KEY_hpmute_grave 0x100000a9 #define XKB_KEY_hpmute_asciicircum 0x100000aa #define XKB_KEY_hpmute_diaeresis 0x100000ab #define XKB_KEY_hpmute_asciitilde 0x100000ac #define XKB_KEY_hplira 0x100000af #define XKB_KEY_hpguilder 0x100000be #define XKB_KEY_hpYdiaeresis 0x100000ee #define XKB_KEY_hpIO 0x100000ee /* deprecated alias for hpYdiaeresis */ #define XKB_KEY_hplongminus 0x100000f6 #define XKB_KEY_hpblock 0x100000fc #define XKB_KEY_osfCopy 0x1004ff02 #define XKB_KEY_osfCut 0x1004ff03 #define XKB_KEY_osfPaste 0x1004ff04 #define XKB_KEY_osfBackTab 0x1004ff07 #define XKB_KEY_osfBackSpace 0x1004ff08 #define XKB_KEY_osfClear 0x1004ff0b #define XKB_KEY_osfEscape 0x1004ff1b #define XKB_KEY_osfAddMode 0x1004ff31 #define XKB_KEY_osfPrimaryPaste 0x1004ff32 #define XKB_KEY_osfQuickPaste 0x1004ff33 #define XKB_KEY_osfPageLeft 0x1004ff40 #define XKB_KEY_osfPageUp 0x1004ff41 #define XKB_KEY_osfPageDown 0x1004ff42 #define XKB_KEY_osfPageRight 0x1004ff43 #define XKB_KEY_osfActivate 0x1004ff44 #define XKB_KEY_osfMenuBar 0x1004ff45 #define XKB_KEY_osfLeft 0x1004ff51 #define XKB_KEY_osfUp 0x1004ff52 #define XKB_KEY_osfRight 0x1004ff53 #define XKB_KEY_osfDown 0x1004ff54 #define XKB_KEY_osfEndLine 0x1004ff57 #define XKB_KEY_osfBeginLine 0x1004ff58 #define XKB_KEY_osfEndData 0x1004ff59 #define XKB_KEY_osfBeginData 0x1004ff5a #define XKB_KEY_osfPrevMenu 0x1004ff5b #define XKB_KEY_osfNextMenu 0x1004ff5c #define XKB_KEY_osfPrevField 0x1004ff5d #define XKB_KEY_osfNextField 0x1004ff5e #define XKB_KEY_osfSelect 0x1004ff60 #define XKB_KEY_osfInsert 0x1004ff63 #define XKB_KEY_osfUndo 0x1004ff65 #define XKB_KEY_osfMenu 0x1004ff67 #define XKB_KEY_osfCancel 0x1004ff69 #define XKB_KEY_osfHelp 0x1004ff6a #define XKB_KEY_osfSelectAll 0x1004ff71 #define XKB_KEY_osfDeselectAll 0x1004ff72 #define XKB_KEY_osfReselect 0x1004ff73 #define XKB_KEY_osfExtend 0x1004ff74 #define XKB_KEY_osfRestore 0x1004ff78 #define XKB_KEY_osfDelete 0x1004ffff /************************************************************** * The use of the following macros is deprecated. * They are listed below only for backwards compatibility. */ #define XKB_KEY_Reset 0x1000ff6c /* deprecated alias for hpReset */ #define XKB_KEY_System 0x1000ff6d /* deprecated alias for hpSystem */ #define XKB_KEY_User 0x1000ff6e /* deprecated alias for hpUser */ #define XKB_KEY_ClearLine 0x1000ff6f /* deprecated alias for hpClearLine */ #define XKB_KEY_InsertLine 0x1000ff70 /* deprecated alias for hpInsertLine */ #define XKB_KEY_DeleteLine 0x1000ff71 /* deprecated alias for hpDeleteLine */ #define XKB_KEY_InsertChar 0x1000ff72 /* deprecated alias for hpInsertChar */ #define XKB_KEY_DeleteChar 0x1000ff73 /* deprecated alias for hpDeleteChar */ #define XKB_KEY_BackTab 0x1000ff74 /* deprecated alias for hpBackTab */ #define XKB_KEY_KP_BackTab 0x1000ff75 /* deprecated alias for hpKP_BackTab */ #define XKB_KEY_Ext16bit_L 0x1000ff76 /* deprecated */ #define XKB_KEY_Ext16bit_R 0x1000ff77 /* deprecated */ #define XKB_KEY_mute_acute 0x100000a8 /* deprecated alias for hpmute_acute */ #define XKB_KEY_mute_grave 0x100000a9 /* deprecated alias for hpmute_grave */ #define XKB_KEY_mute_asciicircum 0x100000aa /* deprecated alias for hpmute_asciicircum */ #define XKB_KEY_mute_diaeresis 0x100000ab /* deprecated alias for hpmute_diaeresis */ #define XKB_KEY_mute_asciitilde 0x100000ac /* deprecated alias for hpmute_asciitilde */ #define XKB_KEY_lira 0x100000af /* deprecated alias for hplira */ #define XKB_KEY_guilder 0x100000be /* deprecated alias for hpguilder */ #define XKB_KEY_IO 0x100000ee /* deprecated alias for hpYdiaeresis */ #define XKB_KEY_longminus 0x100000f6 /* deprecated alias for hplongminus */ #define XKB_KEY_block 0x100000fc /* deprecated alias for hpblock */ #endif xkbcommon-libxkbcommon-54ee7ac/include/xkbcommon/xkbcommon-names.h000066400000000000000000000075021510033435100255560ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #ifndef _XKBCOMMON_NAMES_H #define _XKBCOMMON_NAMES_H /** * @file * @brief Predefined names for common modifiers and LEDs. */ /** * @defgroup modifier-names Predefined names for common modifiers and LEDs * * @{ */ /** * @defgroup real-modifier-names Real modifiers names * * [*Real* modifiers][real modifier] names are hardcoded in libxkbcommon. * * [real modifier]: @ref real-modifier-def * * @{ */ #define XKB_MOD_NAME_SHIFT "Shift" #define XKB_MOD_NAME_CAPS "Lock" #define XKB_MOD_NAME_CTRL "Control" #define XKB_MOD_NAME_MOD1 "Mod1" #define XKB_MOD_NAME_MOD2 "Mod2" #define XKB_MOD_NAME_MOD3 "Mod3" #define XKB_MOD_NAME_MOD4 "Mod4" #define XKB_MOD_NAME_MOD5 "Mod5" /** @} */ /** * @defgroup virtual-modifier-names Virtual modifiers names * * Common [*virtual* modifiers][virtual modifiers], encoded in [xkeyboard-config] * in the [compat] and [symbols] files. They have been stable since the beginning * of the project and are unlikely to ever change. * * [virtual modifiers]: @ref virtual-modifier-def * [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config * [compat]: @ref the-xkb_compat-section * [symbols]: @ref the-xkb_symbols-section * * @{ */ /** @since 1.8.0 */ #define XKB_VMOD_NAME_ALT "Alt" /** @since 1.8.0 */ #define XKB_VMOD_NAME_HYPER "Hyper" /** @since 1.8.0 */ #define XKB_VMOD_NAME_LEVEL3 "LevelThree" /** @since 1.8.0 */ #define XKB_VMOD_NAME_LEVEL5 "LevelFive" /** @since 1.8.0 */ #define XKB_VMOD_NAME_META "Meta" /** @since 1.8.0 */ #define XKB_VMOD_NAME_NUM "NumLock" /** @since 1.8.0 */ #define XKB_VMOD_NAME_SCROLL "ScrollLock" /** @since 1.8.0 */ #define XKB_VMOD_NAME_SUPER "Super" /** @} */ /** * @defgroup legacy-virtual-modifier-names Legacy virtual modifier names * * Usual [*virtual* modifiers][virtual modifiers] mappings to * [*real* modifiers][real modifiers]. * * @deprecated Use @ref virtual-modifier-names instead * * [virtual modifiers]: @ref virtual-modifier-def * [real modifiers]: @ref real-modifier-def * * @{ */ /** * Usual [*real* modifier][real modifier] for the * [*virtual* modifier][virtual modifier] `Alt`. * * @deprecated Use `::XKB_VMOD_NAME_ALT` instead. * @since 1.10: deprecated * * [virtual modifier]: @ref virtual-modifier-def * [real modifier]: @ref real-modifier-def */ #define XKB_MOD_NAME_ALT "Mod1" /** * Usual [*real* modifier][real modifier] for the * [*virtual* modifier][virtual modifier] `Super`. * * @deprecated Use `::XKB_VMOD_NAME_SUPER` instead. * @since 1.10: deprecated * * [virtual modifier]: @ref virtual-modifier-def * [real modifier]: @ref real-modifier-def */ #define XKB_MOD_NAME_LOGO "Mod4" /** * Usual [*real* modifier][real modifier] for the * [*virtual* modifier][virtual modifier] `NumLock`. * * @deprecated Use `::XKB_VMOD_NAME_NUM` instead. * @since 1.10: deprecated * * [virtual modifier]: @ref virtual-modifier-def * [real modifier]: @ref real-modifier-def */ #define XKB_MOD_NAME_NUM "Mod2" /** @} */ /** * @defgroup led-names LEDs names * * LEDs names are encoded in [xkeyboard-config], in the [keycodes] and [compat] * files. They have been stable since the beginning of the project and are * unlikely to ever change. * * [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config * [keycodes]: @ref the-xkb_keycodes-section * [compat]: @ref the-xkb_compat-section * * @{ */ #define XKB_LED_NAME_NUM "Num Lock" #define XKB_LED_NAME_CAPS "Caps Lock" #define XKB_LED_NAME_SCROLL "Scroll Lock" /** @since 1.8.0 */ #define XKB_LED_NAME_COMPOSE "Compose" #define XKB_LED_NAME_KANA "Kana" /** @} */ /** @} */ #endif xkbcommon-libxkbcommon-54ee7ac/include/xkbcommon/xkbcommon-x11.h000066400000000000000000000201161510033435100250600ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #ifndef _XKBCOMMON_X11_H #define _XKBCOMMON_X11_H #include #include #ifdef __cplusplus extern "C" { #endif /** * @file * libxkbcommon-x11 API - Additional X11 support for xkbcommon. */ /** * @defgroup x11 X11 support * Additional X11 support for xkbcommon. * @since 0.4.0 * * @{ */ /** * @page x11-overview Overview * @parblock * * The xkbcommon-x11 module provides a means for creating an xkb_keymap * corresponding to the currently active keymap on the X server. To do * so, it queries the XKB X11 extension using the xcb-xkb library. It * can be used as a replacement for Xlib’s keyboard handling. * * Following is an example workflow using xkbcommon-x11. A complete * example may be found in the `tools/interactive-x11.c` file in the * xkbcommon source repository. On startup: * * 1. Connect to the X server using `xcb_connect()`. * 2. Setup the XKB X11 extension. You can do this either by using the * `xcb_xkb_use_extension()` request directly, or by using the * `xkb_x11_setup_xkb_extension()` helper function. * * The XKB extension supports using separate keymaps and states for * different keyboard devices. The devices are identified by an integer * device ID and are managed by another X11 extension, XInput. The * original X11 protocol only had one keyboard device, called the *core * keyboard*, which is still supported as a *virtual device*. * * 3. We will use the core keyboard as an example. To get its device ID, * use either the `xcb_xkb_get_device_info()` request directly, or the * `xkb_x11_get_core_keyboard_device_id()` helper function. * 4. Create an initial xkb_keymap for this device, using the * `xkb_x11_keymap_new_from_device()` function. * 5. Create an initial xkb_state for this device, using the * `xkb_x11_state_new_from_device()` function. * * @note At this point, you may consider setting various XKB controls and * XKB per-client flags. For example, enabling detectable autorepeat: \n * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Detectable_Autorepeat * * Next, you need to react to state changes (e.g. a modifier was pressed, * the layout was changed) and to keymap changes (e.g. a tool like xkbcomp, * setxkbmap or xmodmap was used): * * 6. Select to listen to at least the following XKB events: * `NewKeyboardNotify`, `MapNotify`, `StateNotify`; using the * `xcb_xkb_select_events_aux()` request. * 7. When `NewKeyboardNotify` or `MapNotify` are received, recreate the * `xkb_keymap` and `xkb_state` as described above. * 8. When `StateNotify` is received, update the `xkb_state` accordingly * using the `xkb_state::xkb_state_update_mask()` function. * * @note It is also possible to use the `KeyPress`/`KeyRelease` @p state * field to find the effective modifier and layout state, instead of * using `XkbStateNotify`: \n * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Computing_A_State_Field_from_an_XKB_State * \n However, `XkbStateNotify` is more accurate. * * @note There is no need to call `xkb_state_update_key()`; the state is * already synchronized. * * Finally, when a key event is received, you can use ordinary xkbcommon * functions, like `xkb_state::xkb_state_key_get_one_sym()` and * `xkb_state::xkb_state_key_get_utf8()`, as you normally would. * * @endparblock */ /** * The minimal compatible major version of the XKB X11 extension which * this library can use. */ #define XKB_X11_MIN_MAJOR_XKB_VERSION 1 /** * The minimal compatible minor version of the XKB X11 extension which * this library can use (for the minimal major version). */ #define XKB_X11_MIN_MINOR_XKB_VERSION 0 /** Flags for the `xkb_x11_setup_xkb_extension()` function. */ enum xkb_x11_setup_xkb_extension_flags { /** Do not apply any flags. */ XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS = 0 }; /** * Setup the XKB X11 extension for this X client. * * The xkbcommon-x11 library uses various XKB requests. Before doing so, * an X client must notify the server that it will be using the extension. * This function (or an XCB equivalent) must be called before any other * function in this library is used. * * Some X servers may not support or disable the XKB extension. If you * want to support such servers, you need to use a different fallback. * * You may call this function several times; it is idempotent. * * @param connection * An XCB connection to the X server. * @param major_xkb_version * See @p minor_xkb_version. * @param minor_xkb_version * The XKB extension version to request. To operate correctly, you * must have (@p major_xkb_version, @p minor_xkb_version) >= * (`XKB_X11_MIN_MAJOR_XKB_VERSION`, `XKB_X11_MIN_MINOR_XKB_VERSION`), * though this is not enforced. * @param flags * Optional flags, or 0. * @param[out] major_xkb_version_out * See @p minor_xkb_version_out. * @param[out] minor_xkb_version_out * Backfilled with the compatible XKB extension version numbers picked * by the server. Can be `NULL`. * @param[out] base_event_out * Backfilled with the XKB base (also known as first) event code, needed * to distinguish XKB events. Can be `NULL`. * @param[out] base_error_out * Backfilled with the XKB base (also known as first) error code, needed * to distinguish XKB errors. Can be `NULL`. * * @returns 1 on success, or 0 on failure. */ XKB_EXPORT int xkb_x11_setup_xkb_extension(xcb_connection_t *connection, uint16_t major_xkb_version, uint16_t minor_xkb_version, enum xkb_x11_setup_xkb_extension_flags flags, uint16_t *major_xkb_version_out, uint16_t *minor_xkb_version_out, uint8_t *base_event_out, uint8_t *base_error_out); /** * Get the keyboard device ID of the core X11 keyboard. * * @param connection An XCB connection to the X server. * * @returns A device ID which may be used with other `xkb_x11_*` functions, * or -1 on failure. */ XKB_EXPORT int32_t xkb_x11_get_core_keyboard_device_id(xcb_connection_t *connection); /** * Create a keymap from an X11 keyboard device. * * This function queries the X server with various requests, fetches the * details of the active keymap on a keyboard device, and creates an * xkb_keymap from these details. * * @param context * The context in which to create the keymap. * @param connection * An XCB connection to the X server. * @param device_id * An XInput device ID (in the range 0-127) with input class KEY. * Passing values outside of this range is an error (the XKB protocol * predates the XInput2 protocol, which first allowed IDs > 127). * @param flags * Optional flags for the keymap, or 0. * * @returns A keymap retrieved from the X server, or `NULL` on failure. * * @memberof xkb_keymap */ XKB_EXPORT struct xkb_keymap * xkb_x11_keymap_new_from_device(struct xkb_context *context, xcb_connection_t *connection, int32_t device_id, enum xkb_keymap_compile_flags flags); /** * Create a new keyboard state object from an X11 keyboard device. * * This function is the same as `xkb_state_new()`, only pre-initialized * with the state of the device at the time this function is called. * * @param keymap * The keymap for which to create the state. * @param connection * An XCB connection to the X server. * @param device_id * An XInput 1 device ID (in the range 0-255) with input class KEY. * Passing values outside of this range is an error. * * @returns A new keyboard state object, or `NULL` on failure. * * @memberof xkb_state */ XKB_EXPORT struct xkb_state * xkb_x11_state_new_from_device(struct xkb_keymap *keymap, xcb_connection_t *connection, int32_t device_id); /** @} */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* _XKBCOMMON_X11_H */ xkbcommon-libxkbcommon-54ee7ac/include/xkbcommon/xkbcommon.h000066400000000000000000002520251510033435100244570ustar00rootroot00000000000000/* * For MIT-open-group: * Copyright 1985, 1987, 1990, 1998 The Open Group * Copyright 2008 Dan Nicholson * * For HPND: * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND * * For MIT: * Copyright © 2009-2012 Daniel Stone * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: MIT-open-group AND HPND AND MIT * * Author: Daniel Stone */ #ifndef _XKBCOMMON_H_ #define _XKBCOMMON_H_ #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #if defined(__GNUC__) && !defined(__CYGWIN__) # define XKB_EXPORT __attribute__((visibility("default"))) #elif defined(_WIN32) # define XKB_EXPORT __declspec(dllexport) #else # define XKB_EXPORT #endif /** * @file * Main libxkbcommon API. */ /** * @struct xkb_context * Opaque top level library context object. * * The context contains various general library data and state, like * logging level and include paths. * * Objects are created in a specific context, and multiple contexts may * coexist simultaneously. Objects from different contexts are completely * separated and do not share any memory or state. */ struct xkb_context; /** * @struct xkb_keymap * Opaque compiled keymap object. * * The keymap object holds all of the static keyboard information obtained * from compiling XKB files. * * A keymap is immutable after it is created (besides reference counts, etc.); * if you need to change it, you must create a new one. */ struct xkb_keymap; /** * @struct xkb_state * Opaque keyboard state object. * * State objects contain the active state of a keyboard (or keyboards), such * as the currently effective layout and the active modifiers. It acts as a * simple state machine, wherein key presses and releases are the input, and * key symbols (keysyms) are the output. */ struct xkb_state; /** * A number used to represent a physical key on a keyboard. * * A standard PC-compatible keyboard might have 102 keys. An appropriate * keymap would assign each of them a keycode, by which the user should * refer to the key throughout the library. * * Historically, the X11 protocol, and consequentially the XKB protocol, * assign only 8 bits for keycodes. This limits the number of different * keys that can be used simultaneously in a single keymap to 256 * (disregarding other limitations). This library does not share this limit; * keycodes beyond 255 (*extended* keycodes) are not treated specially. * Keymaps and applications which are compatible with X11 should not use * these keycodes. * * The values of specific keycodes are determined by the keymap and the * underlying input system. For example, with an X11-compatible keymap * and Linux evdev scan codes (see `linux/input.h`), a fixed offset is used: * * The keymap defines a canonical name for each key, plus possible aliases. * Historically, the XKB protocol restricts these names to at most 4 (ASCII) * characters, but this library does not share this limit. * * @code * xkb_keycode_t keycode_A = KEY_A + 8; * @endcode * * @sa xkb_keycode_is_legal_ext() xkb_keycode_is_legal_x11() */ typedef uint32_t xkb_keycode_t; /** * A number used to represent the symbols generated from a key on a keyboard. * * A key, represented by a keycode, may generate different symbols according * to keyboard state. For example, on a QWERTY keyboard, pressing the key * labled \ generates the symbol ‘a’. If the Shift key is held, it * generates the symbol ‘A’. If a different layout is used, say Greek, * it generates the symbol ‘α’. And so on. * * Each such symbol is represented by a *keysym* (short for “key symbol”). * Note that keysyms are somewhat more general, in that they can also represent * some “function”, such as “Left” or “Right” for the arrow keys. For more * information, see: Appendix A [“KEYSYM Encoding”][encoding] of the X Window * System Protocol. * * Specifically named keysyms can be found in the * xkbcommon/xkbcommon-keysyms.h header file. Their name does not include * the `XKB_KEY_` prefix. * * Besides those, any Unicode/ISO 10646 character in the range U+0100 to * U+10FFFF can be represented by a keysym value in the range 0x01000100 to * 0x0110FFFF. The name of Unicode keysyms is `U`, e.g. `UA1B2`. * * The name of other unnamed keysyms is the hexadecimal representation of * their value, e.g. `0xabcd1234`. * * Keysym names are case-sensitive. * * @note **Encoding:** Keysyms are 32-bit integers with the 3 most significant * bits always set to zero. Thus valid keysyms are in the range * `0 .. 0x1fffffff` = @ref XKB_KEYSYM_MAX. * See: Appendix A [“KEYSYM Encoding”][encoding] of the X Window System Protocol. * * [encoding]: https://www.x.org/releases/current/doc/xproto/x11protocol.html#keysym_encoding * * @ingroup keysyms * @sa `::XKB_KEYSYM_MAX` */ typedef uint32_t xkb_keysym_t; /** * Index of a keyboard layout. * * The layout index is a state component which determines which keyboard * layout is active. These may be different alphabets, different key * arrangements, etc. * * Layout indices are consecutive. The first layout has index 0. * * Each layout is not required to have a name, and the names are not * guaranteed to be unique (though they are usually provided and unique). * Therefore, it is not safe to use the name as a unique identifier for a * layout. Layout names are case-sensitive. * * Layout names are specified in the layout’s definition, for example * “English (US)”. These are different from the (conventionally) short names * which are used to locate the layout, for example `us` or `us(intl)`. These * names are not present in a compiled keymap. * * If the user selects layouts from a list generated from the XKB registry * (using libxkbregistry or directly), and this metadata is needed later on, it * is recommended to store it along with the keymap. * * Layouts are also called *groups* by XKB. * * @sa xkb_keymap::xkb_keymap_num_layouts() * @sa xkb_keymap::xkb_keymap_num_layouts_for_key() */ typedef uint32_t xkb_layout_index_t; /** A mask of layout indices. */ typedef uint32_t xkb_layout_mask_t; /** * Index of a shift level. * * Any key, in any layout, can have several shift levels. Each * shift level can assign different keysyms to the key. The shift level * to use is chosen according to the current keyboard state; for example, * if no keys are pressed, the first level may be used; if the Left Shift * key is pressed, the second; if Num Lock is pressed, the third; and * many such combinations are possible (see `xkb_mod_index_t`). * * Level indices are consecutive. The first level has index 0. */ typedef uint32_t xkb_level_index_t; /** * Index of a modifier. * * A @e modifier is a state component which changes the way keys are * interpreted. A keymap defines a set of modifiers, such as Alt, Shift, * Num Lock or Meta, and specifies which keys may @e activate which * modifiers (in a many-to-many relationship, i.e. a key can activate * several modifiers, and a modifier may be activated by several keys. * Different keymaps do this differently). * * When retrieving the keysyms for a key, the active modifier set is * consulted; this determines the correct shift level to use within the * currently active layout (see `xkb_level_index_t`). * * Modifier indices are consecutive. The first modifier has index 0. * * Each modifier must have a name, and the names are unique. Therefore, it * is safe to use the name as a unique identifier for a modifier. The names * of some common modifiers are provided in the `xkbcommon/xkbcommon-names.h` * header file. Modifier names are case-sensitive. * * @sa xkb_keymap_num_mods() */ typedef uint32_t xkb_mod_index_t; /** A mask of modifier indices. */ typedef uint32_t xkb_mod_mask_t; /** * Index of a keyboard LED. * * LEDs are logical objects which may be @e active or @e inactive. They * typically correspond to the lights on the keyboard. Their state is * determined by the current keyboard state. * * LED indices are non-consecutive. The first LED has index 0. * * Each LED must have a name, and the names are unique. Therefore, * it is safe to use the name as a unique identifier for a LED. The names * of some common LEDs are provided in the `xkbcommon/xkbcommon-names.h` * header file. LED names are case-sensitive. * * @warning A given keymap may specify an exact index for a given LED. * Therefore, LED indexing is not necessarily sequential, as opposed to * modifiers and layouts. This means that when iterating over the LEDs * in a keymap using e.g. xkb_keymap::xkb_keymap_num_leds(), some indices might * be invalid. * Given such an index, functions like xkb_keymap::xkb_keymap_led_get_name() * will return `NULL`, and `xkb_state::xkb_state_led_index_is_active()` will * return -1. * * LEDs are also called *indicators* by XKB. * * @sa `xkb_keymap::xkb_keymap_num_leds()` */ typedef uint32_t xkb_led_index_t; /** A mask of LED indices. */ typedef uint32_t xkb_led_mask_t; /** Invalid keycode */ #define XKB_KEYCODE_INVALID (0xffffffff) /** Invalid layout index */ #define XKB_LAYOUT_INVALID (0xffffffff) /** Invalid level index */ #define XKB_LEVEL_INVALID (0xffffffff) /** Invalid modifier index */ #define XKB_MOD_INVALID (0xffffffff) /** Invalid LED index */ #define XKB_LED_INVALID (0xffffffff) /** Maximum legal keycode */ #define XKB_KEYCODE_MAX (0xffffffff - 1) /** * Maximum keysym value * * @since 1.6.0 * @sa xkb_keysym_t * @ingroup keysyms */ #define XKB_KEYSYM_MAX 0x1fffffff /** * Test whether a value is a valid extended keycode. * @sa xkb_keycode_t **/ #define xkb_keycode_is_legal_ext(key) ((key) <= XKB_KEYCODE_MAX) /** * Test whether a value is a valid X11 keycode. * @sa xkb_keycode_t */ #define xkb_keycode_is_legal_x11(key) ((key) >= 8 && (key) <= 255) /** * @defgroup rules-api Rules * Utility functions related to *rules*, whose purpose is introduced in: * @ref xkb-the-config "". * * @{ */ /** * @struct xkb_rmlvo_builder * Opaque [RMLVO] configuration object. * * It denotes the configuration values by which a user picks a keymap. * * @see [Introduction to RMLVO][RMLVO] * @see @ref rules-api "" * @since 1.11.0 * * [RMLVO]: @ref RMLVO-intro */ struct xkb_rmlvo_builder; enum xkb_rmlvo_builder_flags { XKB_RMLVO_BUILDER_NO_FLAGS = 0 }; /** * Create a new [RMLVO] builder. * * @param context The context in which to create the builder. * @param rules The ruleset. * If `NULL` or the empty string `""`, a default value is used. * If the `XKB_DEFAULT_RULES` environment variable is set, it is used * as the default. Otherwise the system default is used. * @param model The keyboard model. * If `NULL` or the empty string `""`, a default value is used. * If the `XKB_DEFAULT_MODEL` environment variable is set, it is used * as the default. Otherwise the system default is used. * @param flags Optional flags for the builder, or 0. * * @returns A `xkb_rmlvo_builder`, or `NULL` if the compilation failed. * * @see `xkb_rule_names` for a detailed description of `rules` and `model`. * @since 1.11.0 * @memberof xkb_rmlvo_builder * * [RMLVO]: @ref RMLVO-intro */ XKB_EXPORT struct xkb_rmlvo_builder* xkb_rmlvo_builder_new(struct xkb_context *context, const char *rules, const char *model, enum xkb_rmlvo_builder_flags flags); /** * Append a layout to the given [RMLVO] builder. * * @param rmlvo The builder to modify. * @param layout The name of the layout. * @param variant The name of the layout variant, or `NULL` to * select the default variant. * @param options An array of options to apply only to this layout, or * `NULL` if there is no such options. * @param options_len The length of @p options. * * @note The options are only effectual if the corresponding ruleset has the * proper rules to handle them as *layout-specific* options. * @note See `rxkb_option_is_layout_specific()` to query whether an option * supports the layout-specific feature. * * @returns `true` if the call succeeded, otherwise `false`. * * @since 1.11.0 * @memberof xkb_rmlvo_builder * * [RMLVO]: @ref RMLVO-intro */ XKB_EXPORT bool xkb_rmlvo_builder_append_layout(struct xkb_rmlvo_builder *rmlvo, const char *layout, const char *variant, const char* const* options, size_t options_len); /** * Append an option to the given [RMLVO] builder. * * @param rmlvo The builder to modify. * @param option The name of the option. * * @returns `true` if the call succeeded, otherwise `false`. * * @since 1.11.0 * @memberof xkb_rmlvo_builder * * [RMLVO]: @ref RMLVO-intro */ XKB_EXPORT bool xkb_rmlvo_builder_append_option(struct xkb_rmlvo_builder *rmlvo, const char *option); /** * Take a new reference on a [RMLVO] builder. * * @param rmlvo The builder to reference. * * @returns The passed in builder. * * @since 1.11.0 * @memberof xkb_rmlvo_builder * * [RMLVO]: @ref RMLVO-intro */ XKB_EXPORT struct xkb_rmlvo_builder * xkb_rmlvo_builder_ref(struct xkb_rmlvo_builder *rmlvo); /** * Release a reference on a [RMLVO] builder, and possibly free it. * * @param rmlvo The builder. If it is `NULL`, this function does nothing. * * @since 1.11.0 * @memberof xkb_rmlvo_builder * * [RMLVO]: @ref RMLVO-intro */ XKB_EXPORT void xkb_rmlvo_builder_unref(struct xkb_rmlvo_builder *rmlvo); /** * Names to compile a keymap with, also known as [RMLVO]. * * The names are the common configuration values by which a user picks * a keymap. * * If the entire struct is `NULL`, then each field is taken to be `NULL`. * You should prefer passing `NULL` instead of choosing your own defaults. * * @see [Introduction to RMLVO][RMLVO] * @see @ref rules-api "" * * [RMLVO]: @ref RMLVO-intro */ struct xkb_rule_names { /** * The rules file to use. The rules file describes how to interpret * the values of the model, layout, variant and options fields. * * If `NULL` or the empty string `""`, a default value is used. * If the `XKB_DEFAULT_RULES` environment variable is set, it is used * as the default. Otherwise the system default is used. */ const char *rules; /** * The keyboard model by which to interpret keycodes and LEDs. * * If `NULL` or the empty string `""`, a default value is used. * If the `XKB_DEFAULT_MODEL` environment variable is set, it is used * as the default. Otherwise the system default is used. */ const char *model; /** * A comma separated list of layouts (languages) to include in the * keymap. * * If `NULL` or the empty string `""`, a default value is used. * If the `XKB_DEFAULT_LAYOUT` environment variable is set, it is used * as the default. Otherwise the system default is used. */ const char *layout; /** * A comma separated list of variants, one per layout, which may * modify or augment the respective layout in various ways. * * Generally, should either be empty or have the same number of values * as the number of layouts. You may use empty values as in `intl,,neo`. * * If `NULL` or the empty string `""`, and a default value is also used * for the layout, a default value is used. Otherwise no variant is * used. * If the `XKB_DEFAULT_VARIANT` environment variable is set, it is used * as the default. Otherwise the system default is used. */ const char *variant; /** * A comma separated list of options, through which the user specifies * non-layout related preferences, like which key combinations are used * for switching layouts, or which key is the Compose key. * * If `NULL`, a default value is used. If the empty string `""`, no * options are used. * If the `XKB_DEFAULT_OPTIONS` environment variable is set, it is used * as the default. Otherwise the system default is used. * * Each option can additionally have a *layout index specifier*, so that it * applies only if matching the given layout. The index is specified by * appending `!` immediately after the option name, then the 1-indexed * target layout in decimal format: e.g. `ns:option!2`. When no layout is * specified, it matches any layout. * * @note The layout index specifier is only effectual if the corresponding * ruleset has the proper rules to handle the option as *layout-specific*. * @note See `rxkb_option_is_layout_specific()` to query whether an option * supports the layout-specific feature. * * @since 1.11.0: Layout index specifier using `!`. */ const char *options; }; /** * Keymap components, also known as [KcCGST]. * * The components are the result of the [RMLVO] resolution. * * @see [Introduction to RMLVO][RMLVO] * @see [Introduction to KcCGST][KcCGST] * @see @ref rules-api "" * * [RMLVO]: @ref RMLVO-intro * [KcCGST]: @ref KcCGST-intro */ struct xkb_component_names { char *keycodes; char *compatibility; char *geometry; char *symbols; char *types; }; /** * Resolve [RMLVO] names to [KcCGST] components. * * This function is used primarily for *debugging*. See * `xkb_keymap::xkb_keymap_new_from_names2()` for creating keymaps from * [RMLVO] names. * * @param[in] context The context in which to resolve the names. * @param[in] rmlvo_in The [RMLVO] names to use. * @param[out] rmlvo_out The [RMLVO] names actually used after resolving * missing values. * @param[out] components_out The [KcCGST] components resulting of the [RMLVO] * resolution. * * @c rmlvo_out and @c components can be omitted by using `NULL`, but not both. * * If @c components is not `NULL`, it is filled with dynamically-allocated * strings that should be freed by the caller. * * @returns `true` if the [RMLVO] names could be resolved, `false` otherwise. * * @see [Introduction to RMLVO][RMLVO] * @see [Introduction to KcCGST][KcCGST] * @see xkb_rule_names * @see xkb_component_names * @see xkb_keymap::xkb_keymap_new_from_names2() * * @since 1.9.0 * @memberof xkb_component_names * * [RMLVO]: @ref RMLVO-intro * [KcCGST]: @ref KcCGST-intro */ XKB_EXPORT bool xkb_components_names_from_rules(struct xkb_context *context, const struct xkb_rule_names *rmlvo_in, struct xkb_rule_names *rmlvo_out, struct xkb_component_names *components_out); /** @} */ /** * @defgroup keysyms Keysyms * Utility functions related to *keysyms* (short for “key symbols”). * * @{ */ /** * @page keysym-transformations Keysym Transformations * * Keysym translation is subject to several *keysym transformations*, * as described in the XKB specification. These are: * *
*
Capitalization transformation
*
* If the Caps Lock modifier is * active and was not consumed by the translation process, keysyms * are transformed to their upper-case form (if applicable). * Similarly, the UTF-8/UTF-32 string produced is capitalized. * * This is described in: * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier *
*
Control transformation
*
* If the Control modifier is active and * was not consumed by the translation process, the string produced * is transformed to its matching ASCII control character (if * applicable). Keysyms are not affected. * * This is described in: * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier *
*
* * Each relevant function discusses which transformations it performs. * * These transformations are not applicable when a key produces multiple * keysyms. */ /** * Get the name of a keysym. * * For a description of how keysyms are named, see @ref xkb_keysym_t. * * @param[in] keysym The keysym. * @param[out] buffer A string buffer to write the name into. * @param[in] size Size of the buffer. * * @warning If the buffer passed is too small, the string is truncated * (though still `NULL`-terminated); a size of at least 64 bytes is recommended. * * @returns The number of bytes in the name, excluding the `NULL` byte. If * the keysym is invalid, returns -1. * * You may check if truncation has occurred by comparing the return value * with the length of buffer, similarly to the `snprintf(3)` function. * * @sa `xkb_keysym_t` */ XKB_EXPORT int xkb_keysym_get_name(xkb_keysym_t keysym, char *buffer, size_t size); /** Flags for xkb_keysym_from_name(). */ enum xkb_keysym_flags { /** Do not apply any flags. */ XKB_KEYSYM_NO_FLAGS = 0, /** Find keysym by case-insensitive search. */ XKB_KEYSYM_CASE_INSENSITIVE = (1 << 0) }; /** * Get a keysym from its name. * * @param name The name of a keysym. See remarks in `xkb_keysym_get_name()`; * this function will accept any name returned by that function. * @param flags A set of flags controlling how the search is done. If * invalid flags are passed, this will fail with `XKB_KEY_NoSymbol`. * * If you use the `::XKB_KEYSYM_CASE_INSENSITIVE` flag and two keysym names * differ only by case, then the lower-case keysym name is returned. For * instance, for KEY_a and KEY_A, this function would return KEY_a for the * case-insensitive search. If this functionality is needed, it is * recommended to first call this function without this flag; and if that * fails, only then to try with this flag, while possibly warning the user * he had misspelled the name, and might get wrong results. * * Case folding is done according to the C locale; the current locale is not * consulted. * * @returns The keysym. If the name is invalid, returns `XKB_KEY_NoSymbol`. * * @sa xkb_keysym_t * @since 1.9.0: Enable support for C0 and C1 control characters in the Unicode * notation. */ XKB_EXPORT xkb_keysym_t xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags); /** * Get the Unicode/UTF-8 representation of a keysym. * * @param[in] keysym The keysym. * @param[out] buffer A buffer to write the UTF-8 string into. * @param[in] size The size of buffer. Must be at least 5. * * @returns The number of bytes written to the buffer (including the * terminating byte). If the keysym does not have a Unicode * representation, returns 0. If the buffer is too small, returns -1. * * This function does not perform any @ref keysym-transformations. * Therefore, prefer to use `xkb_state::xkb_state_key_get_utf8()` if possible. * * @sa `xkb_state::xkb_state_key_get_utf8()` */ XKB_EXPORT int xkb_keysym_to_utf8(xkb_keysym_t keysym, char *buffer, size_t size); /** * Get the Unicode/UTF-32 representation of a keysym. * * @returns The Unicode/UTF-32 representation of keysym, which is also * compatible with UCS-4. If the keysym does not have a Unicode * representation, returns 0. * * This function does not perform any @ref keysym-transformations. * Therefore, prefer to use xkb_state_key_get_utf32() if possible. * * @sa `xkb_state::xkb_state_key_get_utf32()` */ XKB_EXPORT uint32_t xkb_keysym_to_utf32(xkb_keysym_t keysym); /** * Get the keysym corresponding to a Unicode/UTF-32 codepoint. * * @returns The keysym corresponding to the specified Unicode * codepoint, or XKB_KEY_NoSymbol if there is none. * * This function is the inverse of @ref xkb_keysym_to_utf32. In cases * where a single codepoint corresponds to multiple keysyms, returns * the keysym with the lowest value. * * Unicode codepoints which do not have a special (legacy) keysym * encoding use a direct encoding scheme. These keysyms don’t usually * have an associated keysym constant (`XKB_KEY_*`). * * @sa `xkb_keysym_to_utf32()` * @since 1.0.0 * @since 1.9.0: Enable support for all noncharacters. */ XKB_EXPORT xkb_keysym_t xkb_utf32_to_keysym(uint32_t ucs); /** * Convert a keysym to its uppercase form. * * If there is no such form, the keysym is returned unchanged. * * The conversion rules are the *simple* (i.e. one-to-one) Unicode case * mappings (with some exceptions, see hereinafter) and do not depend * on the locale. If you need the special case mappings (i.e. not * one-to-one or locale-dependent), prefer to work with the Unicode * representation instead, when possible. * * Exceptions to the Unicode mappings: * * | Lower keysym | Lower letter | Upper keysym | Upper letter | Comment | * | ------------ | ------------ | ------------ | ------------ | ------- | * | `ssharp` | `U+00DF`: ß | `U1E9E` | `U+1E9E`: ẞ | [Council for German Orthography] | * * [Council for German Orthography]: https://www.rechtschreibrat.com/regeln-und-woerterverzeichnis/ * * @since 0.8.0: Initial implementation, based on `libX11`. * @since 1.8.0: Use Unicode 16.0 mappings for complete Unicode coverage. * @since 1.12.0: Update to Unicode 17.0. */ XKB_EXPORT xkb_keysym_t xkb_keysym_to_upper(xkb_keysym_t ks); /** * Convert a keysym to its lowercase form. * * If there is no such form, the keysym is returned unchanged. * * The conversion rules are the *simple* (i.e. one-to-one) Unicode case * mappings and do not depend on the locale. If you need the special * case mappings (i.e. not one-to-one or locale-dependent), prefer to * work with the Unicode representation instead, when possible. * * @since 0.8.0: Initial implementation, based on `libX11`. * @since 1.8.0: Use Unicode 16.0 mappings for complete Unicode coverage. * @since 1.12.0: Update to Unicode 17.0. */ XKB_EXPORT xkb_keysym_t xkb_keysym_to_lower(xkb_keysym_t ks); /** @} */ /** * @defgroup context Library Context * Creating, destroying and using library contexts. * * Every keymap compilation request must have a context associated with * it. The context keeps around state such as the include path. * * @{ */ /** * @page envvars Environment Variables * * The user may set some environment variables which affect the library: * * - `XKB_CONFIG_ROOT`, `XKB_CONFIG_EXTRA_PATH`, `XDG_CONFIG_DIR`, `HOME` - see @ref include-path. * - `XKB_LOG_LEVEL` - see `xkb_context::xkb_context_set_log_level()`. * - `XKB_LOG_VERBOSITY` - see `xkb_context::xkb_context_set_log_verbosity()`. * - `XKB_DEFAULT_RULES`, `XKB_DEFAULT_MODEL`, `XKB_DEFAULT_LAYOUT`, * `XKB_DEFAULT_VARIANT`, `XKB_DEFAULT_OPTIONS` - see `xkb_rule_names`. */ /** Flags for context creation. */ enum xkb_context_flags { /** Do not apply any context flags. */ XKB_CONTEXT_NO_FLAGS = 0, /** * Create this context with an empty include path. * * This may be useful e.g.: * - to have full control over the included paths; * - for clients that do not need to access the XKB directories, e.g. * if only retrieving keymap from the Wayland or X server. It avoids * potential issues with directory access permissions. */ XKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0), /** * Don’t take RMLVO names from the environment. * * @since 0.3.0 */ XKB_CONTEXT_NO_ENVIRONMENT_NAMES = (1 << 1), /** * Disable the use of secure_getenv for this context, so that privileged * processes can use environment variables. Client uses at their own risk. * * @since 1.5.0 */ XKB_CONTEXT_NO_SECURE_GETENV = (1 << 2) }; /** * Create a new context. * * @param flags Optional flags for the context, or 0. * * @returns A new context, or `NULL` on failure. * * @memberof xkb_context */ XKB_EXPORT struct xkb_context * xkb_context_new(enum xkb_context_flags flags); /** * Take a new reference on a context. * * @returns The passed in context. * * @memberof xkb_context */ XKB_EXPORT struct xkb_context * xkb_context_ref(struct xkb_context *context); /** * Release a reference on a context, and possibly free it. * * @param context The context. If it is `NULL`, this function does nothing. * * @memberof xkb_context */ XKB_EXPORT void xkb_context_unref(struct xkb_context *context); /** * Store custom user data in the context. * * This may be useful in conjunction with `xkb_context::xkb_context_set_log_fn()` * or other callbacks. * * @memberof xkb_context */ XKB_EXPORT void xkb_context_set_user_data(struct xkb_context *context, void *user_data); /** * Retrieves stored user data from the context. * * @returns The stored user data. If the user data wasn’t set, or the * passed in context is `NULL`, returns `NULL`. * * This may be useful to access private user data from callbacks like a * custom logging function. * * @memberof xkb_context **/ XKB_EXPORT void * xkb_context_get_user_data(struct xkb_context *context); /** @} */ /** * @defgroup include-path Include Paths * Manipulating the include paths in a context. * * The include paths are the file-system paths that are searched when an * include statement is encountered during keymap compilation. * * The default include paths are, in that lookup order: * - The path `$XDG_CONFIG_HOME/xkb`, where `$XDG_CONFIG_HOME` is the value of the environment variable `XDG_CONFIG_HOME`, with the usual fallback to `$HOME/.config/` if unset. * - The path `$HOME/.xkb`, where `$HOME` is the value of the environment * variable `HOME`. * - The `XKB_CONFIG_EXTRA_PATH` environment variable, if defined, otherwise the * system configuration directory, defined at library configuration time * (usually `/etc/xkb`). * - The `XKB_CONFIG_ROOT` environment variable, if defined, otherwise * the system XKB root, defined at library configuration time * (usually `/usr/share/X11/xkb`). * * @{ */ /** * Append a new entry to the context’s include path. * * @returns 1 on success, or 0 if the include path could not be added or is * inaccessible. * * @memberof xkb_context */ XKB_EXPORT int xkb_context_include_path_append(struct xkb_context *context, const char *path); /** * Append the default include paths to the context’s include path. * * @returns 1 on success, or 0 if the primary include path could not be added. * * @memberof xkb_context */ XKB_EXPORT int xkb_context_include_path_append_default(struct xkb_context *context); /** * Reset the context’s include path to the default. * * Removes all entries from the context’s include path, and inserts the * default paths. * * @returns 1 on success, or 0 if the primary include path could not be added. * * @memberof xkb_context */ XKB_EXPORT int xkb_context_include_path_reset_defaults(struct xkb_context *context); /** * Remove all entries from the context’s include path. * * @memberof xkb_context */ XKB_EXPORT void xkb_context_include_path_clear(struct xkb_context *context); /** * Get the number of paths in the context’s include path. * * @memberof xkb_context */ XKB_EXPORT unsigned int xkb_context_num_include_paths(struct xkb_context *context); /** * Get a specific include path from the context’s include path. * * @returns The include path at the specified index. If the index is * invalid, returns NULL. * * @memberof xkb_context */ XKB_EXPORT const char * xkb_context_include_path_get(struct xkb_context *context, unsigned int index); /** @} */ /** * @defgroup logging Logging Handling * Manipulating how logging from this library is handled. * * @{ */ /** Specifies a logging level. */ enum xkb_log_level { XKB_LOG_LEVEL_CRITICAL = 10, /**< Log critical internal errors only. */ XKB_LOG_LEVEL_ERROR = 20, /**< Log all errors. */ XKB_LOG_LEVEL_WARNING = 30, /**< Log warnings and errors. */ XKB_LOG_LEVEL_INFO = 40, /**< Log information, warnings, and errors. */ XKB_LOG_LEVEL_DEBUG = 50 /**< Log everything. */ }; /** * Set the current logging level. * * @param context The context in which to set the logging level. * @param level The logging level to use. Only messages from this level * and below will be logged. * * The default level is `::XKB_LOG_LEVEL_ERROR`. The environment variable * `XKB_LOG_LEVEL`, if set in the time the context was created, overrides the * default value. It may be specified as a level number or name. * * @memberof xkb_context */ XKB_EXPORT void xkb_context_set_log_level(struct xkb_context *context, enum xkb_log_level level); /** * Get the current logging level. * * @memberof xkb_context */ XKB_EXPORT enum xkb_log_level xkb_context_get_log_level(struct xkb_context *context); /** * Sets the current logging verbosity. * * The library can generate a number of warnings which are not helpful to * ordinary users of the library. The verbosity may be increased if more * information is desired (e.g. when developing a new keymap). * * The default verbosity is 0. The environment variable `XKB_LOG_VERBOSITY`, * if set in the time the context was created, overrides the default value. * * @param context The context in which to use the set verbosity. * @param verbosity The verbosity to use. Currently used values are * 1 to 10, higher values being more verbose. 0 would result in no verbose * messages being logged. * * Most verbose messages are of level `::XKB_LOG_LEVEL_WARNING` or lower. * * @memberof xkb_context */ XKB_EXPORT void xkb_context_set_log_verbosity(struct xkb_context *context, int verbosity); /** * Get the current logging verbosity of the context. * * @memberof xkb_context */ XKB_EXPORT int xkb_context_get_log_verbosity(struct xkb_context *context); /** * Set a custom function to handle logging messages. * * @param context The context in which to use the set logging function. * @param log_fn The function that will be called for logging messages. * Passing `NULL` restores the default function, which logs to stderr. * * By default, log messages from this library are printed to stderr. This * function allows you to replace the default behavior with a custom * handler. The handler is only called with messages which match the * current logging level and verbosity settings for the context. * level is the logging level of the message. @a format and @a args are * the same as in the `vprintf(3)` function. * * You may use `xkb_context::xkb_context_set_user_data()` on the context, and * then call `xkb_context::xkb_context_get_user_data()` from within the logging * function to provide it with additional private context. * * @memberof xkb_context */ XKB_EXPORT void xkb_context_set_log_fn(struct xkb_context *context, void (*log_fn)(struct xkb_context *context, enum xkb_log_level level, const char *format, va_list args)); /** @} */ /** * @defgroup keymap Keymap Creation * Creating and destroying keymaps. * * @{ */ /** Flags for keymap compilation. */ enum xkb_keymap_compile_flags { /** Do not apply any flags. */ XKB_KEYMAP_COMPILE_NO_FLAGS = 0 }; /** * The possible keymap formats. * * See @ref keymap-text-format-v1-v2 "" for the complete description of the * formats and @ref keymap-support "" for detailed differences between the * formats. * * @remark A keymap can be parsed in one format and serialized in another, * thanks to automatic fallback mechanisms. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Keymap format to use depending on the target protocol *
Protocollibxkbcommon keymap format
NameKeymap formatParsingSerialization
X11XKB * `::XKB_KEYMAP_FORMAT_TEXT_V1` * * *Always* use `::XKB_KEYMAP_FORMAT_TEXT_V1`, since the other formats are * incompatible. *
Wayland[xkb_v1] *
*
Wayland compositors
*
* The format depends on the keyboard layout database (usually [xkeyboard-config]). * Note that since v2 is a superset of v1, compositors are encouraged to use * `::XKB_KEYMAP_FORMAT_TEXT_V2` whenever possible. *
*
Client apps
*
* Clients should use `::XKB_KEYMAP_FORMAT_TEXT_V1` to parse the keymap sent * by a Wayland compositor, at least until `::XKB_KEYMAP_FORMAT_TEXT_V2` * stabilizes. *
*
* At the time of writing (July 2025), the Wayland [xkb_v1] keymap * format is only defined as “libxkbcommon compatible”. In theory it enables * flexibility, but the set of supported features varies depending on the * libxkbcommon version and libxkbcommon keymap format used. Unfortunately there * is currently no Wayland API for keymap format *negotiation*. * * Therefore the **recommended** serialization format is * `::XKB_KEYMAP_FORMAT_TEXT_V1`, in order to ensure maximum compatibility for * interchange. * * Serializing using `::XKB_KEYMAP_FORMAT_TEXT_V2` should be considered * **experimental**, as some clients may fail to parse the resulting string. *
* * [xkb_v1]: https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_keyboard-enum-keymap_format * [xkeyboard-config]: https://gitlab.freedesktop.org/xkeyboard-config/xkeyboard-config */ enum xkb_keymap_format { /** * The classic XKB text format, as generated by `xkbcomp -xkb`. * * @important This format should *always* be used when *serializing* a * keymap for **X11**. * * @important For the **Wayland** [xkb_v1] format, it is * advised to use this format as well for serializing, in order to ensure * maximum compatibility for interchange. * * [xkb_v1]: https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_keyboard-enum-keymap_format */ XKB_KEYMAP_FORMAT_TEXT_V1 = 1, /** * Xkbcommon extensions of the classic XKB text format, **incompatible with * X11**. * * @important Do *not* use when *serializing* a keymap for **X11** * (incompatible). * * @important Considered *experimental* when *serializing* for **Wayland**: * at the time of writing (July 2025), there is only one XKB keymap format * [xkb_v1] in Wayland and no Wayland API for keymap format * *negotiation*, so the clients may not be able to parse the keymap if it * uses v2-specific features. Therefore a compositor may *parse* keymaps * using `::XKB_KEYMAP_FORMAT_TEXT_V2` but it should serialize them using * `::XKB_KEYMAP_FORMAT_TEXT_V1` and rely on the automatic *fallback* * mechanisms. * * @since 1.11.0 * * [xkb_v1]: https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_keyboard-enum-keymap_format */ XKB_KEYMAP_FORMAT_TEXT_V2 = 2 }; /** * Create a keymap from a [RMLVO] builder. * * The primary keymap entry point: creates a new XKB keymap from a set of * [RMLVO] \(Rules + Model + Layouts + Variants + Options) names. * * @param rmlvo The [RMLVO] builder to use. See `xkb_rmlvo_builder`. * @param format The text format of the keymap file to compile. * @param flags Optional flags for the keymap, or 0. * * @returns A keymap compiled according to the [RMLVO] names, or `NULL` if * the compilation failed. * * @since 1.11.0 * @sa `xkb_keymap_new_from_names2()` * @sa `xkb_rmlvo_builder` * @memberof xkb_keymap * * [RMLVO]: @ref RMLVO-intro */ XKB_EXPORT struct xkb_keymap * xkb_keymap_new_from_rmlvo(const struct xkb_rmlvo_builder *rmlvo, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags); /** * Create a keymap from [RMLVO] names. * * Same as `xkb_keymap_new_from_names2()`, but with the keymap format fixed to: * `::XKB_KEYMAP_FORMAT_TEXT_V2`. * * @deprecated Use `xkb_keymap_new_from_names2()` instead. * @since 1.11.0: Deprecated * @since 1.11.0: Use internally `::XKB_KEYMAP_FORMAT_TEXT_V2` instead of * `::XKB_KEYMAP_FORMAT_TEXT_V1` * @sa `xkb_keymap_new_from_names2()` * @sa `xkb_rule_names` * @sa `xkb_keymap_new_from_rmlvo()` * @memberof xkb_keymap * * [RMLVO]: @ref RMLVO-intro */ XKB_EXPORT struct xkb_keymap * xkb_keymap_new_from_names(struct xkb_context *context, const struct xkb_rule_names *names, enum xkb_keymap_compile_flags flags); /** * Create a keymap from [RMLVO] names. * * The primary keymap entry point: creates a new XKB keymap from a set of * [RMLVO] \(Rules + Model + Layouts + Variants + Options) names. * * @param context The context in which to create the keymap. * @param names The [RMLVO] names to use. See xkb_rule_names. * @param format The text format of the keymap file to compile. * @param flags Optional flags for the keymap, or 0. * * @returns A keymap compiled according to the [RMLVO] names, or `NULL` if * the compilation failed. * * @sa `xkb_rule_names` * @sa `xkb_keymap_new_from_rmlvo()` * @memberof xkb_keymap * @since 1.11.0 * * [RMLVO]: @ref RMLVO-intro */ XKB_EXPORT struct xkb_keymap * xkb_keymap_new_from_names2(struct xkb_context *context, const struct xkb_rule_names *names, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags); /** * Create a keymap from a keymap file. * * @param context The context in which to create the keymap. * @param file The keymap file to compile. * @param format The text format of the keymap file to compile. * @param flags Optional flags for the keymap, or 0. * * @returns A keymap compiled from the given XKB keymap file, or `NULL` if * the compilation failed. * * The file must contain a complete keymap. For example, in the * `::XKB_KEYMAP_FORMAT_TEXT_V1` format, this means the file must contain one * top level `%xkb_keymap` section, which in turn contains other required * sections. * * @memberof xkb_keymap */ XKB_EXPORT struct xkb_keymap * xkb_keymap_new_from_file(struct xkb_context *context, FILE *file, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags); /** * Create a keymap from a keymap string. * * This is just like `xkb_keymap_new_from_file()`, but instead of a file, gets * the keymap as one enormous string. * * @see `xkb_keymap_new_from_file()` * @memberof xkb_keymap */ XKB_EXPORT struct xkb_keymap * xkb_keymap_new_from_string(struct xkb_context *context, const char *string, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags); /** * Create a keymap from a memory buffer. * * This is just like `xkb_keymap_new_from_string()`, but takes a length argument * so the input string does not have to be zero-terminated. * * @see `xkb_keymap_new_from_string()` * @memberof xkb_keymap * @since 0.3.0 */ XKB_EXPORT struct xkb_keymap * xkb_keymap_new_from_buffer(struct xkb_context *context, const char *buffer, size_t length, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags); /** * Take a new reference on a keymap. * * @returns The passed in keymap. * * @memberof xkb_keymap */ XKB_EXPORT struct xkb_keymap * xkb_keymap_ref(struct xkb_keymap *keymap); /** * Release a reference on a keymap, and possibly free it. * * @param keymap The keymap. If it is `NULL`, this function does nothing. * * @memberof xkb_keymap */ XKB_EXPORT void xkb_keymap_unref(struct xkb_keymap *keymap); /** * Get the keymap as a string in the format from which it was created. * @sa `xkb_keymap::xkb_keymap_get_as_string()` **/ #define XKB_KEYMAP_USE_ORIGINAL_FORMAT ((enum xkb_keymap_format) -1) /** * Flags to control keymap serialization. * * @since 1.12.0 */ enum xkb_keymap_serialize_flags { /** Do not apply any flags. */ XKB_KEYMAP_SERIALIZE_NO_FLAGS = 0, /** Enable pretty-printing */ XKB_KEYMAP_SERIALIZE_PRETTY = (1 << 0), /** Do not drop unused bits (key types, compatibility entries) */ XKB_KEYMAP_SERIALIZE_KEEP_UNUSED = (1 << 1), }; /** * Get the compiled keymap as a string. * * Same as `xkb_keymap::xkb_keymap_get_as_string2()` using * `::XKB_KEYMAP_SERIALIZE_NO_FLAGS`. * * @since 1.12.0: Drop unused types and compatibility entries and do not * pretty-print. * * @sa `xkb_keymap::xkb_keymap_get_as_string2()` * @memberof xkb_keymap */ XKB_EXPORT char * xkb_keymap_get_as_string(struct xkb_keymap *keymap, enum xkb_keymap_format format); /** * Get the compiled keymap as a string. * * @param keymap The keymap to get as a string. * @param format The keymap format to use for the string. You can pass * in the special value `::XKB_KEYMAP_USE_ORIGINAL_FORMAT` to use the format * from which the keymap was originally created. When used as an *interchange* * format such as Wayland [xkb_v1], the format should be explicit. * @param flags Optional flags to control the serialization, or 0. * * @returns The keymap as a `NULL`-terminated string, or `NULL` if unsuccessful. * * The returned string may be fed back into `xkb_keymap_new_from_string()` * to get the exact same keymap (possibly in another process, etc.). * * The returned string is *dynamically allocated* and should be freed by the * caller. * * @since 1.12.0 * * @sa `xkb_keymap_get_as_string()` * @sa `xkb_keymap_new_from_string()` * @memberof xkb_keymap * * [xkb_v1]: https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_keyboard-enum-keymap_format */ XKB_EXPORT char * xkb_keymap_get_as_string2(struct xkb_keymap *keymap, enum xkb_keymap_format format, enum xkb_keymap_serialize_flags flags); /** @} */ /** * @defgroup components Keymap Components * Enumeration of state components in a keymap. * * @{ */ /** * Get the minimum keycode in the keymap. * * @sa xkb_keycode_t * @memberof xkb_keymap * @since 0.3.1 */ XKB_EXPORT xkb_keycode_t xkb_keymap_min_keycode(struct xkb_keymap *keymap); /** * Get the maximum keycode in the keymap. * * @sa xkb_keycode_t * @memberof xkb_keymap * @since 0.3.1 */ XKB_EXPORT xkb_keycode_t xkb_keymap_max_keycode(struct xkb_keymap *keymap); /** * The iterator used by `xkb_keymap_key_for_each()`. * * @sa xkb_keymap_key_for_each * @memberof xkb_keymap * @since 0.3.1 */ typedef void (*xkb_keymap_key_iter_t)(struct xkb_keymap *keymap, xkb_keycode_t key, void *data); /** * Run a specified function for every valid keycode in the keymap. If a * keymap is sparse, this function may be called fewer than * (max_keycode - min_keycode + 1) times. * * @sa xkb_keymap_min_keycode() * @sa xkb_keymap_max_keycode() * @sa xkb_keycode_t * @memberof xkb_keymap * @since 0.3.1 */ XKB_EXPORT void xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter, void *data); /** * Find the name of the key with the given keycode. * * This function always returns the canonical name of the key (see * description in `xkb_keycode_t`). * * @returns The key name. If no key with this keycode exists, * returns `NULL`. * * @sa xkb_keycode_t * @memberof xkb_keymap * @since 0.6.0 */ XKB_EXPORT const char * xkb_keymap_key_get_name(struct xkb_keymap *keymap, xkb_keycode_t key); /** * Find the keycode of the key with the given name. * * The name can be either a canonical name or an alias. * * @returns The keycode. If no key with this name exists, * returns `::XKB_KEYCODE_INVALID`. * * @sa xkb_keycode_t * @memberof xkb_keymap * @since 0.6.0 */ XKB_EXPORT xkb_keycode_t xkb_keymap_key_by_name(struct xkb_keymap *keymap, const char *name); /** * Get the number of modifiers in the keymap. * * @sa xkb_mod_index_t * @memberof xkb_keymap */ XKB_EXPORT xkb_mod_index_t xkb_keymap_num_mods(struct xkb_keymap *keymap); /** * Get the name of a modifier by index. * * @returns The name. If the index is invalid, returns `NULL`. * * @sa xkb_mod_index_t * @memberof xkb_keymap */ XKB_EXPORT const char * xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx); /** * Get the index of a modifier by name. * * @returns The index. If no modifier with this name exists, returns * `::XKB_MOD_INVALID`. * * @sa xkb_mod_index_t * @memberof xkb_keymap */ XKB_EXPORT xkb_mod_index_t xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name); /** * Get the encoding of a modifier by name. * * In X11 terminology it corresponds to the mapping to the *[real modifiers]*. * * @returns The encoding of a modifier. Note that it may be 0 if the name does * not exist or if the modifier is not mapped. * * @since 1.10.0 * @sa `xkb_keymap_mod_get_mask2()` * @memberof xkb_keymap * * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT xkb_mod_mask_t xkb_keymap_mod_get_mask(struct xkb_keymap *keymap, const char *name); /** * Get the encoding of a modifier by index. * * In X11 terminology it corresponds to the mapping to the *[real modifiers]*. * * @returns The encoding of a modifier. Note that it may be 0 if the modifier is * not mapped. * * @since 1.11.0 * @sa `xkb_keymap_mod_get_mask()` * @memberof xkb_keymap * * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT xkb_mod_mask_t xkb_keymap_mod_get_mask2(struct xkb_keymap *keymap, xkb_mod_index_t idx); /** * Get the number of layouts in the keymap. * * @sa `xkb_layout_index_t` * @sa `xkb_rule_names` * @sa `xkb_keymap_num_layouts_for_key()` * @memberof xkb_keymap */ XKB_EXPORT xkb_layout_index_t xkb_keymap_num_layouts(struct xkb_keymap *keymap); /** * Get the name of a layout by index. * * @returns The name. If the index is invalid, or the layout does not have * a name, returns `NULL`. * * @sa xkb_layout_index_t * For notes on layout names. * @memberof xkb_keymap */ XKB_EXPORT const char * xkb_keymap_layout_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx); /** * Get the index of a layout by name. * * @returns The index. If no layout exists with this name, returns * `::XKB_LAYOUT_INVALID`. If more than one layout in the keymap has this name, * returns the lowest index among them. * * @sa `xkb_layout_index_t` for notes on layout names. * @memberof xkb_keymap */ XKB_EXPORT xkb_layout_index_t xkb_keymap_layout_get_index(struct xkb_keymap *keymap, const char *name); /** * Get the number of LEDs in the keymap. * * @warning The range [ 0...`xkb_keymap_num_leds()` ) includes all of the LEDs * in the keymap, but may also contain inactive LEDs. When iterating over * this range, you need the handle this case when calling functions such as * `xkb_keymap_led_get_name()` or `xkb_state::xkb_state_led_index_is_active()`. * * @sa xkb_led_index_t * @memberof xkb_keymap */ XKB_EXPORT xkb_led_index_t xkb_keymap_num_leds(struct xkb_keymap *keymap); /** * Get the name of a LED by index. * * @returns The name. If the index is invalid, returns `NULL`. * * @memberof xkb_keymap */ XKB_EXPORT const char * xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx); /** * Get the index of a LED by name. * * @returns The index. If no LED with this name exists, returns * `::XKB_LED_INVALID`. * * @memberof xkb_keymap */ XKB_EXPORT xkb_led_index_t xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name); /** * Get the number of layouts for a specific key. * * This number can be different from `xkb_keymap_num_layouts()`, but is always * smaller. It is the appropriate value to use when iterating over the * layouts of a key. * * @sa xkb_layout_index_t * @memberof xkb_keymap */ XKB_EXPORT xkb_layout_index_t xkb_keymap_num_layouts_for_key(struct xkb_keymap *keymap, xkb_keycode_t key); /** * Get the number of shift levels for a specific key and layout. * * If @c layout is out of range for this key (that is, larger or equal to * the value returned by `xkb_keymap_num_layouts_for_key()`), it is brought * back into range in a manner consistent with * `xkb_state::xkb_state_key_get_layout()`. * * @sa xkb_level_index_t * @memberof xkb_keymap */ XKB_EXPORT xkb_level_index_t xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t key, xkb_layout_index_t layout); /** * Retrieves every possible modifier mask that produces the specified * shift level for a specific key and layout. * * This API is useful for inverse key transformation; i.e. finding out * which modifiers need to be active in order to be able to type the * keysym(s) corresponding to the specific key code, layout and level. * * @warning It returns only up to masks_size modifier masks. If the * buffer passed is too small, some of the possible modifier combinations * will not be returned. * * @param[in] keymap The keymap. * @param[in] key The keycode of the key. * @param[in] layout The layout for which to get modifiers. * @param[in] level The shift level in the layout for which to get the * modifiers. This should be smaller than: * @code xkb_keymap_num_levels_for_key(keymap, key) @endcode * @param[out] masks_out A buffer in which the requested masks should be * stored. * @param[out] masks_size The number of elements in the buffer pointed to by * masks_out. * * If @c layout is out of range for this key (that is, larger or equal to * the value returned by `xkb_keymap_num_layouts_for_key()`), it is brought * back into range in a manner consistent with * `xkb_state::xkb_state_key_get_layout()`. * * @returns The number of modifier masks stored in the masks_out array. * If the key is not in the keymap or if the specified shift level cannot * be reached it returns 0 and does not modify the masks_out buffer. * * @sa xkb_level_index_t * @sa xkb_mod_mask_t * @memberof xkb_keymap * @since 1.0.0 */ XKB_EXPORT size_t xkb_keymap_key_get_mods_for_level(struct xkb_keymap *keymap, xkb_keycode_t key, xkb_layout_index_t layout, xkb_level_index_t level, xkb_mod_mask_t *masks_out, size_t masks_size); /** * Get the keysyms obtained from pressing a key in a given layout and * shift level. * * This function is like `xkb_state::xkb_state_key_get_syms()`, only the layout * and shift level are not derived from the keyboard state but are instead * specified explicitly. * * @param[in] keymap The keymap. * @param[in] key The keycode of the key. * @param[in] layout The layout for which to get the keysyms. * @param[in] level The shift level in the layout for which to get the * keysyms. This should be smaller than: * @code xkb_keymap_num_levels_for_key(keymap, key) @endcode * @param[out] syms_out An immutable array of keysyms corresponding to the * key in the given layout and shift level. * * If @c layout is out of range for this key (that is, larger or equal to * the value returned by `xkb_keymap_num_layouts_for_key()`), it is brought * back into range in a manner consistent with * `xkb_state::xkb_state_key_get_layout()`. * * @returns The number of keysyms in the syms_out array. If no keysyms * are produced by the key in the given layout and shift level, returns 0 * and sets @p syms_out to `NULL`. * * @sa `xkb_state::xkb_state_key_get_syms()` * @memberof xkb_keymap */ XKB_EXPORT int xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap, xkb_keycode_t key, xkb_layout_index_t layout, xkb_level_index_t level, const xkb_keysym_t **syms_out); /** * Determine whether a key should repeat or not. * * A keymap may specify different repeat behaviors for different keys. * Most keys should generally exhibit repeat behavior; for example, holding * the `a` key down in a text editor should normally insert a single ‘a’ * character every few milliseconds, until the key is released. However, * there are keys which should not or do not need to be repeated. For * example, repeating modifier keys such as Left/Right Shift or Caps Lock * is not generally useful or desired. * * @returns 1 if the key should repeat, 0 otherwise. * * @memberof xkb_keymap */ XKB_EXPORT int xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t key); /** @} */ /** * @defgroup state Keyboard State * Creating, destroying and manipulating keyboard state objects. * * @{ */ /** * Create a new keyboard state object. * * @param keymap The keymap which the state will use. * * @returns A new keyboard state object, or `NULL` on failure. * * @memberof xkb_state */ XKB_EXPORT struct xkb_state * xkb_state_new(struct xkb_keymap *keymap); /** * Take a new reference on a keyboard state object. * * @returns The passed in object. * * @memberof xkb_state */ XKB_EXPORT struct xkb_state * xkb_state_ref(struct xkb_state *state); /** * Release a reference on a keyboard state object, and possibly free it. * * @param state The state. If it is `NULL`, this function does nothing. * * @memberof xkb_state */ XKB_EXPORT void xkb_state_unref(struct xkb_state *state); /** * Get the keymap which a keyboard state object is using. * * @returns The keymap which was passed to `xkb_state_new()` when creating * this state object. * * This function does not take a new reference on the keymap; you must * explicitly reference it yourself if you plan to use it beyond the * lifetime of the state. * * @memberof xkb_state */ XKB_EXPORT struct xkb_keymap * xkb_state_get_keymap(struct xkb_state *state); /** * @page server-client-state Server State and Client State * @parblock * * The xkb_state API is used by two distinct actors in most window-system * architectures: * * 1. A *server* - for example, a Wayland compositor, an X11 server, an evdev * listener. * * Servers maintain the XKB state for a device according to input events from * the device, such as key presses and releases, and out-of-band events from * the user, like UI layout switchers. * * 2. A *client* - for example, a Wayland client, an X11 client. * * Clients do not listen to input from the device; instead, whenever the * server state changes, the server serializes the state and notifies the * clients that the state has changed; the clients then update the state * from the serialization. * * Some entry points in the xkb_state API are only meant for servers and some * are only meant for clients, and the two should generally not be mixed. * * @endparblock */ /** Specifies the direction of the key (press / release). */ enum xkb_key_direction { XKB_KEY_UP, /**< The key was released. */ XKB_KEY_DOWN /**< The key was pressed. */ }; /** * Modifier and layout types for state objects. This enum is bitmaskable, * e.g. (`::XKB_STATE_MODS_DEPRESSED` | `::XKB_STATE_MODS_LATCHED`) is valid to * exclude locked modifiers. * * In XKB, the `DEPRESSED` components are also known as *base*. */ enum xkb_state_component { /** Depressed modifiers, i.e. a key is physically holding them. */ XKB_STATE_MODS_DEPRESSED = (1 << 0), /** Latched modifiers, i.e. will be unset after the next non-modifier * key press. */ XKB_STATE_MODS_LATCHED = (1 << 1), /** Locked modifiers, i.e. will be unset after the key provoking the * lock has been pressed again. */ XKB_STATE_MODS_LOCKED = (1 << 2), /** Effective modifiers, i.e. currently active and affect key * processing (derived from the other state components). * Use this unless you explicitly care how the state came about. */ XKB_STATE_MODS_EFFECTIVE = (1 << 3), /** Depressed layout, i.e. a key is physically holding it. */ XKB_STATE_LAYOUT_DEPRESSED = (1 << 4), /** Latched layout, i.e. will be unset after the next non-modifier * key press. */ XKB_STATE_LAYOUT_LATCHED = (1 << 5), /** Locked layout, i.e. will be unset after the key provoking the lock * has been pressed again. */ XKB_STATE_LAYOUT_LOCKED = (1 << 6), /** Effective layout, i.e. currently active and affects key processing * (derived from the other state components). * Use this unless you explicitly care how the state came about. */ XKB_STATE_LAYOUT_EFFECTIVE = (1 << 7), /** LEDs (derived from the other state components). */ XKB_STATE_LEDS = (1 << 8) }; /** * Update the keyboard state to reflect a given key being pressed or * released. * * This entry point is intended for *server* applications and should not be used * by *client* applications; see @ref server-client-state for details. * * A series of calls to this function should be consistent; that is, a call * with `::XKB_KEY_DOWN` for a key should be matched by an `::XKB_KEY_UP`; if a * key is pressed twice, it should be released twice; etc. Otherwise (e.g. due * to missed input events), situations like “stuck modifiers” may occur. * * This function is often used in conjunction with the function * `xkb_state_key_get_syms()` (or `xkb_state_key_get_one_sym()`), for example, * when handling a key event. In this case, you should prefer to get the * keysyms *before* updating the key, such that the keysyms reported for * the key event are not affected by the event itself. This is the * conventional behavior. * * @returns A mask of state components that have changed as a result of * the update. If nothing in the state has changed, returns 0. * * @memberof xkb_state * * @sa `xkb_state_update_mask()` */ XKB_EXPORT enum xkb_state_component xkb_state_update_key(struct xkb_state *state, xkb_keycode_t key, enum xkb_key_direction direction); /** * Update the keyboard state to change the latched and locked state of * the modifiers and layout. * * This entry point is intended for *server* applications and should not be used * by *client* applications; see @ref server-client-state for details. * * Use this function to update the latched and locked state according to * “out of band” (non-device) inputs, such as UI layout switchers. * * @par Layout out of range * @parblock * * If the effective layout, after taking into account the depressed, latched and * locked layout, is out of range (negative or greater than the maximum layout), * it is brought into range. Currently, the layout is wrapped using integer * modulus (with negative values wrapping from the end). The wrapping behavior * may be made configurable in the future. * * @endparblock * * @param state The keyboard state object. * @param affect_latched_mods * @param latched_mods * Modifiers to set as latched or unlatched. Only modifiers in * @p affect_latched_mods are considered. * @param affect_latched_layout * @param latched_layout * Layout to latch. Only considered if @p affect_latched_layout is true. * Maybe be out of range (including negative) -- see note above. * @param affect_locked_mods * @param locked_mods * Modifiers to set as locked or unlocked. Only modifiers in * @p affect_locked_mods are considered. * @param affect_locked_layout * @param locked_layout * Layout to lock. Only considered if @p affect_locked_layout is true. * Maybe be out of range (including negative) -- see note above. * * @returns A mask of state components that have changed as a result of * the update. If nothing in the state has changed, returns 0. * * @memberof xkb_state * * @sa xkb_state_update_mask() */ XKB_EXPORT enum xkb_state_component xkb_state_update_latched_locked(struct xkb_state *state, xkb_mod_mask_t affect_latched_mods, xkb_mod_mask_t latched_mods, bool affect_latched_layout, int32_t latched_layout, xkb_mod_mask_t affect_locked_mods, xkb_mod_mask_t locked_mods, bool affect_locked_layout, int32_t locked_layout); /** * Update a keyboard state from a set of explicit masks. * * This entry point is intended for *client* applications; see @ref * server-client-state for details. *Server* applications should use * `xkb_state_update_key()` instead. * * All parameters must always be passed, or the resulting state may be * incoherent. * * @warning The serialization is lossy and will not survive round trips; it must * only be used to feed client state objects, and must not be used to update the * server state. * * @returns A mask of state components that have changed as a result of * the update. If nothing in the state has changed, returns 0. * * @memberof xkb_state * * @sa `xkb_state_component` * @sa `xkb_state_update_key()` */ XKB_EXPORT enum xkb_state_component xkb_state_update_mask(struct xkb_state *state, xkb_mod_mask_t depressed_mods, xkb_mod_mask_t latched_mods, xkb_mod_mask_t locked_mods, xkb_layout_index_t depressed_layout, xkb_layout_index_t latched_layout, xkb_layout_index_t locked_layout); /** * Get the keysyms obtained from pressing a particular key in a given * keyboard state. * * Get the keysyms for a key according to the current active layout, * modifiers and shift level for the key, as determined by a keyboard * state. * * @param[in] state The keyboard state object. * @param[in] key The keycode of the key. * @param[out] syms_out An immutable array of keysyms corresponding the * key in the given keyboard state. * * As an extension to XKB, this function can return more than one keysym. * If you do not want to handle this case, you can use * `xkb_state_key_get_one_sym()` for a simpler interface. * * @returns The number of keysyms in the syms_out array. If no keysyms * are produced by the key in the given keyboard state, returns 0 and sets * syms_out to `NULL`. * * This function performs Capitalization @ref keysym-transformations. * * @memberof xkb_state * * @since 1.9.0 This function now performs @ref keysym-transformations. */ XKB_EXPORT int xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t key, const xkb_keysym_t **syms_out); /** * Get the Unicode/UTF-8 string obtained from pressing a particular key * in a given keyboard state. * * @param[in] state The keyboard state object. * @param[in] key The keycode of the key. * @param[out] buffer A buffer to write the string into. * @param[in] size Size of the buffer. * * @warning If the buffer passed is too small, the string is truncated * (though still `NULL`-terminated). * * @returns The number of bytes required for the string, excluding the * `NULL` byte. If there is nothing to write, returns 0. * * You may check if truncation has occurred by comparing the return value * with the size of @p buffer, similarly to the `snprintf(3)` function. * You may safely pass `NULL` and 0 to @p buffer and @p size to find the * required size (without the `NULL`-byte). * * This function performs Capitalization and Control @ref * keysym-transformations. * * @memberof xkb_state * @since 0.4.1 */ XKB_EXPORT int xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t key, char *buffer, size_t size); /** * Get the Unicode/UTF-32 codepoint obtained from pressing a particular * key in a a given keyboard state. * * @returns The UTF-32 representation for the key, if it consists of only * a single codepoint. Otherwise, returns 0. * * This function performs Capitalization and Control @ref * keysym-transformations. * * @memberof xkb_state * @since 0.4.1 */ XKB_EXPORT uint32_t xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t key); /** * Get the single keysym obtained from pressing a particular key in a * given keyboard state. * * This function is similar to `xkb_state_key_get_syms()`, but intended * for users which cannot or do not want to handle the case where * multiple keysyms are returned (in which case this function is * preferred). * * @returns The keysym. If the key does not have exactly one keysym, * returns `XKB_KEY_NoSymbol`. * * This function performs Capitalization @ref keysym-transformations. * * @sa xkb_state_key_get_syms() * @memberof xkb_state */ XKB_EXPORT xkb_keysym_t xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t key); /** * Get the effective layout index for a key in a given keyboard state. * * @returns The layout index for the key in the given keyboard state. If * the given keycode is invalid, or if the key is not included in any * layout at all, returns `::XKB_LAYOUT_INVALID`. * * @invariant If the returned layout is valid, the following always holds: * @code * xkb_state_key_get_layout(state, key) < xkb_keymap_num_layouts_for_key(keymap, key) * @endcode * * @memberof xkb_state */ XKB_EXPORT xkb_layout_index_t xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t key); /** * Get the effective shift level for a key in a given keyboard state and * layout. * * @param state The keyboard state. * @param key The keycode of the key. * @param layout The layout for which to get the shift level. This must be * smaller than: * @code xkb_keymap_num_layouts_for_key(keymap, key) @endcode * usually it would be: * @code xkb_state_key_get_layout(state, key) @endcode * * @return The shift level index. If the key or layout are invalid, * returns `::XKB_LEVEL_INVALID`. * * @invariant If the returned level is valid, the following always holds: * @code * xkb_state_key_get_level(state, key, layout) < xkb_keymap_num_levels_for_key(keymap, key, layout) * @endcode * * @memberof xkb_state */ XKB_EXPORT xkb_level_index_t xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t key, xkb_layout_index_t layout); /** * Match flags for `xkb_state::xkb_state_mod_indices_are_active()` and * `xkb_state::xkb_state_mod_names_are_active()`, specifying the conditions for a * successful match. `::XKB_STATE_MATCH_NON_EXCLUSIVE` is bitmaskable with * the other modes. */ enum xkb_state_match { /** Returns true if any of the modifiers are active. */ XKB_STATE_MATCH_ANY = (1 << 0), /** Returns true if all of the modifiers are active. */ XKB_STATE_MATCH_ALL = (1 << 1), /** Makes matching non-exclusive, i.e. will not return false if a * modifier not specified in the arguments is active. */ XKB_STATE_MATCH_NON_EXCLUSIVE = (1 << 16) }; /** * The counterpart to `xkb_state::xkb_state_update_mask()` for modifiers, to be * used on the server side of serialization. * * This entry point is intended for *server* applications; see @ref * server-client-state for details. *Client* applications should use the * `xkb_state_mod_*_is_active` API. * * @param state The keyboard state. * @param components A mask of the modifier state components to serialize. * State components other than `XKB_STATE_MODS_*` are ignored. * If `::XKB_STATE_MODS_EFFECTIVE` is included, all other state components are * ignored. * * @returns A `xkb_mod_mask_t` representing the given components of the * modifier state. * * @memberof xkb_state */ XKB_EXPORT xkb_mod_mask_t xkb_state_serialize_mods(struct xkb_state *state, enum xkb_state_component components); /** * The counterpart to `xkb_state::xkb_state_update_mask()` for layouts, to be * used on the server side of serialization. * * This entry point is intended for *server* applications; see @ref * server-client-state for details. *Client* applications should use the * xkb_state_layout_*_is_active API. * * @param state The keyboard state. * @param components A mask of the layout state components to serialize. * State components other than `XKB_STATE_LAYOUT_*` are ignored. * If `::XKB_STATE_LAYOUT_EFFECTIVE` is included, all other state components are * ignored. * * @returns A layout index representing the given components of the * layout state. * * @memberof xkb_state */ XKB_EXPORT xkb_layout_index_t xkb_state_serialize_layout(struct xkb_state *state, enum xkb_state_component components); /** * Test whether a modifier is active in a given keyboard state by name. * * @warning For [virtual modifiers], this function may *overmatch* in case * there are virtual modifiers with overlapping mappings to [real modifiers]. * * @returns 1 if the modifier is active, 0 if it is not. If the modifier * name does not exist in the keymap, returns -1. * * @memberof xkb_state * * @since 0.1.0: Works only with *real* modifiers * @since 1.8.0: Works also with *virtual* modifiers * * [virtual modifiers]: @ref virtual-modifier-def * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT int xkb_state_mod_name_is_active(struct xkb_state *state, const char *name, enum xkb_state_component type); /** * Test whether a set of modifiers are active in a given keyboard state by * name. * * @warning For [virtual modifiers], this function may *overmatch* in case * there are virtual modifiers with overlapping mappings to [real modifiers]. * * @param state The keyboard state. * @param type The component of the state against which to match the * given modifiers. * @param match The manner by which to match the state against the * given modifiers. * @param ... The set of of modifier names to test, terminated by a NULL * argument (sentinel). * * @returns 1 if the modifiers are active, 0 if they are not. If any of * the modifier names do not exist in the keymap, returns -1. * * @memberof xkb_state * * @since 0.1.0: Works only with *real* modifiers * @since 1.8.0: Works also with *virtual* modifiers * * [virtual modifiers]: @ref virtual-modifier-def * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT int xkb_state_mod_names_are_active(struct xkb_state *state, enum xkb_state_component type, enum xkb_state_match match, ...); /** * Test whether a modifier is active in a given keyboard state by index. * * @warning For [virtual modifiers], this function may *overmatch* in case * there are virtual modifiers with overlapping mappings to [real modifiers]. * * @returns 1 if the modifier is active, 0 if it is not. If the modifier * index is invalid in the keymap, returns -1. * * @memberof xkb_state * * @since 0.1.0: Works only with *real* modifiers * @since 1.8.0: Works also with *virtual* modifiers * * [virtual modifiers]: @ref virtual-modifier-def * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT int xkb_state_mod_index_is_active(struct xkb_state *state, xkb_mod_index_t idx, enum xkb_state_component type); /** * Test whether a set of modifiers are active in a given keyboard state by * index. * * @warning For [virtual modifiers], this function may *overmatch* in case * there are virtual modifiers with overlapping mappings to [real modifiers]. * * @param state The keyboard state. * @param type The component of the state against which to match the * given modifiers. * @param match The manner by which to match the state against the * given modifiers. * @param ... The set of of modifier indices to test, terminated by a * `::XKB_MOD_INVALID` argument (sentinel). * * @returns 1 if the modifiers are active, 0 if they are not. If any of * the modifier indices are invalid in the keymap, returns -1. * * @memberof xkb_state * * @since 0.1.0: Works only with *real* modifiers * @since 1.8.0: Works also with *virtual* modifiers * * [virtual modifiers]: @ref virtual-modifier-def * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT int xkb_state_mod_indices_are_active(struct xkb_state *state, enum xkb_state_component type, enum xkb_state_match match, ...); /** * @page consumed-modifiers Consumed Modifiers * @parblock * * Some functions, like `xkb_state::xkb_state_key_get_syms()`, look at the state * of the modifiers in the keymap and derive from it the correct shift level * to use for the key. For example, in a US layout, pressing the key * labeled `
` while the Shift modifier is active, generates the keysym * `A`. In this case, the Shift modifier is said to be *consumed*. * However, the Num Lock modifier does not affect this translation at all, * even if it is active, so it is not consumed by this translation. * * It may be desirable for some application to not reuse consumed modifiers * for further processing, e.g. for hotkeys or keyboard shortcuts. To * understand why, consider some requirements from a standard shortcut * mechanism, and how they are implemented: * * 1. The shortcut’s modifiers must match exactly to the state. For * example, it is possible to bind separate actions to `` * and to ``. Further, if only `` is * bound to an action, pressing `` should not * trigger the shortcut. * Effectively, this means that the modifiers are compared using the * equality operator (`==`). * * 2. Only relevant modifiers are considered for the matching. For example, * Caps Lock and Num Lock should not generally affect the matching, e.g. * when matching `` against the state, it does not matter * whether Num Lock is active or not. These relevant, or *significant*, * modifiers usually include Alt, Control, Shift, Super and similar. * Effectively, this means that non-significant modifiers are masked out, * before doing the comparison as described above. * * 3. The matching must be independent of the layout/keymap. For example, * the `` (+) symbol is found on the first level on some layouts, * but requires holding Shift on others. If you simply bind the action * to the `` keysym, it would work for the unshifted kind, but * not for the others, because the match against Shift would fail. If * you bind the action to ``, only the shifted kind would * work. So what is needed is to recognize that Shift is used up in the * translation of the keysym itself, and therefore should not be included * in the matching. * Effectively, this means that consumed modifiers (Shift in this example) * are masked out as well, before doing the comparison. * * In summary, this is approximately how the matching would be performed: * * ```c * (keysym == shortcut_keysym) && * ((state_mods & ~consumed_mods & significant_mods) == shortcut_mods) * ``` * * @c state_mods are the modifiers reported by * `xkb_state::xkb_state_mod_index_is_active()` and similar functions. * @c consumed_mods are the modifiers reported by * `xkb_state::xkb_state_mod_index_is_consumed()` and similar functions. * @c significant_mods are decided upon by the application/toolkit/user; * it is up to them to decide whether these are configurable or hard-coded. * * @endparblock */ /** * Consumed modifiers mode. * * There are several possible methods for deciding which modifiers are * consumed and which are not, each applicable for different systems or * situations. The mode selects the method to use. * * Keep in mind that in all methods, the keymap may decide to *preserve* * a modifier, meaning it is not reported as consumed even if it would * have otherwise. */ enum xkb_consumed_mode { /** * This is the mode defined in the XKB specification and used by libX11. * * A modifier is consumed if and only if it *may affect* key translation. * * For example, if `Control+Alt+` produces some assigned keysym, * then when pressing just ``, `Control` and `Alt` are consumed, * even though they are not active, since if they *were* active they would * have affected key translation. */ XKB_CONSUMED_MODE_XKB, /** * This is the mode used by the GTK+ toolkit. * * The mode consists of the following two independent heuristics: * * - The currently active set of modifiers, excluding modifiers which do * not affect the key (as described for @ref XKB_CONSUMED_MODE_XKB), are * considered consumed, if the keysyms produced when all of them are * active are different from the keysyms produced when no modifiers are * active. * * - A single modifier is considered consumed if the keysyms produced for * the key when it is the only active modifier are different from the * keysyms produced when no modifiers are active. */ XKB_CONSUMED_MODE_GTK }; /** * Get the mask of modifiers consumed by translating a given key. * * @param state The keyboard state. * @param key The keycode of the key. * @param mode The consumed modifiers mode to use; see enum description. * * @returns a mask of the consumed [real modifiers] modifiers. * * @memberof xkb_state * @since 0.7.0 * * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT xkb_mod_mask_t xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t key, enum xkb_consumed_mode mode); /** * Same as `xkb_state_key_get_consumed_mods2()` with mode `::XKB_CONSUMED_MODE_XKB`. * * @memberof xkb_state * @since 0.4.1 */ XKB_EXPORT xkb_mod_mask_t xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key); /** * Test whether a modifier is consumed by keyboard state translation for * a key. * * @warning For [virtual modifiers], this function may *overmatch* in case * there are virtual modifiers with overlapping mappings to [real modifiers]. * * @param state The keyboard state. * @param key The keycode of the key. * @param idx The index of the modifier to check. * @param mode The consumed modifiers mode to use; see enum description. * * @returns 1 if the modifier is consumed, 0 if it is not. If the modifier * index is not valid in the keymap, returns -1. * * @sa xkb_state_mod_mask_remove_consumed() * @sa xkb_state_key_get_consumed_mods() * @memberof xkb_state * @since 0.7.0: Works only with *real* modifiers * @since 1.8.0: Works also with *virtual* modifiers * * [virtual modifiers]: @ref virtual-modifier-def * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT int xkb_state_mod_index_is_consumed2(struct xkb_state *state, xkb_keycode_t key, xkb_mod_index_t idx, enum xkb_consumed_mode mode); /** * Same as `xkb_state_mod_index_is_consumed2()` with mode `::XKB_CONSUMED_MOD_XKB`. * * @warning For [virtual modifiers], this function may *overmatch* in case * there are virtual modifiers with overlapping mappings to [real modifiers]. * * @memberof xkb_state * @since 0.4.1: Works only with *real* modifiers * @since 1.8.0: Works also with *virtual* modifiers * * [virtual modifiers]: @ref virtual-modifier-def * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT int xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key, xkb_mod_index_t idx); /** * Remove consumed modifiers from a modifier mask for a key. * * @deprecated Use `xkb_state_key_get_consumed_mods2()` instead. * * Takes the given modifier mask, and removes all modifiers which are * consumed for that particular key (as in `xkb_state_mod_index_is_consumed()`). * * @returns a mask of [real modifiers] modifiers. * * @sa xkb_state_mod_index_is_consumed() * @memberof xkb_state * @since 0.5.0: Works only with *real* modifiers * @since 1.8.0: Works also with *virtual* modifiers * * [real modifiers]: @ref real-modifier-def */ XKB_EXPORT xkb_mod_mask_t xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t key, xkb_mod_mask_t mask); /** * Test whether a layout is active in a given keyboard state by name. * * @returns 1 if the layout is active, 0 if it is not. If no layout with * this name exists in the keymap, return -1. * * If multiple layouts in the keymap have this name, the one with the lowest * index is tested. * * @sa xkb_layout_index_t * @memberof xkb_state */ XKB_EXPORT int xkb_state_layout_name_is_active(struct xkb_state *state, const char *name, enum xkb_state_component type); /** * Test whether a layout is active in a given keyboard state by index. * * @returns 1 if the layout is active, 0 if it is not. If the layout index * is not valid in the keymap, returns -1. * * @sa xkb_layout_index_t * @memberof xkb_state */ XKB_EXPORT int xkb_state_layout_index_is_active(struct xkb_state *state, xkb_layout_index_t idx, enum xkb_state_component type); /** * Test whether a LED is active in a given keyboard state by name. * * @returns 1 if the LED is active, 0 if it not. If no LED with this name * exists in the keymap, returns -1. * * @sa xkb_led_index_t * @memberof xkb_state */ XKB_EXPORT int xkb_state_led_name_is_active(struct xkb_state *state, const char *name); /** * Test whether a LED is active in a given keyboard state by index. * * @returns 1 if the LED is active, 0 if it not. If the LED index is not * valid in the keymap, returns -1. * * @sa xkb_led_index_t * @memberof xkb_state */ XKB_EXPORT int xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx); /** @} */ /* Leave this include last, so it can pick up our types, etc. */ #include #ifdef __cplusplus } /* extern "C" */ #endif #endif /* _XKBCOMMON_H_ */ xkbcommon-libxkbcommon-54ee7ac/include/xkbcommon/xkbregistry.h000066400000000000000000000600661510033435100250410ustar00rootroot00000000000000/* * Copyright © 2020 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #ifndef _XKBREGISTRY_H_ #define _XKBREGISTRY_H_ #include #include /** * @file * @brief Query for available RMLVO * */ #ifdef __cplusplus extern "C" { #endif #if defined(__GNUC__) && !defined(__CYGWIN__) # define RXKB_EXPORT __attribute__((visibility("default"))) #elif defined(_WIN32) # define RXKB_EXPORT __declspec(dllexport) #else # define RXKB_EXPORT #endif /** * @defgroup registry Query for available RMLVO * * The libxkbregistry API to query for available rules, models, layouts, * variants and options (RMLVO). libxkbregistry is a separate library to * libxkbcommon. * * This library is the replacement for clients currently parsing evdev.xml * directly. The library is intended to provide easy access to the set of * **possible** MLVO configurations for a given ruleset. It is not a library to * apply these configurations, merely to enumerate them. The intended users of * this library are the configuration UIs that allow a user to select their * keyboard layout of choice. * * @{ */ /** * @struct rxkb_context * * Opaque top level library context object. * * The context contains general library state, like include paths and parsed * data. Objects are created in a specific context, and multiple contexts * may coexist simultaneously. Objects from different contexts are * completely separated and do not share any memory or state. */ struct rxkb_context; /** * @struct rxkb_model * * Opaque struct representing an XKB model. */ struct rxkb_model; /** * @struct rxkb_layout * * Opaque struct representing an XKB layout, including an optional variant. * Where the variant is `NULL`, the layout is the base layout. * * For example, `us` is the base layout, `us(intl)` is the `intl` variant of the * layout `us`. */ struct rxkb_layout; /** * @struct rxkb_option_group * * Opaque struct representing an option group. Option groups divide the * individual options into logical groups. Their main purpose is to indicate * whether some options are mutually exclusive or not. */ struct rxkb_option_group; /** * @struct rxkb_option * * Opaque struct representing an XKB option. Options are grouped inside an @ref * rxkb_option_group. */ struct rxkb_option; /** * * @struct rxkb_iso639_code * * Opaque struct representing an ISO 639-3 code (e.g. `eng`, `fra`). There * is no guarantee that two identical ISO codes share the same struct. You * must not rely on the pointer value of this struct. * * See https://iso639-3.sil.org/code_tables/639/data for a list of codes. */ struct rxkb_iso639_code; /** * * @struct rxkb_iso3166_code * * Opaque struct representing an ISO 3166 Alpha 2 code (e.g. `US`, `FR`). * There is no guarantee that two identical ISO codes share the same struct. * You must not rely on the pointer value of this struct. * * See https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes for a list * of codes. */ struct rxkb_iso3166_code; /** * Describes the popularity of an item. Historically, some highly specialized or * experimental definitions are excluded from the default list and shipped in * separate files. If these extra definitions are loaded (see @ref * RXKB_CONTEXT_LOAD_EXOTIC_RULES), the popularity of the item is set * accordingly. * * If the exotic items are not loaded, all items will have the standard * popularity. */ enum rxkb_popularity { RXKB_POPULARITY_STANDARD = 1, RXKB_POPULARITY_EXOTIC, }; /** * Flags for context creation. */ enum rxkb_context_flags { RXKB_CONTEXT_NO_FLAGS = 0, /** * Skip the default include paths. This requires the caller to call * `rxkb_context_include_path_append()` or * `rxkb_context_include_path_append_default()`. */ RXKB_CONTEXT_NO_DEFAULT_INCLUDES = (1 << 0), /** * Load the extra items that are considered too exotic for the default list. * * For historical reasons, xkeyboard-config ships those exotic rules in a * separate file (e.g. `evdev.extras.xml`). Where the exotic rules are * requested, libxkbregistry will look for and load `$ruleset.extras.xml` * in the include paths, see `rxkb_context_include_path_append()` for * details on the lookup behavior. */ RXKB_CONTEXT_LOAD_EXOTIC_RULES = (1 << 1), /** * Disable the use of `secure_getenv()` for this context, so that privileged * processes can use environment variables. Client uses at their own risk. * * @since 1.5.0 */ RXKB_CONTEXT_NO_SECURE_GETENV = (1 << 2) }; /** * Create a new xkb registry context. * * The context has an initial refcount of 1. Use `rxkb_context_unref()` to * release memory associated with this context. * * Creating a context does not parse the files yet, use * `rxkb_context_parse()`. * * @param flags Flags affecting context behavior * @return A new xkb registry context or `NULL` on failure */ RXKB_EXPORT struct rxkb_context * rxkb_context_new(enum rxkb_context_flags flags); /** Specifies a logging level. */ enum rxkb_log_level { RXKB_LOG_LEVEL_CRITICAL = 10, /**< Log critical internal errors only. */ RXKB_LOG_LEVEL_ERROR = 20, /**< Log all errors. */ RXKB_LOG_LEVEL_WARNING = 30, /**< Log warnings and errors. */ RXKB_LOG_LEVEL_INFO = 40, /**< Log information, warnings, and errors. */ RXKB_LOG_LEVEL_DEBUG = 50 /**< Log everything. */ }; /** * Set the current logging level. * * @param ctx The context in which to set the logging level. * @param level The logging level to use. Only messages from this level * and below will be logged. * * The default level is `::RXKB_LOG_LEVEL_ERROR`. The environment variable * `RXKB_LOG_LEVEL`, if set at the time the context was created, overrides the * default value. It may be specified as a level number or name. */ RXKB_EXPORT void rxkb_context_set_log_level(struct rxkb_context *ctx, enum rxkb_log_level level); /** * Get the current logging level. */ RXKB_EXPORT enum rxkb_log_level rxkb_context_get_log_level(struct rxkb_context *ctx); /** * Set a custom function to handle logging messages. * * @param ctx The context in which to use the set logging function. * @param log_fn The function that will be called for logging messages. * Passing `NULL` restores the default function, which logs to `stderr`. * * By default, log messages from this library are printed to stderr. This * function allows you to replace the default behavior with a custom * handler. The handler is only called with messages which match the * current logging level and verbosity settings for the context. * level is the logging level of the message. @a format and @a args are * the same as in the `vprintf(3)` function. * * You may use `rxkb_context_set_user_data()` on the context, and then call * `rxkb_context_get_user_data()` from within the logging function to provide * it with additional private context. */ RXKB_EXPORT void rxkb_context_set_log_fn(struct rxkb_context *ctx, void (*log_fn)(struct rxkb_context *ctx, enum rxkb_log_level level, const char *format, va_list args)); /** * Parse the given ruleset. This can only be called once per context and once * parsed the data in the context is considered constant and will never * change. * * This function parses all files with the given ruleset name. See * rxkb_context_include_path_append() for details. * * If this function returns false, libxkbregistry failed to parse the xml files. * This is usually caused by invalid files on the host and should be debugged by * the host’s administrator using external tools. Callers should reduce the * include paths to known good paths and/or fall back to a default RMLVO set. * * If this function returns false, the context should be be considered dead and * must be released with `rxkb_context_unref()`. * * @param ctx The xkb registry context * @param ruleset The ruleset to parse, e.g. `evdev` * @return `true` on success or `false` on failure */ RXKB_EXPORT bool rxkb_context_parse(struct rxkb_context *ctx, const char *ruleset); /** * Parse the default ruleset as configured at build time. See * `rxkb_context_parse()` for details. */ RXKB_EXPORT bool rxkb_context_parse_default_ruleset(struct rxkb_context *ctx); /** * Increases the refcount of this object by one and returns the object. * * @param ctx The xkb registry context * @return The passed in object */ RXKB_EXPORT struct rxkb_context* rxkb_context_ref(struct rxkb_context *ctx); /** * Decreases the refcount of this object by one. Where the refcount of an * object hits zero, associated resources will be freed. * * @param ctx The xkb registry context * @return always `NULL` */ RXKB_EXPORT struct rxkb_context* rxkb_context_unref(struct rxkb_context *ctx); /** * Assign user-specific data. libxkbregistry will not look at or modify the * data, it will merely return the same pointer in * `rxkb_context_get_user_data()`. * * @param ctx The xkb registry context * @param user_data User-specific data pointer */ RXKB_EXPORT void rxkb_context_set_user_data(struct rxkb_context *ctx, void *user_data); /** * Return the pointer passed into `rxkb_context_get_user_data()`. * * @param ctx The xkb registry context * @return User-specific data pointer */ RXKB_EXPORT void * rxkb_context_get_user_data(struct rxkb_context *ctx); /** * Append a new entry to the context’s include path. * * The include path handling is optimized for the most common use-case: a set of * system files that provide a complete set of MLVO and some * custom MLVO provided by a user **in addition** to the system set. * * The include paths should be given so that the least complete path is * specified first and the most complete path is appended last. For example: * * ```c * ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES); * rxkb_context_include_path_append(ctx, `/home/user/.config/xkb`); * rxkb_context_include_path_append(ctx, `/usr/share/X11/xkb`); * rxkb_context_parse(ctx, `evdev`); * ``` * * The above example reflects the default behavior unless @ref * RXKB_CONTEXT_NO_DEFAULT_INCLUDES is provided. * * Loading of the files is in **reverse order**, i.e. the last path appended is * loaded first - in this case the ``/usr/share/X11/xkb`` path. * Any models, layouts, variants and options defined in the `evdev` ruleset * are loaded into the context. Then, any RMLVO found in the `evdev` ruleset of * the user’s path (``/home/user/.config/xkb`` in this example) are **appended** * to the existing set. * * Note that data from previously loaded include paths is never overwritten, * only appended to. It is not not possible to change the system-provided data, * only to append new models, layouts, variants and options to it. * * In other words, to define a new variant of the `us` layout called `banana`, * the following XML is sufficient. * * ```xml * * * * * us * * * * * banana * English (Banana) * * * * * * ``` * * The list of models, options and all other layouts (including `us` and its * variants) is taken from the system files. The resulting list of layouts will * thus have a `us` keyboard layout with the variant `banana` and all other * system-provided variants (`dvorak`, `colemak`, `intl`, etc.) * * This function must be called before `rxkb_context_parse()` or * `rxkb_context_parse_default_ruleset()`. * * @returns `true` on success, or `false` if the include path could not be added * or is inaccessible. */ RXKB_EXPORT bool rxkb_context_include_path_append(struct rxkb_context *ctx, const char *path); /** * Append the default include paths to the context’s include path. * See `rxkb_context_include_path_append()` for details about the merge order. * * This function must be called before `rxkb_context_parse()` or * `rxkb_context_parse_default_ruleset()`. * * @returns `true` on success, or `false` if the include path could not be added * or is inaccessible. */ RXKB_EXPORT bool rxkb_context_include_path_append_default(struct rxkb_context *ctx); /** * Return the first model for this context. Use this to start iterating over * the models, followed by calls to `rxkb_model_next()`. Models are not sorted. * * The refcount of the returned model is not increased. Use `rxkb_model_ref()` * if you need to keep this struct outside the immediate scope. * * @return The first model in the model list. */ RXKB_EXPORT struct rxkb_model * rxkb_model_first(struct rxkb_context *ctx); /** * Return the next model for this context. Returns `NULL` when no more models * are available. * * The refcount of the returned model is not increased. Use `rxkb_model_ref()` * if you need to keep this struct outside the immediate scope. * * @return the next model or `NULL` at the end of the list */ RXKB_EXPORT struct rxkb_model * rxkb_model_next(struct rxkb_model *m); /** * Increase the refcount of the argument by one. * * @returns The argument passed in to this function. */ RXKB_EXPORT struct rxkb_model * rxkb_model_ref(struct rxkb_model *m); /** * Decrease the refcount of the argument by one. When the refcount hits zero, * all memory associated with this struct is freed. * * @returns always `NULL` */ RXKB_EXPORT struct rxkb_model * rxkb_model_unref(struct rxkb_model *m); /** * Return the name of this model. This is the value for M in RMLVO, to be used * with libxkbcommon. */ RXKB_EXPORT const char * rxkb_model_get_name(struct rxkb_model *m); /** * Return a human-readable description of this model. This function may return * `NULL`. */ RXKB_EXPORT const char * rxkb_model_get_description(struct rxkb_model *m); /** * Return the vendor name for this model. This function may return `NULL`. */ RXKB_EXPORT const char * rxkb_model_get_vendor(struct rxkb_model *m); /** * Return the popularity for this model. */ RXKB_EXPORT enum rxkb_popularity rxkb_model_get_popularity(struct rxkb_model *m); /** * Return the first layout for this context. Use this to start iterating over * the layouts, followed by calls to `rxkb_layout_next()`. * * @note Layouts are not sorted. * * The refcount of the returned layout is not increased. * Use `rxkb_layout_ref()` if you need to keep this struct outside the immediate * scope. * * @return The first layout in the layout list. */ RXKB_EXPORT struct rxkb_layout * rxkb_layout_first(struct rxkb_context *ctx); /** * Return the next layout for this context. Returns `NULL` when no more layouts * are available. * * The refcount of the returned layout is not increased. Use `rxkb_layout_ref()` * if you need to keep this struct outside the immediate scope. * * @return the next layout or `NULL` at the end of the list */ RXKB_EXPORT struct rxkb_layout * rxkb_layout_next(struct rxkb_layout *l); /** * Increase the refcount of the argument by one. * * @returns The argument passed in to this function. */ RXKB_EXPORT struct rxkb_layout * rxkb_layout_ref(struct rxkb_layout *l); /** * Decrease the refcount of the argument by one. When the refcount hits zero, * all memory associated with this struct is freed. * * @returns always `NULL` */ RXKB_EXPORT struct rxkb_layout * rxkb_layout_unref(struct rxkb_layout *l); /** * Return the name of this layout. This is the value for L in RMLVO, to be used * with libxkbcommon. */ RXKB_EXPORT const char * rxkb_layout_get_name(struct rxkb_layout *l); /** * Return the variant of this layout. This is the value for V in RMLVO, to be * used with libxkbcommon. * * A variant does not stand on its own, it always depends on the base layout. * e.g. there may be multiple variants called `intl` but there is only one * `us(intl)`. * * Where the variant is `NULL`, the layout is the base layout (e.g. `us`). */ RXKB_EXPORT const char * rxkb_layout_get_variant(struct rxkb_layout *l); /** * Return a short (one-word) description of this layout. This function may * return `NULL`. */ RXKB_EXPORT const char * rxkb_layout_get_brief(struct rxkb_layout *l); /** * Return a human-readable description of this layout. This function may return * `NULL`. */ RXKB_EXPORT const char * rxkb_layout_get_description(struct rxkb_layout *l); /** * Return the popularity for this layout. */ RXKB_EXPORT enum rxkb_popularity rxkb_layout_get_popularity(struct rxkb_layout *l); /** * Return the first option group for this context. Use this to start iterating * over the option groups, followed by calls to `rxkb_option_group_next()`. * Option groups are not sorted. * * The refcount of the returned option group is not increased. Use * `rxkb_option_group_ref()` if you need to keep this struct outside the immediate * scope. * * @return The first option group in the option group list. */ RXKB_EXPORT struct rxkb_option_group * rxkb_option_group_first(struct rxkb_context *ctx); /** * Return the next option group for this context. Returns `NULL` when no more * option groups are available. * * The refcount of the returned option group is not increased. Use * `rxkb_option_group_ref()` if you need to keep this struct outside the immediate * scope. * * @return the next option group or `NULL` at the end of the list */ RXKB_EXPORT struct rxkb_option_group * rxkb_option_group_next(struct rxkb_option_group *g); /** * Increase the refcount of the argument by one. * * @returns The argument passed in to this function. */ RXKB_EXPORT struct rxkb_option_group * rxkb_option_group_ref(struct rxkb_option_group *g); /** * Decrease the refcount of the argument by one. When the refcount hits zero, * all memory associated with this struct is freed. * * @returns always `NULL` */ RXKB_EXPORT struct rxkb_option_group * rxkb_option_group_unref(struct rxkb_option_group *g); /** * Return the name of this option group. This is **not** the value for O in * RMLVO, the name can be used for internal sorting in the caller. This function * may return `NULL`. */ RXKB_EXPORT const char * rxkb_option_group_get_name(struct rxkb_option_group *m); /** * Return a human-readable description of this option group. This function may * return `NULL`. */ RXKB_EXPORT const char * rxkb_option_group_get_description(struct rxkb_option_group *m); /** * @return `true` if multiple options within this option group can be selected * simultaneously, `false` if all options within this option * group are mutually exclusive. */ RXKB_EXPORT bool rxkb_option_group_allows_multiple(struct rxkb_option_group *g); /** * Return the popularity for this option group. */ RXKB_EXPORT enum rxkb_popularity rxkb_option_group_get_popularity(struct rxkb_option_group *g); /** * Return the first option for this option group. Use this to start iterating * over the options, followed by calls to `rxkb_option_next()`. Options are not * sorted. * * The refcount of the returned option is not increased. Use `rxkb_option_ref()` * if you need to keep this struct outside the immediate scope. * * @return The first option in the option list. */ RXKB_EXPORT struct rxkb_option * rxkb_option_first(struct rxkb_option_group *group); /** * Return the next option for this option group. Returns `NULL` when no more * options are available. * * The refcount of the returned options is not increased. Use `rxkb_option_ref()` * if you need to keep this struct outside the immediate scope. * * @returns The next option or `NULL` at the end of the list */ RXKB_EXPORT struct rxkb_option * rxkb_option_next(struct rxkb_option *o); /** * Increase the refcount of the argument by one. * * @returns The argument passed in to this function. */ RXKB_EXPORT struct rxkb_option * rxkb_option_ref(struct rxkb_option *o); /** * Decrease the refcount of the argument by one. When the refcount hits zero, * all memory associated with this struct is freed. * * @returns always `NULL` */ RXKB_EXPORT struct rxkb_option * rxkb_option_unref(struct rxkb_option *o); /** * Return the name of this option. This is the value for O in RMLVO, to be used * with libxkbcommon. */ RXKB_EXPORT const char * rxkb_option_get_name(struct rxkb_option *o); /** * Return a short (one-word) description of this option. This function may * return `NULL`. */ RXKB_EXPORT const char * rxkb_option_get_brief(struct rxkb_option *o); /** * Return a human-readable description of this option. This function may return * `NULL`. */ RXKB_EXPORT const char * rxkb_option_get_description(struct rxkb_option *o); /** * Return the popularity for this option. */ RXKB_EXPORT enum rxkb_popularity rxkb_option_get_popularity(struct rxkb_option *o); /** * Return `true` if the given option accepts layout index specifiers to restrict * its application to the corresponding layouts, `false` otherwise. * * @sa `xkb_rmlvo_builder::xkb_rmlvo_builder_append_layout()` * @sa `xkb_rule_names::options` */ RXKB_EXPORT bool rxkb_option_is_layout_specific(struct rxkb_option *o); /** * Increase the refcount of the argument by one. * * @returns The argument passed in to this function. */ RXKB_EXPORT struct rxkb_iso639_code * rxkb_iso639_code_ref(struct rxkb_iso639_code *iso639); /** * Decrease the refcount of the argument by one. When the refcount hits zero, * all memory associated with this struct is freed. * * @returns always `NULL` */ RXKB_EXPORT struct rxkb_iso639_code * rxkb_iso639_code_unref(struct rxkb_iso639_code *iso639); /** * Return the ISO 639-3 code for this code. E.g. `eng`, `fra`. */ RXKB_EXPORT const char * rxkb_iso639_code_get_code(struct rxkb_iso639_code *iso639); /** * Return the first ISO 639 for this layout. Use this to start iterating over * the codes, followed by calls to `rxkb_iso639_code_next()`. Codes are not * sorted. * * The refcount of the returned code is not increased. * Use `rxkb_iso639_code_ref()` if you need to keep this struct outside the * immediate scope. * * @return The first code in the code list. */ RXKB_EXPORT struct rxkb_iso639_code * rxkb_layout_get_iso639_first(struct rxkb_layout *layout); /** * Return the next code in the list. Returns `NULL` when no more codes * are available. * * The refcount of the returned codes is not increased. * Use `rxkb_iso639_code_ref()` if you need to keep this struct outside the * immediate scope. * * @returns The next code or `NULL` at the end of the list */ RXKB_EXPORT struct rxkb_iso639_code * rxkb_iso639_code_next(struct rxkb_iso639_code *iso639); /** * Increase the refcount of the argument by one. * * @returns The argument passed in to this function. */ RXKB_EXPORT struct rxkb_iso3166_code * rxkb_iso3166_code_ref(struct rxkb_iso3166_code *iso3166); /** * Decrease the refcount of the argument by one. When the refcount hits zero, * all memory associated with this struct is freed. * * @returns always `NULL` */ RXKB_EXPORT struct rxkb_iso3166_code * rxkb_iso3166_code_unref(struct rxkb_iso3166_code *iso3166); /** * Return the ISO 3166 Alpha 2 code for this code (e.g. `US`, `FR`). */ RXKB_EXPORT const char * rxkb_iso3166_code_get_code(struct rxkb_iso3166_code *iso3166); /** * Return the first ISO 3166 for this layout. Use this to start iterating over * the codes, followed by calls to `rxkb_iso3166_code_next()`. Codes are not * sorted. * * The refcount of the returned code is not increased. Use * `rxkb_iso3166_code_ref()` if you need to keep this struct outside the immediate * scope. * * @return The first code in the code list. */ RXKB_EXPORT struct rxkb_iso3166_code * rxkb_layout_get_iso3166_first(struct rxkb_layout *layout); /** * Return the next code in the list. Returns `NULL` when no more codes * are available. * * The refcount of the returned codes is not increased. Use * `rxkb_iso3166_code_ref()` if you need to keep this struct outside the immediate * scope. * * @returns The next code or `NULL` at the end of the list */ RXKB_EXPORT struct rxkb_iso3166_code * rxkb_iso3166_code_next(struct rxkb_iso3166_code *iso3166); /** @} */ #ifdef __cplusplus } /* extern "C" */ #endif #endif /* _XKBREGISTRY_H_ */ xkbcommon-libxkbcommon-54ee7ac/meson.build000066400000000000000000001331141510033435100210300ustar00rootroot00000000000000project( 'libxkbcommon', 'c', version: '1.12.3', default_options: [ 'c_std=c11', 'warning_level=3', ], meson_version : '>= 0.58.0', # Released on May 2021 ) xkbcommon_project_version = meson.project_version().split('.') if xkbcommon_project_version[0] != '1' # The versioning used for the shared libraries assumes that the major # version of xkbcommon as a whole will increase to 2 if and only if there # is an ABI break, at which point we should probably bump the SONAME of # all libraries to .so.2. error('We probably need to bump the SONAME of libxkbcommon') else # To avoid an unnecessary SONAME bump, xkbcommon 1.x.y produces # libxkbcommon.so.0.x.y, libxkbcommon-x11.so.0.x.y, libxkbregistry.so.0.x.y. soname_version = '.'.join( ['0', xkbcommon_project_version[1], xkbcommon_project_version[2]] ) endif pkgconfig = import('pkgconfig') cc = meson.get_compiler('c') dir_libexec = get_option('prefix')/get_option('libexecdir')/'xkbcommon' # Compiler flags. cflags = [ '-fno-strict-aliasing', '-Wno-unused-parameter', '-Wno-missing-field-initializers', '-Wpointer-arith', '-Wmissing-declarations', '-Wformat=2', '-Wstrict-prototypes', '-Wmissing-prototypes', '-Wnested-externs', '-Wbad-function-cast', '-Wshadow', '-Wlogical-op', '-Wdate-time', '-Wwrite-strings', '-Wno-documentation-deprecated-sync', '-Wno-pedantic', '/utf-8', '/wd4100', # Disable MSVC C4100: unreferenced formal parameter ] add_project_arguments(cc.get_supported_arguments(cflags), language: 'c') # The legacy X11 config root. Only xkeyboard-config 2.* provides it. # This is intented when using old xkeyboard-config and as a last resort for # misconfigured setups. # Try both un- and versioned pkg-config (xkeyboard-config < 2.45). XKBLEGACYROOT = '' foreach v: ['-2', ''] xkeyboard_config_dep = dependency(f'xkeyboard-config@v@', required: false) if xkeyboard_config_dep.found() XKBLEGACYROOT = xkeyboard_config_dep.get_variable( pkgconfig: 'xkb_base', default_value: '' ) break endif endforeach if XKBLEGACYROOT == '' # Fallback to the legacy X11 directory XKBLEGACYROOT = get_option('prefix')/get_option('datadir')/'X11'/'xkb' endif # The XKB config root. XKBCONFIGROOT = get_option('xkb-config-root') if XKBCONFIGROOT == '' # Try to set from the xkeyboard-config package, from the most recent to the # oldest major version. The hard-coded major versions list should cover at # least a decade (and probably much more!), given the expected pace of # xkeyboard-config format changes. foreach v: [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2] xkeyboard_config_dep = dependency(f'xkeyboard-config-@v@', required: false) if xkeyboard_config_dep.found() XKBCONFIGROOT = xkeyboard_config_dep.get_variable(pkgconfig: 'xkb_root') break endif endforeach if XKBCONFIGROOT == '' # No xkeyboard-config or too old: use legacy X11 path fallback XKBCONFIGROOT = XKBLEGACYROOT endif endif XKBCONFIGEXTRAPATH = get_option('xkb-config-extra-path') if XKBCONFIGEXTRAPATH == '' XKBCONFIGEXTRAPATH = get_option('prefix')/get_option('sysconfdir')/'xkb' endif # The X locale directory for compose. XLOCALEDIR = get_option('x-locale-root') if XLOCALEDIR == '' XLOCALEDIR = get_option('prefix')/get_option('datadir')/'X11'/'locale' endif # config.h. configh_data = configuration_data() configh_data.set('EXIT_INVALID_USAGE', '2') configh_data.set_quoted('LIBXKBCOMMON_VERSION', meson.project_version()) configh_data.set_quoted('LIBXKBCOMMON_TOOL_PATH', dir_libexec) # Like AC_USE_SYSTEM_EXTENSIONS, what #define to use to get extensions # beyond the base POSIX function set. if host_machine.system() == 'sunos' system_extensions = '__EXTENSIONS__' else system_extensions = '_GNU_SOURCE' endif configh_data.set(system_extensions, 1) system_ext_define = '#define ' + system_extensions configh_data.set_quoted('DFLT_XKB_LEGACY_ROOT', XKBLEGACYROOT) configh_data.set_quoted('DFLT_XKB_CONFIG_ROOT', XKBCONFIGROOT) configh_data.set_quoted('DFLT_XKB_CONFIG_EXTRA_PATH', XKBCONFIGEXTRAPATH) configh_data.set_quoted('XLOCALEDIR', XLOCALEDIR) configh_data.set_quoted('DEFAULT_XKB_RULES', get_option('default-rules')) configh_data.set_quoted('DEFAULT_XKB_MODEL', get_option('default-model')) configh_data.set_quoted('DEFAULT_XKB_LAYOUT', get_option('default-layout')) if get_option('default-variant') != '' configh_data.set_quoted('DEFAULT_XKB_VARIANT', get_option('default-variant')) else configh_data.set('DEFAULT_XKB_VARIANT', 'NULL') endif if get_option('default-options') != '' configh_data.set_quoted('DEFAULT_XKB_OPTIONS', get_option('default-options')) else configh_data.set('DEFAULT_XKB_OPTIONS', 'NULL') endif if cc.has_header('unistd.h') configh_data.set('HAVE_UNISTD_H', 1) endif if cc.links('int main(){if(__builtin_expect(1<0,0)){}}', name: '__builtin_expect') configh_data.set('HAVE___BUILTIN_EXPECT', 1) endif if cc.has_header_symbol('unistd.h', 'eaccess', prefix: system_ext_define) configh_data.set('HAVE_EACCESS', 1) endif if cc.has_header_symbol('unistd.h', 'euidaccess', prefix: system_ext_define) configh_data.set('HAVE_EUIDACCESS', 1) endif if cc.has_header_symbol('sys/mman.h', 'mmap') configh_data.set('HAVE_MMAP', 1) endif if cc.has_header_symbol('stdlib.h', 'mkostemp', prefix: system_ext_define) configh_data.set('HAVE_MKOSTEMP', 1) endif if cc.has_header_symbol('fcntl.h', 'posix_fallocate', prefix: system_ext_define) configh_data.set('HAVE_POSIX_FALLOCATE', 1) endif if cc.has_header_symbol('string.h', 'strndup', prefix: system_ext_define) configh_data.set('HAVE_STRNDUP', 1) endif if cc.has_header_symbol('stdio.h', 'asprintf', prefix: system_ext_define) configh_data.set('HAVE_ASPRINTF', 1) elif cc.has_header_symbol('stdio.h', 'vasprintf', prefix: system_ext_define) configh_data.set('HAVE_VASPRINTF', 1) endif if cc.has_header_symbol('stdio.h', 'open_memstream', prefix: system_ext_define) configh_data.set('HAVE_OPEN_MEMSTREAM', 1) endif if cc.has_header_symbol('stdlib.h', 'secure_getenv', prefix: system_ext_define) configh_data.set('HAVE_SECURE_GETENV', 1) elif cc.has_header_symbol('stdlib.h', '__secure_getenv', prefix: system_ext_define) configh_data.set('HAVE___SECURE_GETENV', 1) else message('C library does not support secure_getenv, using getenv instead') endif if cc.has_header_symbol('stdlib.h', 'realpath', prefix: system_ext_define) configh_data.set('HAVE_REAL_PATH', 1) endif if not cc.has_header_symbol('limits.h', 'PATH_MAX', prefix: system_ext_define) if host_machine.system() == 'windows' # see https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation configh_data.set('PATH_MAX', 260) else configh_data.set('PATH_MAX', 4096) endif endif has_glibc = cc.has_function( 'gnu_get_libc_version', prefix: '#include ' ) has_compose_locale_fallback = false if cc.has_header_symbol('locale.h', 'newlocale', prefix: system_ext_define) # Use newlocale only if it fails on missing locales if meson.can_run_host_binaries() # Check newlocale implementation r = cc.run( ''' #define _GNU_SOURCE #include int main(void){ locale_t loc = newlocale(LC_ALL_MASK, "¡NONSENSE!", (locale_t) 0); return (loc != (locale_t) 0); }''', name: 'newlocale fails on invalid locales', ) if r.compiled() and r.returncode() == 0 has_compose_locale_fallback = true endif elif has_glibc # Cannot check implementation, so enable only for implementations # known to failed on missing locales. has_compose_locale_fallback = true endif if has_compose_locale_fallback configh_data.set('HAVE_NEWLOCALE', 1) endif endif # Silence some security & deprecation warnings on MSVC # for some unix/C functions we use. # https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4996?view=vs-2019 configh_data.set('_CRT_SECURE_NO_WARNINGS', 1) configh_data.set('_CRT_NONSTDC_NO_WARNINGS', 1) configh_data.set('_CRT_NONSTDC_NO_DEPRECATE', 1) # Reduce unnecessary includes on MSVC. configh_data.set('WIN32_LEAN_AND_MEAN', 1) xkbcommon_map = meson.current_source_dir() / 'xkbcommon.map' # Supports -Wl,--version-script? meson_test_map = meson.current_source_dir() / 'test/meson_test.map' have_version_script = cc.links( 'int main() { return 0; }', args: f'-Wl,--version-script=@meson_test_map@', name: '-Wl,--version-script', ) map_to_def = find_program('scripts/map-to-def') # libxkbcommon. bison = find_program('bison', 'win_bison', required: true, version: '>= 3.6') yacc = bison yacc_gen = generator( bison, output: ['@BASENAME@.c', '@BASENAME@.h'], arguments: ['--defines=@OUTPUT1@', '-o', '@OUTPUT0@', '-p', '_xkbcommon_', '@INPUT@'], ) libxkbcommon_sources = [ 'src/compose/constants.h', 'src/compose/parser.c', 'src/compose/parser.h', 'src/compose/paths.c', 'src/compose/paths.h', 'src/compose/state.c', 'src/compose/table.c', 'src/compose/table.h', 'src/xkbcomp/action.c', 'src/xkbcomp/action.h', 'src/xkbcomp/ast.h', 'src/xkbcomp/ast-build.c', 'src/xkbcomp/ast-build.h', 'src/xkbcomp/compat.c', 'src/xkbcomp/expr.c', 'src/xkbcomp/expr.h', 'src/xkbcomp/include.c', 'src/xkbcomp/include.h', 'src/xkbcomp/keycodes.c', 'src/xkbcomp/keymap.c', 'src/xkbcomp/keymap-dump.c', 'src/xkbcomp/keywords.c', yacc_gen.process('src/xkbcomp/parser.y'), 'src/xkbcomp/parser-priv.h', 'src/xkbcomp/rules.c', 'src/xkbcomp/rules.h', 'src/xkbcomp/scanner.c', 'src/xkbcomp/symbols.c', 'src/xkbcomp/types.c', 'src/xkbcomp/vmod.c', 'src/xkbcomp/vmod.h', 'src/xkbcomp/xkbcomp.c', 'src/xkbcomp/xkbcomp-priv.h', 'src/atom.c', 'src/atom.h', 'src/context.c', 'src/context.h', 'src/context-priv.c', 'src/darray.h', 'src/keysym.c', 'src/keysym.h', 'src/keysym-case-mappings.c', 'src/keysym-utf.c', 'src/ks_tables.h', 'src/keymap.c', 'src/keymap.h', 'src/keymap-compare.c', 'src/keymap-compare.h', 'src/keymap-priv.c', 'src/messages-codes.h', 'src/rmlvo.c', 'src/rmlvo.h', 'src/scanner-utils.c', 'src/scanner-utils.h', 'src/state.c', 'src/text.c', 'src/text.h', 'src/utf8.c', 'src/utf8.h', 'src/utf8-decoding.c', 'src/utf8-decoding.h', 'src/utils.c', 'src/utils.h', 'src/util-mem.h', 'src/utils-checked-arithmetic.h', 'src/utils-numbers.h', 'src/utils-paths.c', 'src/utils-paths.h', ] libxkbcommon_link_args = [] libxkbcommon_link_deps = [] if have_version_script libxkbcommon_link_args += f'-Wl,--version-script=@xkbcommon_map@' libxkbcommon_link_deps += 'xkbcommon.map' elif cc.get_argument_syntax() == 'msvc' libxkbcommon_def = custom_target('xkbcommon.def', command: [map_to_def, '@INPUT@', '@OUTPUT@'], input: 'xkbcommon.map', output: 'xkbcommon.def', ) libxkbcommon_link_deps += libxkbcommon_def libxkbcommon_link_args += '/DEF:' + libxkbcommon_def.full_path() endif libxkbcommon = library( 'xkbcommon', 'include/xkbcommon/xkbcommon.h', libxkbcommon_sources, link_args: libxkbcommon_link_args, link_depends: libxkbcommon_link_deps, gnu_symbol_visibility: 'hidden', version: soname_version, install: true, include_directories: include_directories('src', 'include'), ) install_headers( 'include/xkbcommon/xkbcommon.h', 'include/xkbcommon/xkbcommon-compat.h', 'include/xkbcommon/xkbcommon-compose.h', 'include/xkbcommon/xkbcommon-keysyms.h', 'include/xkbcommon/xkbcommon-names.h', subdir: 'xkbcommon', ) dep_libxkbcommon = declare_dependency( link_with: libxkbcommon, include_directories: include_directories('include'), ) meson.override_dependency('xkbcommon', dep_libxkbcommon) pkgconfig.generate( libxkbcommon, name: 'xkbcommon', filebase: 'xkbcommon', version: meson.project_version(), description: 'XKB API common to servers and clients', ) # libxkbcommon-x11. if get_option('enable-x11') xcb_dep = dependency('xcb', version: '>=1.10', required: false) xcb_xkb_dep = dependency('xcb-xkb', version: '>=1.10', required: false) if not xcb_dep.found() or not xcb_xkb_dep.found() error('''X11 support requires xcb-xkb >= 1.10 which was not found. You can disable X11 support with -Denable-x11=false.''') endif libxkbcommon_x11_sources = [ 'src/x11/keymap.c', 'src/x11/state.c', 'src/x11/util.c', 'src/x11/x11-priv.h', 'src/context.h', 'src/context-priv.c', 'src/keymap.h', 'src/keymap-priv.c', 'src/atom.h', 'src/atom.c', ] libxkbcommon_x11_link_args = [] libxkbcommon_x11_link_deps = [] if have_version_script libxkbcommon_x11_link_args += '-Wl,--version-script=' + meson.current_source_dir()/'xkbcommon-x11.map' libxkbcommon_x11_link_deps += 'xkbcommon-x11.map' elif cc.get_argument_syntax() == 'msvc' libxkbcommon_x11_def = custom_target('xkbcommon-x11.def', command: [map_to_def, '@INPUT@', '@OUTPUT@'], input: 'xkbcommon-x11.map', output: 'xkbcommon-x11.def', ) libxkbcommon_x11_link_deps += libxkbcommon_x11_def libxkbcommon_x11_link_args += '/DEF:' + libxkbcommon_x11_def.full_path() endif libxkbcommon_x11 = library( 'xkbcommon-x11', 'include/xkbcommon/xkbcommon-x11.h', libxkbcommon_x11_sources, link_args: libxkbcommon_x11_link_args, link_depends: libxkbcommon_x11_link_deps, gnu_symbol_visibility: 'hidden', version: soname_version, install: true, include_directories: include_directories('src', 'include'), link_with: libxkbcommon, dependencies: [ xcb_dep, xcb_xkb_dep, ], ) install_headers( 'include/xkbcommon/xkbcommon-x11.h', subdir: 'xkbcommon', ) dep_libxkbcommon_x11 = declare_dependency( link_with: libxkbcommon_x11, include_directories: include_directories('include'), ) meson.override_dependency('xkbcommon-x11', dep_libxkbcommon_x11) pkgconfig.generate( libxkbcommon_x11, name: 'xkbcommon-x11', filebase: 'xkbcommon-x11', version: meson.project_version(), description: 'XKB API common to servers and clients - X11 support', requires: ['xkbcommon'], requires_private: ['xcb>=1.10', 'xcb-xkb>=1.10'], ) endif # libxkbregistry if get_option('enable-xkbregistry') dep_libxml = dependency('libxml-2.0') # Since libxml-2.13 if cc.has_header_symbol( 'libxml/parser.h', 'xmlCtxtSetErrorHandler', prefix: system_ext_define, ) configh_data.set10('HAVE_XML_CTXT_SET_ERRORHANDLER', true) endif # Since libxml-2.14 if cc.has_header_symbol( 'libxml/parser.h', 'xmlCtxtParseDtd', prefix: system_ext_define, ) configh_data.set10('HAVE_XML_CTXT_PARSE_DTD', true) endif deps_libxkbregistry = [dep_libxml] libxkbregistry_sources = [ 'src/registry.c', 'src/messages-codes.h', 'src/utils.h', 'src/utils.c', 'src/util-list.h', 'src/util-list.c', 'src/util-mem.h', ] libxkbregistry_link_args = [] libxkbregistry_link_deps = [] if have_version_script libxkbregistry_link_args += '-Wl,--version-script=' + meson.current_source_dir()/'xkbregistry.map' libxkbregistry_link_deps += 'xkbregistry.map' elif cc.get_argument_syntax() == 'msvc' libxkbregistry_def = custom_target('xkbregistry.def', command: [map_to_def, '@INPUT@', '@OUTPUT@'], input: 'xkbregistry.map', output: 'xkbregistry.def', ) libxkbregistry_link_deps += libxkbregistry_def libxkbregistry_link_args += '/DEF:' + libxkbregistry_def.full_path() endif libxkbregistry = library( 'xkbregistry', 'include/xkbcommon/xkbregistry.h', libxkbregistry_sources, link_args: libxkbregistry_link_args, link_depends: libxkbregistry_link_deps, gnu_symbol_visibility: 'hidden', dependencies: deps_libxkbregistry, version: soname_version, install: true, include_directories: include_directories('src', 'include'), ) install_headers( 'include/xkbcommon/xkbregistry.h', subdir: 'xkbcommon', ) pkgconfig.generate( libxkbregistry, name: 'xkbregistry', filebase: 'xkbregistry', version: meson.project_version(), description: 'XKB API to query available rules, models, layouts, variants and options', ) dep_libxkbregistry = declare_dependency( link_with: libxkbregistry, include_directories: include_directories('include'), ) meson.override_dependency('xkbregistry', dep_libxkbregistry) endif man_pages = [] # Tools icu_dep = dependency('icu-uc', required: false) build_tools = get_option('enable-tools') and cc.has_header_symbol('getopt.h', 'getopt_long', prefix: '#define _GNU_SOURCE') if build_tools # Common resources tools_dep = declare_dependency( sources: [ 'tools/tools-common.h', 'tools/tools-common.c', 'src/compose/constants.h', 'src/utf8-decoding.c', 'src/utf8-decoding.h', ], include_directories: [include_directories('tools', 'include')], dependencies: dep_libxkbcommon, ) configh_data.set10('HAVE_TOOLS', true) # Tool: export-keysyms export_keysym_dep = [tools_dep] if icu_dep.found() export_keysym_dep += [icu_dep] endif executable('export-keysyms', 'tools/export-keysyms.c', libxkbcommon_sources, dependencies: export_keysym_dep, c_args: ['-DENABLE_PRIVATE_APIS'], include_directories: [include_directories('src', 'include')], install: false) # Tool: xkbcli executable('xkbcli', 'tools/xkbcli.c', dependencies: tools_dep, install: true) install_man('tools/xkbcli.1') if get_option('enable-bash-completion') bash_completion_path = get_option('bash-completion-path') if bash_completion_path == '' bash_completion = dependency('bash-completion', required: false) if bash_completion.found() bash_completion_path = bash_completion.get_variable(pkgconfig: 'completionsdir') else bash_completion_path = get_option('datadir') / 'bash-completion/completions' endif endif install_data('tools/xkbcli-bash-completion.sh', rename: 'xkbcli', install_dir: bash_completion_path) endif # Tool: compile-keymap xkbcli_compile_keymap = executable('xkbcli-compile-keymap', 'tools/compile-keymap.c', 'src/keymap-formats.c', 'src/keymap-formats.h', dependencies: tools_dep, install: true, install_dir: dir_libexec) install_man('tools/xkbcli-compile-keymap.1') configh_data.set10('HAVE_XKBCLI_COMPILE_KEYMAP', true) # Tool: compose executable('xkbcli-compile-compose', 'tools/compile-compose.c', 'src/compose/dump.c', 'src/compose/dump.h', 'src/compose/escape.h', dependencies: tools_dep, install: true, install_dir: dir_libexec) install_man('tools/xkbcli-compile-compose.1') configh_data.set10('HAVE_XKBCLI_COMPILE_COMPOSE', true) # Tool: how-to-type executable('xkbcli-how-to-type', 'tools/how-to-type.c', 'src/keymap-formats.c', 'src/keymap-formats.h', dependencies: tools_dep, install: true, install_dir: dir_libexec) install_man('tools/xkbcli-how-to-type.1') configh_data.set10('HAVE_XKBCLI_HOW_TO_TYPE', true) # Tool: interactive-evdev if cc.has_header('linux/input.h') executable('xkbcli-interactive-evdev', 'tools/interactive-evdev.c', 'src/keymap-formats.c', 'src/keymap-formats.h', dependencies: tools_dep, install: true, install_dir: dir_libexec) configh_data.set10('HAVE_XKBCLI_INTERACTIVE_EVDEV', true) install_man('tools/xkbcli-interactive-evdev.1') endif # Tools: interactive-x11 if get_option('enable-x11') x11_tools_dep = declare_dependency( link_with: libxkbcommon_x11, dependencies: [ tools_dep, xcb_dep, xcb_xkb_dep, ], ) executable('xkbcli-interactive-x11', 'tools/interactive-x11.c', 'src/keymap-formats.c', 'src/keymap-formats.h', 'src/utils.h', dependencies: x11_tools_dep, install: true, install_dir: dir_libexec) install_man('tools/xkbcli-interactive-x11.1') configh_data.set10('HAVE_XKBCLI_INTERACTIVE_X11', true) executable('xkbcli-dump-keymap-x11', 'tools/interactive-x11.c', 'src/keymap-formats.c', 'src/keymap-formats.h', 'src/utils.h', dependencies: x11_tools_dep, c_args: ['-DKEYMAP_DUMP'], install: true, install_dir: dir_libexec) install_man('tools/xkbcli-dump-keymap-x11.1') configh_data.set10('HAVE_XKBCLI_DUMP_KEYMAP_X11', true) endif # Tools: interactive-wayland if get_option('enable-wayland') wayland_client_dep = dependency('wayland-client', version: '>=1.2.0', required: false) wayland_protocols_dep = dependency('wayland-protocols', version: '>=1.15', required: false) wayland_scanner_dep = dependency('wayland-scanner', required: false, native: true) if not wayland_client_dep.found() or not wayland_protocols_dep.found() or not wayland_scanner_dep.found() error('''The Wayland xkbcli programs require wayland-client and wayland-protocols which were not found. You can disable the Wayland xkbcli programs with -Denable-wayland=false.''') endif wayland_scanner = find_program(wayland_scanner_dep.get_variable(pkgconfig: 'wayland_scanner')) wayland_scanner_code_gen = generator( wayland_scanner, output: '@BASENAME@-protocol.c', arguments: ['private-code', '@INPUT@', '@OUTPUT@'], ) wayland_scanner_client_header_gen = generator( wayland_scanner, output: '@BASENAME@-client-protocol.h', arguments: ['client-header', '@INPUT@', '@OUTPUT@'], ) wayland_protocols_datadir = wayland_protocols_dep.get_variable(pkgconfig: 'pkgdatadir') xdg_shell_xml = wayland_protocols_datadir/'stable/xdg-shell/xdg-shell.xml' xdg_shell_sources = [ wayland_scanner_code_gen.process(xdg_shell_xml), wayland_scanner_client_header_gen.process(xdg_shell_xml), ] xdg_decoration_xml = wayland_protocols_datadir/'unstable/xdg-decoration/xdg-decoration-unstable-v1.xml' xdg_decoration_sources = [ wayland_scanner_code_gen.process(xdg_decoration_xml), wayland_scanner_client_header_gen.process(xdg_decoration_xml), ] executable('xkbcli-interactive-wayland', 'tools/interactive-wayland.c', 'src/keymap-formats.c', 'src/keymap-formats.h', 'src/utils.h', xdg_shell_sources, xdg_decoration_sources, dependencies: [tools_dep, wayland_client_dep], install: true, install_dir: dir_libexec) install_man('tools/xkbcli-interactive-wayland.1') configh_data.set10('HAVE_XKBCLI_INTERACTIVE_WAYLAND', true) executable('xkbcli-dump-keymap-wayland', 'tools/interactive-wayland.c', 'src/keymap-formats.c', 'src/keymap-formats.h', 'src/utils.h', xdg_shell_sources, xdg_decoration_sources, dependencies: [tools_dep, wayland_client_dep], c_args: ['-DKEYMAP_DUMP'], install: true, install_dir: dir_libexec) install_man('tools/xkbcli-dump-keymap-wayland.1') configh_data.set10('HAVE_XKBCLI_DUMP_KEYMAP_WAYLAND', true) endif # Tool: interactive if ( configh_data.get('HAVE_XKBCLI_INTERACTIVE_WAYLAND', 0) == 1 or configh_data.get('HAVE_XKBCLI_INTERACTIVE_X11', 0) == 1 or configh_data.get('HAVE_XKBCLI_INTERACTIVE_EVDEV', 0) == 1 ) executable('xkbcli-interactive', 'tools/interactive.c', dependencies: tools_dep, install: true, install_dir: dir_libexec) endif # Tool: dump-keymap if ( configh_data.get('HAVE_XKBCLI_DUMP_KEYMAP_WAYLAND', 0) == 1 or configh_data.get('HAVE_XKBCLI_DUMP_KEYMAP_X11', 0) == 1 ) executable('xkbcli-dump-keymap', 'tools/interactive.c', c_args: ['-DKEYMAP_DUMP'], dependencies: tools_dep, install: true, install_dir: dir_libexec) endif # Tool: list if get_option('enable-xkbregistry') configh_data.set10('HAVE_XKBCLI_LIST', true) executable('xkbcli-list', 'tools/registry-list.c', dependencies: dep_libxkbregistry, install: true, install_dir: dir_libexec) install_man('tools/xkbcli-list.1') endif # Tool: check-messages executable('xkb-check-messages', 'tools/check-messages.c', 'tools/messages.c', 'tools/messages.h', 'src/messages-codes.h', dependencies: [tools_dep], include_directories: [include_directories('src', 'include', 'tools')], install: false) else tools_dep = declare_dependency() endif # xkeyboard-config "verifier" xkct_config = configuration_data() xkct_config.set('MESON_BUILD_ROOT', meson.current_build_dir()) xkct_config.set('XKB_CONFIG_ROOT', XKBCONFIGROOT) configure_file(input: 'test/xkeyboard-config-test.py.in', output: 'xkeyboard-config-test', configuration: xkct_config) # Tests test_env = environment() test_env.set('XKB_LOG_LEVEL', 'debug') test_env.set('XKB_LOG_VERBOSITY', '10') test_env.set('top_srcdir', meson.current_source_dir()) test_env.set('top_builddir', meson.current_build_dir()) test_env.set('HAVE_XKBCLI_INTERACTIVE_EVDEV', configh_data.get('HAVE_XKBCLI_INTERACTIVE_EVDEV', 0).to_string()) test_env.set('HAVE_XKBCLI_INTERACTIVE_WAYLAND', configh_data.get('HAVE_XKBCLI_INTERACTIVE_WAYLAND', 0).to_string()) test_env.set('HAVE_XKBCLI_INTERACTIVE_X11', configh_data.get('HAVE_XKBCLI_INTERACTIVE_X11', 0).to_string()) test_env.set('HAVE_XKBCLI_LIST', configh_data.get('HAVE_XKBCLI_LIST', 0).to_string()) test_configh_data = configuration_data() test_configh_data.set_quoted('TEST_XKB_CONFIG_ROOT', meson.current_source_dir()/'test'/'data') configure_file(output: 'test-config.h', configuration: test_configh_data) m_dep = cc.find_library('m', required : false) # Some tests need to use unexported symbols, so we link them against # an internal copy of libxkbcommon with all symbols exposed. libxkbcommon_test_internal = library( 'xkbcommon-test-internal', libxkbcommon_sources, 'src/xkbcomp/keymap-file-iterator.c', 'src/xkbcomp/keymap-file-iterator.h', include_directories: include_directories('src', 'include'), c_args: ['-DENABLE_PRIVATE_APIS'], gnu_symbol_visibility: 'hidden', ) test_dep = declare_dependency( sources: [ 'bench/bench.c', 'bench/bench.h', 'src/utils-numbers.h', 'src/utf8-decoding.c', 'src/utf8-decoding.h', 'test/common.c', 'test/evdev-scancodes.h', 'test/test.h', 'tools/tools-common.c', 'tools/tools-common.h', ], include_directories: include_directories('src', 'include'), link_with: libxkbcommon_test_internal, dependencies: [m_dep], ) if build_tools # Tool: introspection executable( 'introspection', 'tools/introspection.c', 'src/utils.c', 'src/utils.h', 'src/keymap-formats.c', 'src/keymap-formats.h', 'src/xkbcomp/keymap-file-iterator.h', dependencies: test_dep, include_directories: include_directories('src', 'src/xkbcomp', 'include'), install: false ) introspection_config = configuration_data() introspection_config.set('MESON_BUILD_ROOT', meson.current_build_dir()) introspection_config.set('DEFAULT_XKB_RULES', get_option('default-rules')) introspection_config.set('DEFAULT_XKB_MODEL', get_option('default-model')) introspection_config.set('DEFAULT_XKB_LAYOUT', get_option('default-layout')) introspection_config.set('DEFAULT_XKB_VARIANT', get_option('default-variant')) introspection_config.set('DEFAULT_XKB_OPTIONS', get_option('default-options')) configure_file( input: 'tools/introspection-query.py.in', output: 'introspection-query', configuration: introspection_config ) endif if get_option('enable-x11') libxkbcommon_x11_test_internal = library( 'xkbcommon-x11-internal', libxkbcommon_x11_sources, include_directories: include_directories('src', 'include'), c_args: ['-DENABLE_PRIVATE_APIS'], gnu_symbol_visibility: 'hidden', link_with: libxkbcommon_test_internal, dependencies: [ xcb_dep, xcb_xkb_dep, ], ) x11_test_dep = declare_dependency( link_with: libxkbcommon_x11_test_internal, dependencies: [ test_dep, xcb_dep, ], ) x11_xvfb_test_dep = declare_dependency( sources: [ 'test/xvfb-wrapper.c', 'test/xvfb-wrapper.h', ], dependencies: [x11_test_dep], ) endif # TODO: version range? keysyms_test_dep = [test_dep] keysyms_test_c_args = ['-DENABLE_PRIVATE_APIS'] if icu_dep.found() keysyms_test_dep += [icu_dep] configh_data.set10('HAVE_ICU', true) endif test( 'keysym', executable('test-keysym', 'test/keysym.c', 'test/keysym.h', dependencies: keysyms_test_dep, c_args: keysyms_test_c_args), env: test_env, ) test( 'keysym-unicode', executable('test-keysym-unicode', 'test/keysym-unicode.c', dependencies: keysyms_test_dep, c_args: keysyms_test_c_args), env: test_env, ) test( 'keymap', executable( 'test-keymap', 'test/keymap.c', 'test/keysym.h', 'test/keysym-case-mapping.h', 'src/keymap-formats.c', 'src/keymap-formats.h', dependencies: test_dep), env: test_env, ) test( 'filecomp', executable('test-filecomp', 'test/filecomp.c', dependencies: test_dep), env: test_env, ) test( 'context', executable('test-context', 'test/context.c', dependencies: test_dep), env: test_env, ) test( 'rules-file', executable('test-rules-file', 'test/rules-file.c', dependencies: test_dep), env: test_env, ) test( 'rules-file-includes', executable('test-rules-file-includes', 'test/rules-file-includes.c', dependencies: test_dep), env: test_env, ) test( 'stringcomp', executable( 'test-stringcomp', 'test/stringcomp.c', 'test/utils-text.c', 'test/utils-text.h', dependencies: test_dep ), env: test_env, ) test( 'buffercomp', executable('test-buffercomp', 'test/buffercomp.c', dependencies: test_dep), env: test_env, ) test( 'introspection', executable( 'test-introspection', 'test/introspection.c', dependencies: test_dep ), env: test_env, ) # The merge modes tests are optional and generated locally on-the-fly pymod = import('python') python = pymod.find_installation('python3', modules: ['jinja2'], required: false) has_merge_modes_tests = python.found() and python.language_version().version_compare('>=3.11') if has_merge_modes_tests script = find_program('scripts/update-merge-modes-tests.py') merge_modes_tests = [meson.project_name()] # NOTE: The following tests deal with third-party XKB compilers and are # reserved for debugging purposes. Uncomment to enable them. # merge_modes_tests += 'xkbcomp' # Xorg XKB compiler # merge_modes_tests += 'kbvm' # Jay compositor XKB compiler foreach xkb_compiler: merge_modes_tests if xkb_compiler == meson.project_name() suffix = '' extra_args = [] extra_source_files = [] else suffix = '-' + xkb_compiler extra_args = [xkb_compiler] extra_source_files = ['test/external_xkb_compilers.h'] endif filename = f'merge-modes@suffix@.c' merge_modes_c = custom_target( filename, build_by_default: true, command: [ script, '--root', meson.project_source_root(), '--c-out', '@OUTPUT@', '--no-xkb', ] + extra_args, depend_files: ['test/merge_modes.c.jinja'], output: filename, capture: false, install: false ) test( f'merge-modes@suffix@', executable( f'test-merge-modes@suffix@', merge_modes_c, extra_source_files, dependencies: test_dep, include_directories: ['test'], ), env: test_env, ) endforeach endif test( 'log', executable('test-log', 'test/log.c', dependencies: test_dep), env: test_env, ) test( 'atom', executable('test-atom', 'test/atom.c', dependencies: test_dep), env: test_env, ) test( 'utf8', executable( 'test-utf8', 'test/utf8.c', 'src/utf8-decoding.c', 'src/utf8-decoding.h', dependencies: test_dep ), env: test_env, ) test( 'state', executable('test-state', 'test/state.c', dependencies: test_dep), env: test_env, ) test( 'keyseq', executable('test-keyseq', 'test/keyseq.c', dependencies: test_dep), env: test_env, ) test( 'rulescomp', executable('test-rulescomp', 'test/rulescomp.c', dependencies: test_dep), env: test_env, ) test( 'compose', executable( 'test-compose', 'test/compose.c', 'test/compose-iter.c', 'test/compose-iter.h', 'test/utils-text.c', 'test/utils-text.h', 'src/compose/constants.h', 'src/compose/dump.c', 'src/compose/dump.h', 'src/compose/escape.h', 'src/compose/escape.h', 'src/compose/parser.h', dependencies: test_dep ), env: test_env, ) test( 'utils', executable( 'test-utils', 'src/utils.h', 'src/utils-numbers.h', 'src/utils-paths.h', 'test/utils.c', 'test/utils-text.c', 'test/utils-text.h', dependencies: test_dep ), env: test_env, ) test( 'symbols-leak-test', find_program('test/symbols-leak-test.py'), env: test_env, suite: ['python-tests'], ) test( 'modifiers', executable('test-modifiers', 'test/modifiers.c', dependencies: test_dep), env: test_env, ) test( 'messages', executable( 'test-messages', 'test/messages.c', 'tools/messages.c', 'tools/messages.h', include_directories: include_directories('src', 'include', 'tools'), dependencies: test_dep), env: test_env, ) if get_option('enable-x11') has_xvfb = find_program('Xvfb', required: false) has_xkbcomp = find_program('xkbcomp', required: false) # We only warn because the build machine may not be the same # as the host/test machine. if not has_xvfb.found() warning('Xvfb program not found, but is required to run X11 tests.') endif if not has_xkbcomp.found() warning('xkbcomp program not found, but is required to run X11 tests.') endif test( 'x11', executable('test-x11', 'test/x11.c', dependencies: x11_xvfb_test_dep), env: test_env, is_parallel : false, ) test( 'x11comp', executable( 'test-x11comp', 'test/x11comp.c', 'test/utils-text.c', 'test/utils-text.h', dependencies: x11_xvfb_test_dep ), env: test_env, is_parallel : false, ) endif if get_option('enable-xkbregistry') test( 'registry', executable('test-registry', 'test/registry.c', include_directories: include_directories('src'), dependencies: [dep_libxkbregistry, dep_libxml, test_dep]), env: test_env, ) endif if build_tools test('tool-option-parsing', find_program('test/tool-option-parsing.py'), env: test_env, suite: ['python-tests']) # A set of keysyms to test for. Add one or two symbols to this array # whenever the xorgproto gets updated to make sure we resolve them. keysyms_to_test = [ 'XF86Macro23', ] env = environment() env.set('XKB_CONFIG_ROOT', meson.current_source_dir()/'test'/'data') foreach keysym: keysyms_to_test test('keysym-test-@0@'.format(keysym), find_program('test/test-keysym.py'), env: env, args: [keysym, '--tool', xkbcli_compile_keymap], suite: ['python-tests']) endforeach endif valgrind = find_program('valgrind', required: false) if valgrind.found() add_test_setup('valgrind', exe_wrapper: [valgrind, '--leak-check=full', '--track-origins=yes', '--gen-suppressions=all', '--error-exitcode=99'], # This is used in some tests, to avoid excessive run time. env: {'RUNNING_VALGRIND': '1'}, timeout_multiplier : 10) else message('valgrind not found, disabling valgrind test setup') endif # Fuzzing target programs. executable('fuzz-keymap', 'fuzz/keymap/target.c', dependencies: test_dep) executable('fuzz-compose', 'fuzz/compose/target.c', dependencies: test_dep) # Benchmarks. bench_env = environment() bench_env.set('top_srcdir', meson.current_source_dir()) benchmark( 'key-proc', executable('bench-key-proc', 'bench/key-proc.c', dependencies: test_dep), env: bench_env, ) benchmark( 'keysym-case-mappings', executable( 'bench-keysym-case-mappings', 'bench/keysym-case-mappings.c', dependencies: test_dep, c_args: ['-DENABLE_PRIVATE_APIS'], ), ) benchmark( 'rulescomp', executable('bench-rulescomp', 'bench/rulescomp.c', dependencies: test_dep), env: bench_env, ) if cc.has_header_symbol('getopt.h', 'getopt_long', prefix: '#define _GNU_SOURCE') benchmark( 'rules', executable('bench-rules', 'bench/rules.c', dependencies: test_dep), env: bench_env, ) benchmark( 'compile-keymap', executable( 'bench-compile-keymap', 'bench/compile-keymap.c', 'src/keymap-formats.c', 'src/keymap-formats.h', 'src/utils.c', 'src/utils.h', dependencies: test_dep ), env: bench_env, ) benchmark( 'dump-keymap', executable( 'bench-dump-keymap', 'bench/compile-keymap.c', 'src/keymap-formats.c', 'src/keymap-formats.h', dependencies: test_dep, c_args: ['-DKEYMAP_DUMP'], ), env: bench_env, ) benchmark( 'custom-parsers', executable( 'bench-custom-parsers', 'bench/custom-parsers.c', 'src/utils.c', 'src/utils.h', 'src/utils-numbers.h', dependencies: test_dep, ), env: bench_env, ) endif benchmark( 'compose', executable('bench-compose', 'bench/compose.c', dependencies: test_dep), env: bench_env, ) benchmark( 'compose-traversal', executable( 'bench-compose-traversal', 'bench/compose-traversal.c', 'bench/bench.h', 'src/compose/constants.h', 'test/compose-iter.c', 'test/compose-iter.h', 'test/test.h', dependencies: test_dep ), env: bench_env, ) benchmark( 'atom', executable('bench-atom', 'bench/atom.c', dependencies: test_dep), env: bench_env, ) if get_option('enable-x11') benchmark( 'x11', executable('bench-x11', 'bench/x11.c', dependencies: x11_test_dep), env: bench_env, ) endif # Documentation. if get_option('enable-docs') doxygen = find_program('doxygen', required: false) if not doxygen.found() error('''Documentation requires doxygen which was not found. You can disable the documentation with -Denable-docs=false.''') endif doxygen_wrapper = find_program('scripts/doxygen-wrapper') doxygen_input = [ 'README.md', 'LICENSE', 'NEWS.md', 'meson_options.txt', 'doc/debugging.md', 'doc/diagrams/xkb-configuration.dot', 'doc/diagrams/xkb-keymap-components.dot', 'doc/diagrams/xkb-types-explanation.dot', 'doc/doxygen-extra.css', 'doc/faq.md', 'doc/introduction-to-xkb.md', 'doc/quick-guide.md', 'doc/compatibility.md', 'doc/user-configuration.md', 'doc/rules-format.md', 'doc/keymap-text-format-v1-v2.md', 'doc/message-registry.md', 'doc/release-notes.md', 'doc/license.md', 'include/xkbcommon/xkbcommon.h', 'include/xkbcommon/xkbcommon-compose.h', 'include/xkbcommon/xkbcommon-keysyms.h', 'include/xkbcommon/xkbcommon-names.h', 'include/xkbcommon/xkbcommon-x11.h', 'include/xkbcommon/xkbregistry.h', ] doxygen_data = configuration_data() doxygen_data.set('PACKAGE_NAME', meson.project_name()) doxygen_data.set('PACKAGE_VERSION', meson.project_version()) doxygen_data.set('INPUT', ' '.join(doxygen_input)) doxygen_data.set('OUTPUT_DIRECTORY', meson.current_build_dir()) doxyfile = configure_file( input: 'doc/Doxyfile.in', output: 'Doxyfile', configuration: doxygen_data, ) # TODO: Meson should provide this. docdir = get_option('datadir')/'doc'/meson.project_name() doc_gen = custom_target( 'doc', input: [doxyfile] + doxygen_input, output: 'html', command: [ doxygen_wrapper, doxygen, meson.current_build_dir()/'Doxyfile', meson.current_source_dir(), ], install: true, install_dir: docdir, build_by_default: true, ) if get_option('enable-cool-uris') ensure_stable_urls = find_program('scripts'/'ensure-stable-doc-urls.py') custom_target( 'doc-cool-uris', input: [doc_gen, 'doc'/'cool-uris.yaml'], output: 'html-xtra', command: [ ensure_stable_urls, 'generate-redirections', meson.current_source_dir()/'doc'/'cool-uris.yaml', meson.current_build_dir()/'html' ], install: false, build_by_default: true, ) endif endif configure_file(output: 'config.h', configuration: configh_data) # Stable variables for projects using xkbcommon as a subproject. # These variables should not be renamed. libxkbcommon_dep = dep_libxkbcommon if get_option('enable-x11') libxkbcommon_x11_dep = dep_libxkbcommon_x11 endif if get_option('enable-xkbregistry') libxkbregistry_dep = dep_libxkbregistry endif if meson.version().version_compare('>=0.62.0') summary({ 'backend': meson.backend(), 'buildtype': get_option('buildtype'), 'id': cc.get_id(), 'c_args': get_option('c_args'), 'c_link_args': get_option('c_link_args'), 'yacc': yacc.full_path() + ' ' + yacc.version(), 'glibc': has_glibc, }, section: 'Compiler') summary({ 'prefix': get_option('prefix'), 'bindir': get_option('bindir'), 'libdir': get_option('libdir'), 'datadir': get_option('datadir'), 'xkb-config-root': XKBCONFIGROOT, 'xkb-config-extra-path': XKBCONFIGEXTRAPATH, 'xlocaledir': XLOCALEDIR, }, section: 'Directories') summary({ 'docs': get_option('enable-docs'), 'tools': get_option('enable-tools'), 'wayland': get_option('enable-wayland'), 'x11': get_option('enable-x11'), 'compose locale fallback': has_compose_locale_fallback, }, section: 'Features') summary({ 'layout': get_option('default-layout'), 'model': get_option('default-model'), 'options': get_option('default-options'), 'rules': get_option('default-rules'), 'variant': get_option('default-variant'), }, section: 'Defaults') summary({ 'merge-modes': has_merge_modes_tests, }, section: 'Tests') endif xkbcommon-libxkbcommon-54ee7ac/meson_options.txt000066400000000000000000000037231510033435100223250ustar00rootroot00000000000000option( 'xkb-config-root', type: 'string', description: 'The XKB config root [default=xkeyboard-config install path]', ) option( 'xkb-config-extra-path', type: 'string', description: 'Extra lookup path for system-wide XKB data [default=$sysconfdir/xkb]', ) option( 'x-locale-root', type: 'string', description: 'The X locale root [default=$datadir/X11/locale]', ) option( 'bash-completion-path', type: 'string', description: 'Directory for bash completion scripts' ) option( 'default-rules', type: 'string', value: 'evdev', description: 'Default XKB ruleset', ) option( 'default-model', type: 'string', value: 'pc105', description: 'Default XKB model', ) option( 'default-layout', type: 'string', value: 'us', description: 'Default XKB layout', ) option( 'default-variant', type: 'string', value: '', description: 'Default XKB variant', ) option( 'default-options', type: 'string', value: '', description: 'Default XKB options', ) option( 'enable-tools', type: 'boolean', value: true, description: 'Enable building tools', ) option( 'enable-x11', type: 'boolean', value: true, description: 'Enable building the xkbcommon-x11 library', ) option( 'enable-docs', type: 'boolean', value: false, description: 'Enable building the documentation', ) option( 'enable-cool-uris', type: 'boolean', value: false, description: 'Enable creating redirections to maintain stable documentation pages', ) option( 'enable-wayland', type: 'boolean', value: true, description: 'Enable support for Wayland utility programs (requires enable-tools)', ) option( 'enable-xkbregistry', type: 'boolean', value: true, description: 'Enable building libxkbregistry', ) option( 'enable-bash-completion', type: 'boolean', value: true, description: 'Enable installing bash completion scripts', ) xkbcommon-libxkbcommon-54ee7ac/scripts/000077500000000000000000000000001510033435100203525ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/scripts/doxygen-wrapper000077500000000000000000000007111510033435100234320ustar00rootroot00000000000000#!/bin/sh # Run doxygen such that the working directory is the source root. # This is needed for various reasons (e.g. relative references in md files). # Do not use directly. DOXYGEN="$1" DOXYFILE="$2" ABS_TOP_SRCDIR="$3" # Set environment variables that are unset if [ -z "$DOXYGEN_WARN_AS_ERROR" ] then export DOXYGEN_WARN_AS_ERROR="NO" fi if [ -z "$DOXYGEN_QUIET" ] then export DOXYGEN_QUIET="YES" fi cd "$ABS_TOP_SRCDIR" && exec "$DOXYGEN" "$DOXYFILE" xkbcommon-libxkbcommon-54ee7ac/scripts/ensure-stable-doc-urls.py000077500000000000000000000241351510033435100252330ustar00rootroot00000000000000#!/usr/bin/env python3 # Doc URLs may change with time because they depend on Doxygen machinery. # This is unfortunate because it is good practice to keep valid URLs. # See: “Cool URIs don’t change” at https://www.w3.org/Provider/Style/URI.html. # # There is no built-in solution in Doxygen that we are aware of. # The solution proposed here is to maintain a registry of all URLs and manage # legacy URLs as redirections to their canonical page. import argparse from enum import IntFlag import glob from itertools import chain from pathlib import Path from string import Template from typing import NamedTuple, Sequence import yaml class Update(NamedTuple): new: str old: str class ExitCode(IntFlag): NORMAL = 0 INVALID_UPDATES = 1 << 4 MISSING_UPDATES = 1 << 5 NON_UNIQUE_DIRECTIONS = 1 << 6 THIS_SCRIPT_PATH = Path(__file__) RELATIVE_SCRIPT_PATH = THIS_SCRIPT_PATH.relative_to(THIS_SCRIPT_PATH.parent.parent) REDIRECTION_DELAY = 6 # in seconds. Note: at least 6s for accessibility REDIRECTION_TITLE = "xkbcommon: Page Redirection" OPTIONAL_ENTRY = "__optional__" # NOTE: The redirection works with the HTML tag: . # See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta#http-equiv # # NOTE: This page is a simplified version of the Doxygen-generated ones. # It does use the current stylesheets, but it may break if the theme is updated. # Ideally, we would just let Doxygen generate them, but I (Wismill) could not # find a way to do this with the redirection feature. REDIRECTION_PAGE_TEMPLATE = Template( """ ${title}
libxkbcommon
""" ) def parse_page_update(update: str) -> Update: updateʹ = Update(*update.split("=")) if updateʹ.new == updateʹ.old: raise ValueError(f"Invalid update: {updateʹ}") return updateʹ def is_page_redirection(path: Path): with path.open("rt", encoding="utf-8") as fd: for line in fd: if REDIRECTION_TITLE in line: return True return False def update_registry(registry_path: Path, doc_dir: Path, updates: Sequence[str]): """ Update the URL registry by: • Adding new pages • Updating page aliases """ # Parse updates updates_ = dict(map(parse_page_update, updates)) # Update invalid_updates = set(updates_) # Load previous registry with registry_path.open("rt", encoding="utf-8") as fd: registry: dict[str, list[str]] = yaml.safe_load(fd) or {} registryʹ = dict( (canonical, aliases) for canonical, aliases in registry.items() if canonical != OPTIONAL_ENTRY ) # Expected updates missing_updates = set( canonical for canonical in registryʹ if not (doc_dir / canonical).is_file() ) # Ensure each page is unique for d, rs in registryʹ.items(): if clashes := frozenset(rs).intersection(registry): print( f"[ERROR] The following redirections of “{d}”", f"clash with canonical directions: {clashes}", ) exit(ExitCode.NON_UNIQUE_DIRECTIONS) redirections = frozenset(chain.from_iterable(registryʹ.values())) for file in glob.iglob("**/*.html", root_dir=doc_dir, recursive=True): # Skip redirection pages if file in redirections: continue # Get previous entry and potential update if old := updates_.get(file): # Update old entry invalid_updates.remove(file) entry = registry.get(old) if entry is None: raise ValueError(f"Invalid update: {file}<-{old}") else: del registry[old] missing_updates.remove(old) registry[file] = [e for e in [old] + entry if e != file] print(f"[INFO] Updated: “{old}” to “{file}”") else: entry = registry.get(file) if entry is None: # New entry registry[file] = [] print(f"[INFO] Added: {file}") else: # Keep previous entry pass exit_code = ExitCode.NORMAL # Check if invalid_updates: for update in invalid_updates: print(f"[ERROR] Update not processed: {update}") exit_code |= ExitCode.INVALID_UPDATES if missing_updates: for old in missing_updates: # Handle older Doxygen versions if old in registry.get(OPTIONAL_ENTRY, []): print( "[WARNING] Handling old Doxygen version:", f"skip optional “{old}”", ) missing_updates.remove(old) continue old_redirections = registry[old] for r in old_redirections: path = doc_dir / r if path.is_file() and not is_page_redirection(path): print( "[WARNING] Handling old Doxygen version:", f"use “{r}” instead of “{old}” for the canonical direction", ) missing_updates.remove(old) break else: print(f"[ERROR] “{old}” not found and has no update.") if missing_updates: exit_code |= ExitCode.MISSING_UPDATES if exit_code: print("[ERROR] Processing interrupted: please fix the errors above.") exit(exit_code.value) # Write changes with registry_path.open("wt", encoding="utf-8") as fd: fd.write(f"# WARNING: This file is autogenerated by: {RELATIVE_SCRIPT_PATH}\n") fd.write("# Do not edit manually.\n") yaml.dump(registry, fd) def generate_redirections(registry_path: Path, doc_dir: Path): """ Create redirection pages using the aliases in the given URL registry. """ cool = True # Load registry with registry_path.open("rt", encoding="utf-8") as fd: registry: dict[str, list[str]] = yaml.safe_load(fd) or {} registryʹ = dict( (canonical, aliases) for canonical, aliases in registry.items() if canonical != OPTIONAL_ENTRY ) for canonical, aliases in registryʹ.items(): # Check canonical path is up-to-date if not (doc_dir / canonical).is_file(): # Handle older Doxygen versions if canonical in registry.get(OPTIONAL_ENTRY, []): print( "[WARNING] Handling old Doxygen version:", f"skip optional “{canonical}”", ) continue for r in aliases: path = doc_dir / r if path.is_file() and not is_page_redirection(path): print( "[WARNING] Handling old Doxygen version:", f"use “{r}” instead of “{canonical}” for the canonical direction", ) canonical = r aliases.remove(r) break else: cool = False print( f"ERROR: missing canonical documentation page “{canonical}”. " f"Please update “{registry_path}” using {RELATIVE_SCRIPT_PATH}”." ) # Add a redirection page for alias in aliases: path = doc_dir / alias with path.open("wt", encoding="utf-8") as fd: fd.write( REDIRECTION_PAGE_TEMPLATE.substitute( canonical=canonical, delay=REDIRECTION_DELAY, title=REDIRECTION_TITLE, ) ) if not cool: exit(1) def add_registry_argument(parser): parser.add_argument( "registry", type=Path, help="Path to the doc URI registry.", ) def add_docdir_argument(parser): parser.add_argument( "docdir", type=Path, metavar="DOC_DIR", help="Path to the generated HTML documentation directory.", ) if __name__ == "__main__": parser = argparse.ArgumentParser( description="Tool to ensure HTML documentation has stable URLs" ) subparsers = parser.add_subparsers() parser_registry = subparsers.add_parser( "update-registry", help="Update the registry of URIs" ) add_registry_argument(parser_registry) add_docdir_argument(parser_registry) parser_registry.add_argument( "updates", nargs="*", type=str, help="Update: new=previous entries", ) parser_registry.set_defaults( run=lambda args: update_registry(args.registry, args.docdir, args.updates) ) parser_redirections = subparsers.add_parser( "generate-redirections", help="Generate URIs redirections" ) add_registry_argument(parser_redirections) add_docdir_argument(parser_redirections) parser_redirections.set_defaults( run=lambda args: generate_redirections(args.registry, args.docdir) ) args = parser.parse_args() args.run(args) xkbcommon-libxkbcommon-54ee7ac/scripts/map-to-def000077500000000000000000000013521510033435100222320ustar00rootroot00000000000000#!/usr/bin/env python """A script to generate MSVC Module-Definition files from version-script files (which are maintained manually).""" import re import sys import pathlib def symbols_from_map(path): return re.findall(r"^\s+(r?xkb_.*);", path.read_text("utf-8"), re.MULTILINE) if 2 > len(sys.argv) > 3: raise SystemExit("Usage: {} file.map [file.def]".format(sys.argv[0])) map_file = pathlib.Path(sys.argv[1]) map_symbols = set(symbols_from_map(map_file)) if len(sys.argv) == 3: def_file = open(sys.argv[2], "w", encoding="utf-8") else: def_file = sys.stdout def_file.write("LIBRARY {}\n".format(map_file.stem)) def_file.write("EXPORTS\n") for symbol in sorted(map_symbols): def_file.write("\t{}\n".format(symbol)) xkbcommon-libxkbcommon-54ee7ac/scripts/perfect_hash.py000066400000000000000000000540071510033435100233650ustar00rootroot00000000000000# Derived from: https://github.com/ilanschnell/perfect-hash # Commit: 6b7dd80a525dbd4349ea2c69f04a9c96f3c2fd54 # BSD 3-Clause License # # Copyright (c) 2019 - 2021, Ilan Schnell # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the Ilan Schnell nor the # names of its contributors may be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL ILAN SCHNELL BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. """ Generate a minimal perfect hash function for the keys in a file, desired hash values may be specified within this file as well. A given code template is filled with parameters, such that the output is code which implements the hash function. Templates can easily be constructed for any programming language. The code is based on an a program A.M. Kuchling wrote: http://www.amk.ca/python/code/perfect-hash The algorithm the program uses is described in the paper 'Optimal algorithms for minimal perfect hashing', Z. J. Czech, G. Havas and B.S. Majewski. http://citeseer.ist.psu.edu/122364.html The algorithm works like this: 1. You have K keys, that you want to perfectly hash against some desired hash values. 2. Choose a number N larger than K. This is the number of vertices in a graph G, and also the size of the resulting table G. 3. Pick two random hash functions f1, f2, that return values from 0..N-1. 4. Now, for all keys, you draw an edge between vertices f1(key) and f2(key) of the graph G, and associate the desired hash value with that edge. 5. If G is cyclic, go back to step 2. 6. Assign values to each vertex such that, for each edge, you can add the values for the two vertices and get the desired (hash) value for that edge. This task is easy, because the graph is acyclic. This is done by picking a vertex, and assigning it a value of 0. Then do a depth-first search, assigning values to new vertices so that they sum up properly. 7. f1, f2, and vertex values of G now make up a perfect hash function. For simplicity, the implementation of the algorithm combines steps 5 and 6. That is, we check for loops in G and assign the vertex values in one procedure. If this procedure succeeds, G is acyclic and the vertex values are assigned. If the procedure fails, G is cyclic, and we go back to step 2, replacing G with a new graph, and thereby discarding the vertex values from the failed attempt. """ from __future__ import absolute_import, division, print_function import random import shutil import string import subprocess import sys import tempfile from collections import defaultdict from optparse import Values from os.path import join from typing import Any, Sequence, TypeVar if sys.version_info[0] == 2: from cStringIO import StringIO else: from io import StringIO __version__ = "0.4.2" verbose = False trials = 150 class Graph(object): """ Implements a graph with 'N' vertices. First, you connect the graph with edges, which have a desired value associated. Then the vertex values are assigned, which will fail if the graph is cyclic. The vertex values are assigned such that the two values corresponding to an edge add up to the desired edge value (mod N). """ def __init__(self, N: int): self.N = N # number of vertices # maps a vertex number to the list of tuples (vertex, edge value) # to which it is connected by edges. self.adjacent: dict[int, list[tuple[int, int]]] = defaultdict(list) def connect(self, vertex1: int, vertex2: int, edge_value: int) -> None: """ Connect 'vertex1' and 'vertex2' with an edge, with associated value 'value' """ # Add vertices to each other's adjacent list self.adjacent[vertex1].append((vertex2, edge_value)) self.adjacent[vertex2].append((vertex1, edge_value)) def assign_vertex_values(self) -> bool: """ Try to assign the vertex values, such that, for each edge, you can add the values for the two vertices involved and get the desired value for that edge, i.e. the desired hash key. This will fail when the graph is cyclic. This is done by a Depth-First Search of the graph. If the search finds a vertex that was visited before, there's a loop and False is returned immediately, i.e. the assignment is terminated. On success (when the graph is acyclic) True is returned. """ self.vertex_values = self.N * [-1] # -1 means unassigned visited = self.N * [False] # Loop over all vertices, taking unvisited ones as roots. for root in range(self.N): if visited[root]: continue # explore tree starting at 'root' self.vertex_values[root] = 0 # set arbitrarily to zero # Stack of vertices to visit, a list of tuples (parent, vertex) tovisit: list[tuple[int | None, int]] = [(None, root)] while tovisit: parent, vertex = tovisit.pop() visited[vertex] = True # Loop over adjacent vertices, but skip the vertex we arrived # here from the first time it is encountered. skip = True for neighbor, edge_value in self.adjacent[vertex]: if skip and neighbor == parent: skip = False continue if visited[neighbor]: # We visited here before, so the graph is cyclic. return False tovisit.append((vertex, neighbor)) # Set new vertex's value to the desired edge value, # minus the value of the vertex we came here from. self.vertex_values[neighbor] = ( edge_value - self.vertex_values[vertex] ) % self.N # check if all vertices have a valid value for vertex in range(self.N): assert self.vertex_values[vertex] >= 0 # We got though, so the graph is acyclic, # and all values are now assigned. return True class StrSaltHash: """ Random hash function generator. Simple byte level hashing: each byte is multiplied to another byte from a random string of characters, summed up, and finally modulo NG is taken. """ chars = string.ascii_letters + string.digits def __init__(self, N: int): self.N = N self.salt = "" def __call__(self, key: Sequence[str]) -> int: # XXX: xkbcommon modification: make the salt length a power of 2 # so that the % operation in the hash is fast. while len(self.salt) < max(len(key), 32): # add more salt as necessary self.salt += random.choice(self.chars) return sum(ord(self.salt[i]) * ord(c) for i, c in enumerate(key)) % self.N template = """ def hash_f(key, T): return sum(ord(T[i % $NS]) * ord(c) for i, c in enumerate(key)) % $NG def perfect_hash(key): return (G[hash_f(key, "$S1")] + G[hash_f(key, "$S2")]) % $NG """ class IntSaltHash: """ Random hash function generator. Simple byte level hashing, each byte is multiplied in sequence to a table containing random numbers, summed tp, and finally modulo NG is taken. """ def __init__(self, N: int): self.N: int = N self.salt: list[int] = [] def __call__(self, key: Sequence[str]) -> int: while len(self.salt) < len(key): # add more salt as necessary self.salt.append(random.randint(1, self.N - 1)) return sum(self.salt[i] * ord(c) for i, c in enumerate(key)) % self.N template = """ S1 = [$S1] S2 = [$S2] assert len(S1) == len(S2) == $NS def hash_f(key, T): return sum(T[i % $NS] * ord(c) for i, c in enumerate(key)) % $NG def perfect_hash(key): return (G[hash_f(key, S1)] + G[hash_f(key, S2)]) % $NG """ H = TypeVar("H", StrSaltHash, IntSaltHash) def builtin_template(Hash: type[H]) -> str: return ( """\ # ======================================================================= # ================= Python code for perfect hash function =============== # ======================================================================= G = [$G] """ + Hash.template + """ # ============================ Sanity check ============================= K = [$K] assert len(K) == $NK for h, k in enumerate(K): assert perfect_hash(k) == h """ ) class TooManyInterationsError(Exception): pass # NOTE: as of mypy 1.13, it is not possible to specify a default value for a generic # parameter, so `Hash: type[H] = StrSaltHash` will raise a type error. See: # • https://github.com/python/mypy/issues/3737 # • https://github.com/python/mypy/issues/18017 def generate_hash( keys: list[str], Hash: type[H] = StrSaltHash ) -> tuple[H, H, list[int]]: """ Return hash functions f1 and f2, and G for a perfect minimal hash. Input is an iterable of 'keys', whos indicies are the desired hash values. 'Hash' is a random hash function generator, that means Hash(N) returns a returns a random hash function which returns hash values from 0..N-1. """ if not isinstance(keys, (list, tuple)): raise TypeError("list or tuple expected") NK = len(keys) if NK != len(set(keys)): raise ValueError("duplicate keys") for key in keys: if not isinstance(key, str): raise TypeError("key a not string: %r" % key) if NK > 10000 and Hash == StrSaltHash: print( """\ WARNING: You have %d keys. Using --hft=1 is likely to fail for so many keys. Please use --hft=2 instead. """ % NK ) # the number of vertices in the graph G NG = NK + 1 if verbose: print("NG = %d" % NG) trial = 0 # Number of trial graphs so far while True: if (trial % trials) == 0: # trials failures, increase NG slightly if trial > 0: NG = max(NG + 1, int(1.05 * NG)) if verbose: sys.stdout.write("\nGenerating graphs NG = %d " % NG) trial += 1 if NG > 100 * (NK + 1): raise TooManyInterationsError("%d keys" % NK) if verbose: sys.stdout.write(".") sys.stdout.flush() G = Graph(NG) # Create graph with NG vertices f1 = Hash(NG) # Create 2 random hash functions f2 = Hash(NG) # Connect vertices given by the values of the two hash functions # for each key. Associate the desired hash value with each edge. for hashval, key in enumerate(keys): G.connect(f1(key), f2(key), hashval) # Try to assign the vertex values. This will fail when the graph # is cyclic. But when the graph is acyclic it will succeed and we # break out, because we're done. if G.assign_vertex_values(): break if verbose: print("\nAcyclic graph found after %d trials." % trial) print("NG = %d" % NG) # Sanity check the result by actually verifying that all the keys # hash to the right value. for hashval, key in enumerate(keys): assert hashval == (G.vertex_values[f1(key)] + G.vertex_values[f2(key)]) % NG if verbose: print("OK") return f1, f2, G.vertex_values class Format(object): def __init__(self, width: int = 76, indent: int = 4, delimiter: str = ", "): self.width = width self.indent = indent self.delimiter = delimiter def print_format(self) -> None: print("Format options:") for name in "width", "indent", "delimiter": print(" %s: %r" % (name, getattr(self, name))) def __call__(self, data: Any, quote: bool = False) -> str: if not isinstance(data, (list, tuple)): return str(data) lendel = len(self.delimiter) aux = StringIO() pos = 20 for i, elt in enumerate(data): last = bool(i == len(data) - 1) s = ('"%s"' if quote else "%s") % elt if pos + len(s) + lendel > self.width: aux.write("\n" + (self.indent * " ")) pos = self.indent aux.write(s) pos += len(s) if not last: aux.write(self.delimiter) pos += lendel return "\n".join(l.rstrip() for l in aux.getvalue().split("\n")) def generate_code( keys: list[str], Hash: type[H] = StrSaltHash, template: str | None = None, options: Values | None = None, ) -> str: """ Takes a list of key value pairs and inserts the generated parameter lists into the 'template' string. 'Hash' is the random hash function generator, and the optional keywords are formating options. The return value is the substituted code template. """ f1, f2, G = generate_hash(keys, Hash) assert f1.N == f2.N == len(G) try: salt_len = len(f1.salt) assert salt_len == len(f2.salt) except TypeError: salt_len = None if template is None: template = builtin_template(Hash) if options is None: fmt = Format() else: fmt = Format( width=options.width, indent=options.indent, delimiter=options.delimiter ) if verbose: fmt.print_format() return string.Template(template).substitute( NS=salt_len, S1=fmt(f1.salt), S2=fmt(f2.salt), NG=len(G), G=fmt(G), NK=len(keys), K=fmt(list(keys), quote=True), ) def read_table(filename: str, options: Values) -> list[str]: """ Reads keys and desired hash value pairs from a file. If no column for the hash value is specified, a sequence of hash values is generated, from 0 to N-1, where N is the number of rows found in the file. """ if verbose: print("Reading table from file `%s' to extract keys." % filename) try: fi = open(filename) except IOError: sys.exit("Error: Could not open `%s' for reading." % filename) keys = [] if verbose: print("Reader options:") for name in "comment", "splitby", "keycol": print(" %s: %r" % (name, getattr(options, name))) for n, line in enumerate(fi): line = line.strip() if not line or line.startswith(options.comment): continue if line.count(options.comment): # strip content after comment line = line.split(options.comment)[0].strip() row = [col.strip() for col in line.split(options.splitby)] try: key: str = row[options.keycol - 1] except IndexError: sys.exit( "%s:%d: Error: Cannot read key, not enough columns." % (filename, n + 1) ) keys.append(key) fi.close() if not keys: exit("Error: no keys found in file `%s'." % filename) return keys def read_template(filename: str) -> str: if verbose: print("Reading template from file `%s'" % filename) try: with open(filename, "r") as fi: return fi.read() except IOError: sys.exit("Error: Could not open `%s' for reading." % filename) def run_code(code: str) -> None: tmpdir = tempfile.mkdtemp() path = join(tmpdir, "t.py") with open(path, "w") as fo: fo.write(code) try: subprocess.check_call([sys.executable, path]) except subprocess.CalledProcessError as e: raise AssertionError(e) finally: shutil.rmtree(tmpdir) def main() -> None: from optparse import OptionParser usage = "usage: %prog [options] KEYS_FILE [TMPL_FILE]" description = """\ Generates code for perfect hash functions from a file with keywords and a code template. If no template file is provided, a small built-in Python template is processed and the output code is written to stdout. """ parser = OptionParser( usage=usage, description=description, prog=sys.argv[0], version="%prog: " + __version__, ) parser.add_option( "--delimiter", action="store", default=", ", help="Delimiter for list items used in output, " "the default delimiter is '%default'", metavar="STR", ) parser.add_option( "--indent", action="store", default=4, type="int", help="Make INT spaces at the beginning of a " "new line when generated list is wrapped. " "Default is %default", metavar="INT", ) parser.add_option( "--width", action="store", default=76, type="int", help="Maximal width of generated list when wrapped. Default width is %default", metavar="INT", ) parser.add_option( "--comment", action="store", default="#", help="STR is the character, or sequence of " "characters, which marks the beginning " "of a comment (which runs till " "the end of the line), in the input " "KEYS_FILE. " "Default is '%default'", metavar="STR", ) parser.add_option( "--splitby", action="store", default=",", help="STR is the character by which the columns " "in the input KEYS_FILE are split. " "Default is '%default'", metavar="STR", ) parser.add_option( "--keycol", action="store", default=1, type="int", help="Specifies the column INT in the input " "KEYS_FILE which contains the keys. " "Default is %default, i.e. the first column.", metavar="INT", ) parser.add_option( "--trials", action="store", default=5, type="int", help="Specifies the number of trials before " "NG is increased. A small INT will give " "compute faster, but the array G will be " "large. A large INT will take longer to " "compute but G will be smaller. " "Default is %default", metavar="INT", ) parser.add_option( "--hft", action="store", default=1, type="int", help="Hash function type INT. Possible values " "are 1 (StrSaltHash) and 2 (IntSaltHash). " "The default is %default", metavar="INT", ) parser.add_option( "-e", "--execute", action="store_true", help="Execute the generated code within the Python interpreter.", ) parser.add_option( "-o", "--output", action="store", help="Specify output FILE explicitly. " "`-o std' means standard output. " "`-o no' means no output. " "By default, the file name is obtained " "from the name of the template file by " "substituting `tmpl' to `code'.", metavar="FILE", ) parser.add_option("-v", "--verbose", action="store_true", help="verbosity") options, args = parser.parse_args() if options.trials <= 0: parser.error("trials before increasing N has to be larger than zero") global trials trials = options.trials global verbose verbose = options.verbose if len(args) not in (1, 2): parser.error("incorrect number of arguments") if len(args) == 2 and not args[1].count("tmpl"): parser.error("template filename does not contain 'tmpl'") if options.hft == 1: Hash: type = StrSaltHash elif options.hft == 2: Hash = IntSaltHash else: parser.error("Hash function %s not implemented." % options.hft) # --------------------- end parsing and checking -------------- keys_file = args[0] if verbose: print("keys_file = %r" % keys_file) keys = read_table(keys_file, options) if verbose: print("Number os keys: %d" % len(keys)) tmpl_file = args[1] if len(args) == 2 else None if verbose: print("tmpl_file = %r" % tmpl_file) template = read_template(tmpl_file) if tmpl_file else None if options.output: outname = options.output else: if tmpl_file: if "tmpl" not in tmpl_file: sys.exit("Hmm, template filename does not contain 'tmpl'") outname = tmpl_file.replace("tmpl", "code") else: outname = "std" if verbose: print("outname = %r\n" % outname) if outname == "std": outstream = sys.stdout elif outname == "no": outstream = None else: try: outstream = open(outname, "w") except IOError: sys.exit("Error: Could not open `%s' for writing." % outname) code = generate_code(keys, Hash, template, options) if options.execute or template == builtin_template(Hash): if verbose: print("Executing code...\n") run_code(code) if outstream: outstream.write(code) if not outname == "std": outstream.close() if __name__ == "__main__": main() xkbcommon-libxkbcommon-54ee7ac/scripts/ucd.py000077500000000000000000000142301510033435100215020ustar00rootroot00000000000000#!/usr/bin/env python3 # # Copyright © 2025 Pierre Le Marre # SPDX-License-Identifier: MIT """ Utils to parse the Unicode database files """ from collections.abc import Callable, Iterator from dataclasses import dataclass from pathlib import Path import sys from typing import ClassVar, Self def parse_code_point(raw: str) -> int | None: return None if not raw else int(raw, 16) @dataclass class CodePointRange: start: int end: int def __iter__(self) -> Iterator[int]: yield from range(self.start, self.end + 1) @classmethod def parse(cls, raw: str) -> Self: start, *end = raw.strip().split("..") return cls( start=int(start, 16), end=int(start, 16) if not end else int(end[0], 16) ) @dataclass class PropertyEntry: code_point: int property: str @classmethod def parse_file( cls, path: Path, filter: Callable[[str], bool] | None = None ) -> Iterator[Self]: with path.open("rt", encoding="utf-8") as fd: for line in fd: # Remove comment line, *_ = line.split("#") line = line.strip() # Skip empty lines if not line: continue raw_range, property, *_ = line.split(";") range = CodePointRange.parse(raw_range) property = property.strip() if filter and not filter(property): continue for code_point in range: yield cls(code_point=code_point, property=property) @dataclass class UnicodeDataEntry: code_point: int general_category: str lower_case: int | None upper_case: int | None title_case: int | None @classmethod def parse_file(cls, path: Path) -> Iterator[Self]: with path.open("rt", encoding="utf-8") as fd: for line in fd: line = line.strip() if not line or line.startswith("#"): continue ( cp, _name, general_category, _cc, _bc, _d, _decimal, _digit, _numeric, _mirrored, _, _, upper_case, lower_case, title_case, *_, ) = line.split(";") code_point = int(cp, 16) yield cls( code_point=code_point, general_category=general_category, lower_case=parse_code_point(lower_case), upper_case=parse_code_point(upper_case), title_case=parse_code_point(title_case), ) @dataclass class DB: lower_case: set[int] upper_case: set[int] title_case: set[int] lower_case_mappings: dict[int, int] upper_case_mappings: dict[int, int] title_case_mappings: dict[int, int] case_properties: ClassVar[frozenset[str]] = frozenset(("Lowercase", "Uppercase")) @classmethod def filter_case_properties(cls, property: str) -> bool: return property in cls.case_properties @classmethod def parse_ucd(cls, path: Path) -> Self: lower_case: set[int] = set() upper_case: set[int] = set() title_case: set[int] = set() lower_case_mappings: dict[int, int] = {} upper_case_mappings: dict[int, int] = {} title_case_mappings: dict[int, int] = {} for entry in UnicodeDataEntry.parse_file(path / "UnicodeData.txt"): if entry.general_category == "Lt": title_case.add(entry.code_point) if entry.lower_case is not None: lower_case_mappings[entry.code_point] = entry.lower_case if entry.upper_case is not None: upper_case_mappings[entry.code_point] = entry.upper_case if entry.title_case is not None: title_case_mappings[entry.code_point] = entry.title_case for entry in PropertyEntry.parse_file( path / "DerivedCoreProperties.txt", filter=cls.filter_case_properties ): match entry.property: case "Lowercase": lower_case.add(entry.code_point) case "Uppercase": upper_case.add(entry.code_point) case _: raise ValueError(entry) return cls( lower_case=lower_case, upper_case=upper_case, title_case=title_case, lower_case_mappings=lower_case_mappings, upper_case_mappings=upper_case_mappings, title_case_mappings=title_case_mappings, ) def isULowercase(self, cp: int) -> bool: return cp in self.lower_case def isUUppercase(self, cp: int) -> bool: return cp in self.upper_case def istitle(self, cp: int) -> bool: return cp in self.title_case def tolower(self, cp_or_char: int | str) -> int | str: cp = cp_or_char if isinstance(cp_or_char, int) else ord(cp_or_char) mapping = self.lower_case_mappings.get(cp, cp) return mapping if isinstance(cp_or_char, int) else chr(mapping) def toupper(self, cp_or_char: int | str) -> int | str: cp = cp_or_char if isinstance(cp_or_char, int) else ord(cp_or_char) mapping = self.upper_case_mappings.get(cp, cp) return mapping if isinstance(cp_or_char, int) else chr(mapping) if __name__ == "__main__": # Test import icu c = icu.Locale.createFromName("C") icu.Locale.setDefault(c) path = Path(sys.argv[1]) db = DB.parse_ucd(path) for cp in range(0, 0x10FFFF + 1): assert db.isULowercase(cp) == icu.DB.isULowercase(cp), ( cp, db.isULowercase(cp), icu.DB.isULowercase(cp), ) assert db.isUUppercase(cp) == icu.DB.isUUppercase(cp), cp assert db.istitle(cp) == icu.DB.istitle(cp), cp assert db.tolower(cp) == icu.DB.tolower(cp) assert db.toupper(cp) == icu.DB.toupper(cp) xkbcommon-libxkbcommon-54ee7ac/scripts/update-keysyms000077500000000000000000000010611510033435100232620ustar00rootroot00000000000000#!/bin/sh # Run this to regenerate xkbcommon-keysyms.h from the X11 headers # defining the keysyms, update the name <-> keysym mapping and various # derived headers. export LC_CTYPE=C.UTF-8 export LC_COLLATE=C.UTF-8 KEYSYMS_HEADER="include/xkbcommon/xkbcommon-keysyms.h" scripts/update-keysyms-definitions.py > "$KEYSYMS_HEADER" scripts/update-keysyms-names-handling.py "$KEYSYMS_HEADER" \ src/xkbcomp/keywords.gperf > \ src/ks_tables.h scripts/update-keysyms-derived-headers.py xkbcommon-libxkbcommon-54ee7ac/scripts/update-keysyms-case-mappings.py000077500000000000000000002105421510033435100264440ustar00rootroot00000000000000#!/usr/bin/env python3 # This script creates the keysym case mappings in `src/keysym-case-mappings.c`. # # Inspired from: https://github.com/apankrat/notes/blob/3c551cb028595fd34046c5761fd12d1692576003/fast-case-conversion/README.md # NOTE: the following docstring is also used to document the resulting C file. """ There are two kinds of keysyms to consider: • Legacy keysyms: their case mappings is located at `data/keysyms.yaml`. • Unicode keysyms: their case mappings come from the ICU library. These mappings would create huge lookup tables if done naively. Fortunately, we can observe that if we compute only the *difference* between a keysym and its corresponding case mapping, there are a lot of repetitions that can be efficiently compressed. The idea for the compression is, for each kind of keysyms: 1. Compute the deltas between the keysyms and their case mappings. 2. Split the delta array in chunks of a given size. 3. Rearrange the order of the chunks in order to optimize consecutive chunks overlap. 4. Create a data table with the reordered chunks and an index table that maps the original chunk index to its offset in the data table. Trivial example (chunk size: 4, from step 2): [1, 2, 3, 4, 2, 3, 4, 5, 0, 1, 2, 3] # source data -> [[1, 2, 3, 4], [2, 3, 4, 5], [0, 1, 2, 3]] # make chunks -> [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] # rearrange to have best overlaps -> {data: [0, 1, 2, 3, 4, 5], offsets: [1, 2, 0]} # overlap chunks & compute # their offsets Then we can retrieve the data from the original array at index i with the following formula: mask = (1 << chunk_size) - 1; original[i] = data[offsets[i >> chunk_size] + (i & mask)]; Since the index array is itself quite repetitive with the real data, we apply the compression a second time to the offsets table. The complete algorithm optimizes the chunk sizes for both arrays in order to get the lowest total data size. There are 6 resulting arrays, 3 for each kind of keysyms: 1. The data array. Each item is either: • 0, if the keysym is not cased. • A delta to lower case. • A delta to upper case. • For some special cases, there are both a lower *and* an upper case mapping. The delta is identical in both cases. 2. The 1st offsets array, that provides offsets into the data array. 3. The 2nd offsets array, that provides offsets into the 1st index array. Finally, given the chunks sizes `cs_data` and `cs_offsets`: 1. We compute the corresponding masks: • `mask_data = (1 << cs_data) - 1` and • `mask_offsets = (1 << cs_offsets) - 1`. 2. We can retrieve the case mapping of a keysyms `ks` with the following formula: data[ offsets1[ offsets2[ks >> (cs_data + cs_offsets)] + ((ks >> cs_data) & mask_offsets) ] + (ks & mask_data) ]; """ from __future__ import annotations import argparse import ctypes import itertools import math import os import re import sys import textwrap from abc import ABCMeta, abstractmethod from collections import defaultdict from collections.abc import Callable from ctypes.util import find_library from dataclasses import dataclass from enum import Enum, unique from functools import cache, reduce import importlib.util from pathlib import Path from typing import ( Any, ClassVar, Generator, Generic, Iterable, NewType, Protocol, Self, Sequence, TypeAlias, TypeVar, cast, ) import unicodedata import jinja2 import yaml assert sys.version_info >= (3, 12) try: import icu c = icu.Locale.createFromName("C") icu.Locale.setDefault(c) except ImportError: icu = None SCRIPT = Path(__file__) CodePoint = NewType("CodePoint", int) Keysym = NewType("Keysym", int) KeysymName = NewType("KeysymName", str) T = TypeVar("T") X = TypeVar("X", int, CodePoint, Keysym) ################################################################################ # Configuration ################################################################################ @dataclass class Config: check_error: bool verbose: bool ################################################################################ # XKBCOMMON ################################################################################ class XKBCOMMON: XKB_KEYSYM_MIN = Keysym(0) XKB_KEYSYM_MAX = Keysym(0x1FFFFFFF) XKB_KEYSYM_MIN_EXPLICIT = Keysym(0x00000000) XKB_KEYSYM_MAX_EXPLICIT = Keysym(0x1008FFB8) XKB_KEYSYM_UNICODE_OFFSET = Keysym(0x01000000) XKB_KEYSYM_UNICODE_MIN = Keysym(0x01000100) XKB_KEYSYM_UNICODE_MAX = Keysym(0x0110FFFF) XKB_KEY_NoSymbol = Keysym(0) xkb_keysym_t = ctypes.c_uint32 XKB_KEYSYM_NO_FLAGS = 0 def __init__(self) -> None: self._xkbcommon_path = os.environ.get("XKBCOMMON_LIB_PATH") if self._xkbcommon_path: self._xkbcommon_path = str(Path(self._xkbcommon_path).resolve()) self._lib = ctypes.cdll.LoadLibrary(self._xkbcommon_path) else: self._xkbcommon_path = find_library("xkbcommon") if self._xkbcommon_path: self._lib = ctypes.cdll.LoadLibrary(self._xkbcommon_path) else: raise OSError("Cannot load libxbcommon") self._lib.xkb_keysym_to_lower.argtypes = [self.xkb_keysym_t] self._lib.xkb_keysym_to_lower.restype = self.xkb_keysym_t self._lib.xkb_keysym_to_upper.argtypes = [self.xkb_keysym_t] self._lib.xkb_keysym_to_upper.restype = self.xkb_keysym_t self._lib.xkb_keysym_to_utf8.argtypes = [ self.xkb_keysym_t, ctypes.c_char_p, ctypes.c_size_t, ] self._lib.xkb_keysym_to_utf8.restype = ctypes.c_int self._lib.xkb_keysym_to_utf32.argtypes = [self.xkb_keysym_t] self._lib.xkb_keysym_to_utf32.restype = ctypes.c_uint32 self._lib.xkb_keysym_from_name.argtypes = [ctypes.c_char_p, ctypes.c_int] self._lib.xkb_keysym_from_name.restype = self.xkb_keysym_t self._lib.xkb_utf32_to_keysym.argtypes = [ctypes.c_uint32] self._lib.xkb_utf32_to_keysym.restype = self.xkb_keysym_t def keysym_from_name(self, keysym_name: KeysymName) -> Keysym: return self._lib.xkb_keysym_from_name( keysym_name.encode("utf-8"), self.XKB_KEYSYM_NO_FLAGS ) def keysym_from_cp(self, cp: CodePoint) -> Keysym: return self._lib.xkb_utf32_to_keysym(cp) def keysym_from_char(self, char: str) -> Keysym: return self._lib.xkb_utf32_to_keysym(ord(char)) def keysym_to_lower(self, keysym: Keysym) -> Keysym: return self._lib.xkb_keysym_to_lower(keysym) def keysym_to_upper(self, keysym: Keysym) -> Keysym: return self._lib.xkb_keysym_to_upper(keysym) def keysym_to_str(self, keysym: Keysym) -> str: buf_len = 7 buf = ctypes.create_string_buffer(buf_len) n = self._lib.xkb_keysym_to_utf8(keysym, buf, ctypes.c_size_t(buf_len)) if n < 0: raise ValueError(f"Unsupported keysym: 0x{keysym:0>4X})") elif n >= buf_len: raise ValueError(f"Buffer is not big enough: expected at least {n}.") else: return buf.value.decode("utf-8") def keysym_code_point(self, keysym: Keysym) -> int: return self._lib.xkb_keysym_to_utf32(keysym) def iter_case_mappings(self, unicode: bool) -> Iterable[tuple[Keysym, Entry]]: for keysym in map( Keysym, range(self.XKB_KEYSYM_MIN_EXPLICIT, self.XKB_KEYSYM_MAX_EXPLICIT + 1), ): if ( not unicode and self.XKB_KEYSYM_UNICODE_OFFSET <= keysym <= self.XKB_KEYSYM_UNICODE_MAX ) or not self.keysym_code_point(keysym): continue cp = self.keysym_code_point(keysym) yield ( keysym, Entry( lower=self.keysym_to_lower(keysym) - keysym, upper=keysym - self.keysym_to_upper(keysym), # FIXME: should use xkbcommon API, but it’s not exposed is_lower=icu.Char.isULowercase(cp), is_upper=icu.Char.isUUppercase(cp) or icu.istitle(cp), ), ) def case_mappings(self, unicode: bool) -> tuple[Entry, ...]: mappings = dict(self.iter_case_mappings(unicode)) keysym_max = max(mappings) return tuple( mappings.get(cast(Keysym, ks), Entry.zeros()) for ks in range(0, keysym_max + 1) ) xkbcommon = XKBCOMMON() def load_keysyms(path: Path, unicode: bool) -> tuple[Entry, ...]: with path.open("rt", encoding="utf-8") as fd: keysyms = { ks: entry for ks, data in yaml.safe_load(fd).items() if unicode or ( ks < XKBCOMMON.XKB_KEYSYM_UNICODE_MIN or ks > XKBCOMMON.XKB_KEYSYM_UNICODE_MAX ) if data.get("code point") if ( entry := Entry( data.get("lower", ks) - ks, ks - data.get("upper", ks), is_lower=icu.Char.isULowercase(data.get("code point")), is_upper=icu.Char.isUUppercase(data.get("code point")) or icu.Char.istitle(data.get("code point")), ) ) } # Check either non-cased, upper or lower errors = [] for ks, e in keysyms.items(): if e.lower and e.upper and e.lower != e.upper: errors.append((ks, e)) if errors: raise ValueError(errors) keysym_max = max(keysyms) return tuple(keysyms.get(ks, Entry.zeros()) for ks in range(0, keysym_max + 1)) ################################################################################ # Case mapping ################################################################################ @dataclass(frozen=True, order=True) class Entry: """ Case mapping deltas for a character or a keysym. """ lower: int upper: int is_lower: bool is_upper: bool # [NOTE] Exceptions must be documented in `xkbcommon.h`. to_upper_exceptions: ClassVar[dict[str, str]] = {"ß": "ẞ"} "Upper mappings exceptions" @classmethod def zeros(cls) -> Self: return cls(lower=0, upper=0, is_lower=False, is_upper=False) def __bool__(self) -> bool: return any(self) or self.is_lower or self.is_upper def __str__(self) -> str: return str(tuple(self)) def __iter__(self) -> Generator[int, None, None]: yield self.lower yield self.upper @classmethod def from_code_point(cls, cp: CodePoint) -> Self: return cls( lower=cls.lower_delta(cp), upper=cls.upper_delta(cp), is_lower=icu.Char.isULowercase(cp), is_upper=icu.Char.isUUppercase(cp) or icu.Char.istitle(cp), ) @classmethod def lower_delta(cls, cp: CodePoint) -> int: return cls.to_lower_cp(cp) - cp @classmethod def upper_delta(cls, cp: CodePoint) -> int: return cp - cls.to_upper_cp(cp) @classmethod def to_upper_cp(cls, cp: CodePoint) -> CodePoint: if upper := cls.to_upper_exceptions.get(chr(cp)): return ord(upper) return icu.Char.toupper(cp) @staticmethod def to_lower_cp(cp: CodePoint) -> CodePoint: return icu.Char.tolower(cp) @classmethod def to_upper_char(cls, char: str) -> str: if upper := cls.to_upper_exceptions.get(char): return upper return icu.Char.toupper(char) @staticmethod def to_lower_char(char: str) -> str: return icu.Char.tolower(char) def to_lower(self, x: X) -> X: return x.__class__(x + self.lower) def to_upper(self, x: X) -> X: return x.__class__(x - self.upper) @dataclass class Deltas(Generic[T]): """ Sequences of case mappings deltas """ keysyms: tuple[T, ...] keysym_max: Keysym "Maximum keysym with a case mapping" unicode: tuple[T, ...] unicode_max: CodePoint "Maximum Unicode code point with a case mapping" class Entries(Deltas[Entry]): @classmethod def compute( cls, config: Config, path: Path | None = None, ) -> Self: # Keysyms if path: keysyms_deltas = load_keysyms(path, unicode=False) else: keysyms_deltas = xkbcommon.case_mappings(True) max_keysym = max(Keysym(ks) for ks, e in enumerate(keysyms_deltas) if e) assert max_keysym keysyms_deltas = keysyms_deltas[: max_keysym + 1] # Unicode unicode_deltas = tuple( Entry.from_code_point(CodePoint(cp)) for cp in range(0, sys.maxunicode + 1) ) max_unicode = max((CodePoint(cp) for cp, d in enumerate(unicode_deltas) if d)) assert max_unicode unicode_deltas = unicode_deltas[: max_unicode + 1] errors = [] for n, e1 in enumerate(unicode_deltas): cp = CodePoint(n) # Check with legacy keysyms keysym = xkbcommon.keysym_from_cp(cp) if keysym <= max_keysym: e2 = keysyms_deltas[keysym] if e1 or e2: cls.check( config, "lower", cp, e1.to_lower(cp), keysym, e2.to_lower(keysym), ) cls.check( config, "upper", cp, e1.to_upper(cp), keysym, e2.to_upper(keysym), ) # Check character has either # • No case mapping # • Lower or an upper mapping # • Both, with the same delta if e1.lower and e1.upper and e1.lower != e1.upper: errors.append((cp, e1)) if errors: raise ValueError(errors) return cls( keysyms=keysyms_deltas, keysym_max=max_keysym, unicode=unicode_deltas, unicode_max=max_unicode, ) @classmethod def check( cls, config: Config, casing: str, cp: CodePoint, cpʹ: CodePoint, keysym: Keysym, keysymʹ: Keysym, ) -> None: char = chr(cp) expected = chr(cpʹ) got = xkbcommon.keysym_to_str(keysymʹ) data = ( hex(keysym), hex(cp), char, hex(keysymʹ), got, expected, ) if config.check_error: assert got == expected, data elif got != expected: print( f"Error: legacy keysym 0x{keysym:4>x} has incorrect {casing} mapping:", data, ) @property def lower(self) -> Deltas[int]: return Deltas( keysyms=tuple(e.lower for e in self.keysyms), keysym_max=self.keysym_max, unicode=tuple(e.lower for e in self.unicode), unicode_max=self.unicode_max, ) @property def upper(self) -> Deltas[int]: return Deltas( keysyms=tuple(e.upper for e in self.keysyms), keysym_max=self.keysym_max, unicode=tuple(e.upper for e in self.unicode), unicode_max=self.unicode_max, ) @dataclass(frozen=True) class DeltasPair(Generic[T]): d1: tuple[T, ...] d2: tuple[T, ...] overlap: int def __contains__(self, x: tuple[T, ...]) -> bool: return (x == self.d1) or (x == self.d2) @classmethod def compute_pairs_overlaps( cls, deltas: Iterable[tuple[T, ...]] ) -> Generator[DeltasPair[T], None, None]: for d1, d2 in itertools.combinations(deltas, 2): if overlap := Overlap.compute_simple(d1, d2): yield DeltasPair(d1, d2, overlap) if overlap := Overlap.compute_simple(d2, d1): yield DeltasPair(d2, d1, overlap) def remove_from_pairs( self, pairs: list[DeltasPair[T]] ) -> Generator[DeltasPair[T], None, None]: for p in pairs: if p.d1 not in self and p.d2 not in self: yield p @classmethod def remove_chunk_from_pairs( cls, pairs: Iterable[DeltasPair[T]], chunk: tuple[T, ...] ) -> Generator[DeltasPair[T], None, None]: for p in pairs: if chunk not in p: yield p @classmethod def compute_best_pair(cls, pairs: Iterable[DeltasPair[T]]) -> DeltasPair[T]: return max(pairs, key=lambda p: p.overlap) ################################################################################ # Overlap ################################################################################ @dataclass class Overlap: "Overlap of two sequences" offset: int overlap: int @staticmethod @cache def compute_simple(s1: Sequence[T], s2: Sequence[T]) -> int: return max((n for n in range(0, len(s1) + 1) if s1[-n:] == s2[:n]), default=0) @classmethod @cache def compute(cls, s1: Sequence[T], s2: Sequence[T]) -> Self: l1 = len(s1) l2 = len(s2) return max( ( cls(offset=start, overlap=overlap) for start in range(0, l1) if (end := min(start + l2, l1)) and (overlap := end - start) and s1[start:end] == s2[:overlap] ), key=lambda x: x.overlap, default=cls(offset=l1, overlap=0), ) @classmethod def test(cls) -> None: c1 = (1, 2, 3, 4) c2 = (2, 3) c3 = (3, 2, 1) c4 = (3, 4, 5) c5 = (1, 2, 4) overlap = cls.compute(c1, c2) assert overlap == cls(1, 2) overlap = cls.compute(c3, c1) assert overlap == cls(2, 1) overlap = cls.compute(c1, c4) assert overlap == cls(2, 2) overlap = cls.compute(c1, c5) assert overlap == cls(4, 0), overlap ################################################################################ # Groups ################################################################################ Groups: TypeAlias = dict[tuple[T, ...], list[int]] def generate_groups(block_size: int, data: Iterable[T]) -> Groups[T]: groups: defaultdict[tuple[T, ...], list[int]] = defaultdict(list) for n, d in enumerate(itertools.batched(data, block_size)): groups[d].append(n) return groups ################################################################################ # Overlapped Sequences ################################################################################ @dataclass class OverlappedSequences(Generic[T]): data: tuple[T, ...] offsets: dict[tuple[T, ...], int] def __bool__(self) -> bool: return bool(self.data) def __hash__(self) -> int: return hash((self.data, tuple(self.offsets))) def __add__(self, x: Any) -> Self: if isinstance(x, self.__class__): return self.extend(x) elif isinstance(x, tuple): return self.add(x) else: return NotImplemented def __iadd__(self, x: Any) -> Self: if isinstance(x, self.__class__): overlap = Overlap.compute(self.data, x.data) self.data = ( self.data if overlap.offset <= len(self.data) - len(x.data) else self.data + x.data[overlap.overlap :] ) for c, o in x.offsets.items(): self.offsets[c] = overlap.offset + o return self elif isinstance(x, tuple): overlap = Overlap.compute(self.data, x) self.data = ( self.data if overlap.offset <= len(self.data) - len(x) else self.data + x[overlap.overlap :] ) self.offsets[x] = overlap.offset return self else: return NotImplemented @classmethod def from_singleton(cls, chunk: tuple[T, ...]) -> Self: return cls(data=chunk, offsets={chunk: 0}) @classmethod def from_pair(cls, pair: DeltasPair[T]) -> Self: return cls( data=pair.d1 + pair.d2[pair.overlap :], offsets={ pair.d1: 0, pair.d2: len(pair.d1) - pair.overlap, }, ) @classmethod def from_iterable(cls, ts: Iterable[tuple[T, ...]]) -> Self: return reduce(lambda s, t: s.add(t), ts, cls((), {})) @classmethod def from_ordered_iterable(cls, ts: Iterable[tuple[T, ...]]) -> Self: return reduce(lambda s, t: s.append(t), ts, cls((), {})) def extend(self, s: Self) -> Self: overlap: Overlap s1: Self s2: Self overlap, s1, s2 = max( ( (Overlap.compute(self.data, s.data), self, s), (Overlap.compute(s.data, self.data), s, self), ), key=lambda x: x[0].overlap, ) data = ( s1.data if overlap.offset <= len(s1.data) - len(s2.data) else s1.data + s2.data[overlap.overlap :] ) offsets = dict(s1.offsets) for c, o in s2.offsets.items(): offsets[c] = overlap.offset + o return self.__class__(data=data, offsets=offsets) def add(self, chunk: tuple[T, ...]) -> Self: return self.extend(self.from_singleton(chunk)) def append(self, chunk: tuple[T, ...]) -> Self: overlap = Overlap.compute(self.data, chunk) self.data = ( self.data if overlap.offset <= len(self.data) - len(chunk) else self.data + chunk[overlap.overlap :] ) self.offsets[chunk] = overlap.offset return self def insert(self, offset: int, overlap: int, chunk: tuple[T, ...]) -> None: chunk_length = len(chunk) if offset < 0: self.data = chunk[:-overlap] + self.data assert chunk == self.data[:chunk_length] for c in self.offsets: self.offsets[c] += -offset self.offsets[chunk] = 0 elif offset <= len(self.data) - len(chunk): assert self.data[offset : offset + chunk_length] == chunk self.offsets[chunk] = offset else: self.data += chunk[overlap:] assert self.data[offset:] == chunk self.offsets[chunk] = offset def merge(self, offset: int, overlap: int, s: OverlappedSequences[T]) -> None: s_length = len(s.data) if offset < 0: self.data = s.data[:-overlap] + self.data assert s.data == self.data[:s_length] for c in self.offsets: self.offsets[c] += -offset self.offsets.update(s.offsets) elif offset <= len(self.data) - len(s.data): assert self.data[offset : offset + s_length] == s.data for c, offset2 in s.offsets.items(): self.offsets[c] = offset2 + offset else: self.data += s.data[overlap:] assert self.data[offset:] == s.data for c, offset2 in s.offsets.items(): self.offsets[c] = offset2 + offset def flatten_iter(self) -> Generator[tuple[T, ...], None, None]: for t, _ in sorted(self.offsets.items(), key=lambda x: x[1]): yield t def flatten(self) -> list[tuple[T, ...]]: return list(self.flatten_iter()) def flatten_groups_iter(self) -> Generator[list[tuple[T, ...]], None, None]: i = self.flatten_iter() g = [next(i)] for t in i: if Overlap.compute(g[-1], t).overlap: g.append(t) else: yield g g = [t] yield g def split(self) -> list[OverlappedSequences[T]]: offsets = sorted(self.offsets.items(), key=lambda x: x[1]) start = 0 pending: dict[tuple[T, ...], int] = {} end = 0 new: list[OverlappedSequences[T]] = [] for d, i in offsets: # print(start, end, d, i) if end and i >= end: assert start < end new.append( OverlappedSequences(data=self.data[start:end], offsets=pending) ) pending = {d: 0} start = i else: pending[d] = i - start end = max(end, i + len(d)) assert start < end new.append(OverlappedSequences(data=self.data[start:end], offsets=pending)) return new def total_overlap(self) -> int: return sum(len(d) for d in self.offsets) - len(self.data) class _OverlappedSequences(OverlappedSequences[int]): @classmethod def test(cls) -> None: c1: tuple[int, ...] = (1, 2, 3, 4) c2: tuple[int, ...] = (2, 3) c3: tuple[int, ...] = (3, 4, 5) c4: tuple[int, ...] = (1, 3) assert cls(c1, {}).add(c2) == cls(c1, {c2: 1}) assert cls(c1, {}).add(c3) == cls(c1 + c3[2:], {c3: 2}) assert cls(c1, {}).add(c4) == cls(c1 + c4, {c4: len(c1)}) assert cls(c1, {}) + cls(c2, {c2: 0}) == cls(c1, {c2: 1}) assert cls(c1, {}) + cls(c3, {c3: 0}) == cls(c1 + c3[2:], {c3: 2}) assert cls(c1, {}) + cls(c4, {c4: 0}) == cls(c1 + c4, {c4: len(c1)}) assert cls(c2, {c2: 0}) + cls(c1, {}) == cls(c1, {c2: 1}) assert cls(c3, {c3: 0}) + cls(c1, {}) == cls(c1 + c3[2:], {c3: 2}) assert cls(c4, {c4: 0}) + cls(c1, {}) == cls(c4 + c1, {c4: 0}) c5 = (1, 2, 3, 4, 5, 6) c6 = (1,) c7 = (6,) s = cls(c5, {c6: 0, c2: 1, c3: 2, c7: 5}) assert s.total_overlap() == 1, s.total_overlap() assert s.split() == [ cls(c6, {c6: 0}), cls(c5[1:-1], {c2: 0, c3: 1}), cls(c7, {c7: 0}), ], s.split() cs = s.flatten() assert cs == [c6, c2, c3, c7], cs assert cls.from_iterable(cs) == s ################################################################################ # Chunks compressor ################################################################################ class Move(Protocol, Generic[T]): def __call__( self, pairs: list[DeltasPair[T]], remaining_chunks: set[tuple[T, ...]], overlapped_sequences: list[OverlappedSequences[T]], ) -> None: ... @dataclass class ChunksCompressor: verbose: bool @classmethod def _insert( cls, chunk: tuple[T, ...], index: int, offset: int, overlap: int ) -> Move[T]: def action( pairs: list[DeltasPair[T]], remaining_chunks: set[tuple[T, ...]], overlapped_sequences: list[OverlappedSequences[T]], ) -> None: remaining_chunks.remove(chunk) pairs[:] = DeltasPair.remove_chunk_from_pairs(pairs, chunk) s = overlapped_sequences[index] s.insert(offset, overlap, chunk) return action @classmethod def _merge(cls, index1: int, index2: int, offset: int, overlap: int) -> Move[T]: def action( pairs: list[DeltasPair[T]], remaining_chunks: set[tuple[T, ...]], overlapped_sequences: list[OverlappedSequences[T]], ) -> None: s1 = overlapped_sequences[index1] s2 = overlapped_sequences.pop(index2) s1.merge(offset, overlap, s2) return action @classmethod def _add_new_singleton(cls, chunk: tuple[T, ...]) -> Move[T]: def action( pairs: list[DeltasPair[T]], remaining_chunks: set[tuple[T, ...]], overlapped_sequences: list[OverlappedSequences[T]], ) -> None: remaining_chunks.remove(chunk) pairs[:] = DeltasPair.remove_chunk_from_pairs(pairs, chunk) overlapped_sequences.append(OverlappedSequences.from_singleton(chunk)) return action @classmethod def _add_new_sequence(cls, pair: DeltasPair[T]) -> Move[T]: def action( pairs: list[DeltasPair[T]], remaining_chunks: set[tuple[T, ...]], overlapped_sequences: list[OverlappedSequences[T]], ) -> None: remaining_chunks.remove(pair.d1) remaining_chunks.remove(pair.d2) pairs[:] = pair.remove_from_pairs(pairs) assert pair not in pairs overlapped_sequences.append(OverlappedSequences.from_pair(pair)) return action def compress(self, chunks: Iterable[tuple[T, ...]]) -> OverlappedSequences[T]: # Prepare data and offsets pairs = list(DeltasPair.compute_pairs_overlaps(chunks)) remaining_chunks = set(chunks) if self.verbose: print( "Count of chunks:", len(remaining_chunks), ) overlapped_sequences: list[OverlappedSequences[T]] = [] best_move: Move[T] | None = None total_chunks = len(remaining_chunks) while remaining_chunks or (len(overlapped_sequences) > 1 and best_move): if self.verbose: print( f"# Remaining: {len(remaining_chunks)}/{total_chunks}", "Current pairs:", len(overlapped_sequences), ) best_move = None best_overlap: int = 0 # Try inserting for n, s in enumerate(overlapped_sequences): for d in remaining_chunks: # Try prepend overlap = Overlap.compute_simple(d, s.data) if overlap > best_overlap: best_overlap = overlap best_move = self._insert(d, n, overlap - len(d), overlap) if self.verbose: print( "Insert chunk (prepend)", best_overlap, len(overlapped_sequences), ) # Try insert overlap_max = Overlap.compute(s.data, d) if overlap_max.overlap > best_overlap: best_overlap = overlap_max.overlap best_move = self._insert( d, n, overlap_max.offset, overlap_max.overlap ) if self.verbose: print( "Insert chunk (append)", overlap_max, len(overlapped_sequences), ) # Try merging for n1, n2 in itertools.permutations(range(len(overlapped_sequences)), 2): s1 = overlapped_sequences[n1] s2 = overlapped_sequences[n2] # Try insert overlap_max = Overlap.compute(s1.data, s2.data) if overlap_max.overlap > best_overlap: best_overlap = overlap_max.overlap best_move = self._merge( n1, n2, overlap_max.offset, overlap_max.overlap ) if self.verbose: print( "Merge 2 sequences", overlap_max, len(overlapped_sequences), ) # Take next best pair if ( pairs and (best_pair := DeltasPair.compute_best_pair(pairs)) and best_pair.overlap > best_overlap ): best_overlap = best_pair.overlap best_move = self._add_new_sequence(best_pair) if self.verbose: print("Add new sequence", best_overlap, len(overlapped_sequences)) if not best_move: if self.verbose: print("No best move", len(overlapped_sequences)) if remaining_chunks: best_move = self._add_new_singleton(min(remaining_chunks)) if best_move: best_move( pairs=pairs, remaining_chunks=remaining_chunks, overlapped_sequences=overlapped_sequences, ) assert len(overlapped_sequences) >= 1 assert not remaining_chunks if (l := len(overlapped_sequences)) > 1: if self.verbose: print("Force merging remaining sequences", l) for n1, n2 in itertools.permutations(range(len(overlapped_sequences)), 2): s1 = overlapped_sequences[n1] s2 = overlapped_sequences[n2] overlap_max = Overlap.compute(s1.data, s2.data) assert overlap_max.overlap == 0, overlap_max for _ in range(1, len(overlapped_sequences)): move: Move[T] = self._merge(0, 1, len(overlapped_sequences[0].data), 0) move( pairs=pairs, remaining_chunks=remaining_chunks, overlapped_sequences=overlapped_sequences, ) assert len(overlapped_sequences) == 1, overlapped_sequences s = overlapped_sequences[0] return s @classmethod def test_moves(cls) -> None: c1 = (1, 2, 3, 4, 5) c2 = (6, 1) c3 = (7, 6, 1) c4 = (3, 4) c5 = (5, 6, 7) c6 = (6, 1, 2) c7 = (8, 7, 6) chunks0 = {c1, c2, c3, c4, c5, c6, c7} chunks = set(chunks0) sequences: list[OverlappedSequences[int]] = [] offsets: dict[tuple[int, ...], int] overlap_max = Overlap.compute((1, 2, 3), c1) assert overlap_max == Overlap(offset=0, overlap=3) pairs: list[DeltasPair[int]] = [] move = ChunksCompressor._add_new_singleton(c1) move(pairs, chunks, sequences) offsets = {c1: 0} data: tuple[int, ...] = c1 assert len(sequences) == 1 s = sequences[0] assert s.data == data assert s.offsets == offsets overlap = Overlap.compute_simple(c2, s.data) assert overlap == 1 overlap_max = Overlap.compute(c2, s.data) assert overlap_max.overlap == overlap move = ChunksCompressor._insert( chunk=c2, index=0, offset=-overlap, overlap=overlap ) move(pairs, chunks, sequences) offsets[c1] = 1 offsets[c2] = 0 data = c2[:-overlap] + data assert len(sequences) == 1 assert s.data == data assert s.offsets == offsets overlap = Overlap.compute_simple(c3, s.data) assert overlap == 2 overlap_max = Overlap.compute(c3, s.data) assert overlap_max.overlap == overlap move = ChunksCompressor._insert( chunk=c3, index=0, offset=overlap - len(c3), overlap=overlap ) move(pairs, chunks, sequences) offsets[c1] += 1 offsets[c2] += 1 offsets[c3] = 0 data = c3[:-overlap] + data assert len(sequences) == 1 assert s.data == data assert s.offsets == offsets overlap_max = Overlap.compute(s.data, c4) assert overlap_max.overlap == 2, (s.data, c4, overlap_max) assert overlap_max.offset == 4, (s.data, c4, overlap_max) move = ChunksCompressor._insert( chunk=c4, index=0, offset=overlap_max.offset, overlap=overlap_max.overlap ) move(pairs, chunks, sequences) offsets[c4] = overlap_max.offset assert len(sequences) == 1 assert s.data == data assert s.offsets == offsets overlap_max = Overlap.compute(s.data, c5) assert overlap_max.overlap == 1, (s.data, c5, overlap_max) assert overlap_max.offset == 6, (s.data, c5, overlap_max) move = ChunksCompressor._insert( chunk=c5, index=0, offset=overlap_max.offset, overlap=overlap_max.overlap ) move(pairs, chunks, sequences) offsets[c5] = overlap_max.offset data += c5[overlap_max.overlap :] assert len(sequences) == 1 assert s.data == data, (s.data, data) assert s.offsets == offsets overlap_max = Overlap.compute(s.data, c6) assert overlap_max.overlap == 3, (s.data, c6, overlap_max) assert overlap_max.offset == 1, (s.data, c6, overlap_max) move = ChunksCompressor._insert( chunk=c6, index=0, offset=overlap_max.offset, overlap=overlap_max.overlap ) move(pairs, chunks, sequences) offsets[c6] = overlap_max.offset assert len(sequences) == 1 assert s.data == data, (s.data, data) assert s.offsets == offsets overlap = Overlap.compute_simple(c7, s.data) assert overlap == 2 overlap_max = Overlap.compute(c7, s.data) assert overlap_max.overlap == overlap move = ChunksCompressor._insert( chunk=c7, index=0, offset=overlap - len(c7), overlap=overlap ) move(pairs, chunks, sequences) for c in offsets: offsets[c] += len(c7) - overlap offsets[c7] = 0 data = c7[:-overlap] + data assert len(sequences) == 1 assert s.data == data assert s.offsets == offsets for c in chunks0: offset = s.offsets[c] assert c == s.data[offset : offset + len(c)], ( c, s.data[offset : offset + len(c)], ) @classmethod def test_compression(cls) -> None: c1 = (1, 2, 3) c2 = (-1, 0, 1) c3 = (-2, -1, 0) c4 = (3, 4, 5) c5 = (0, 1, 2) c6 = (2, 3, 5) chunks = {c1, c2, c3, c4, c5, c6} compressor = cls(verbose=True) r = compressor.compress(chunks) assert set(r.offsets) == {c1, c2, c3, c4, c5, c6} for c in chunks: offset = r.offsets[c] assert c == r.data[offset : offset + len(c)], ( c, r.data[offset : offset + len(c)], ) ################################################################################ # Stats ################################################################################ @dataclass class Stats: data_length: int data_int_size: int data_overlap: int offsets1_length: int offsets1_int_size: int offsets2_length: int offsets2_int_size: int @property def data_size(self) -> int: return self.data_length * self.data_int_size @property def offsets1_size(self) -> int: return self.offsets1_length * self.offsets1_int_size @property def offsets2_size(self) -> int: return self.offsets2_length * self.offsets2_int_size @property def total(self) -> int: return self.data_size + self.offsets1_size + self.offsets2_size def _int_size(ts: Sequence[Iterable[int] | int], offset: int = 0) -> int: assert ts if isinstance(ts[0], int): ts = cast(Sequence[int], ts) min_delta: int = min(ts) max_delta: int = max(ts) else: ts = cast(Sequence[Iterable[int]], ts) min_delta = min(min(t) for t in ts) max_delta = max(max(t) for t in ts) if offset: min_delta <<= offset max_delta <<= offset for n in range(3, 7): size: int = 2**n min_int = -(1 << (size - 1)) max_int = -min_int - 1 if min_int <= min_delta and max_delta <= max_int: return size else: raise ValueError((min_delta, max_delta)) def uint_size(ts: Sequence[int]) -> int: min_delta = min(ts) if min_delta < 0: raise ValueError(min_delta) max_delta = max(ts) for n in range(3, 7): size: int = 2**n max_int = (1 << size) - 1 if max_delta <= max_int: return size else: raise ValueError((min_delta, max_delta)) ################################################################################ # Compressed array ################################################################################ I = TypeVar("I", Entry, int) @dataclass class CompressedArray(Generic[I]): data: tuple[I, ...] offsets: tuple[int, ...] chunk_offsets: dict[tuple[I, ...], int] @classmethod def from_overlapped_sequences( cls, s: OverlappedSequences[I], groups: Groups[I] ) -> Self: offsets = tuple( s.offsets[d] for _, d in sorted( ((g, d0) for d0, gs in groups.items() for g in gs), key=lambda x: x[0], ) ) return cls(data=s.data, offsets=offsets, chunk_offsets=s.offsets) def total_overlap(self) -> int: return sum(len(d) for d in self.chunk_offsets) - len(self.data) def stats(self, int_size: Callable[[Sequence[Iterable[int] | int]], int]) -> Stats: return Stats( data_length=len(self.data), data_int_size=int_size(self.data), data_overlap=self.total_overlap(), offsets1_length=len(self.offsets), offsets1_int_size=_int_size(self.offsets), offsets2_length=0, offsets2_int_size=0, ) @staticmethod def test() -> None: c1 = (1, 2, 3, 4) c2 = (2, 3) c3 = (3, 4, 5) c4 = (1, 3) s = OverlappedSequences.from_singleton(c1) s += c2 s += c3 s += c4 groups: Groups[int] = {c1: [0, 3], c2: [4], c3: [1, 2]} a = CompressedArray.from_overlapped_sequences(s, groups) assert a == CompressedArray( data=s.data, offsets=(0, 2, 2, 0, 1), chunk_offsets=s.offsets ), a @dataclass class ArrayCompressor: compressor: ChunksCompressor verbose: bool def run(self, groups: Groups[I]) -> CompressedArray[I]: s = self.compressor.compress(groups) return CompressedArray.from_overlapped_sequences(s, groups) @classmethod def compress( cls, compressor: ChunksCompressor, block_size: int, data: Iterable[I], default: I, verbose: bool = False, ) -> CompressedArray[I]: groups = generate_groups(block_size=block_size, data=data) array_compressor = cls(compressor=compressor, verbose=verbose) return array_compressor.run(groups) @classmethod def test_compression(cls) -> None: c1 = (1, 2, 3) c2 = (-1, 0, 1) c3 = (-2, -1, 0) c4 = (3, 4, 5) c5 = (0, 1, 2) c6 = (2, 3, 5) groups: Groups[int] = { c1: [0], c2: [1], c3: [2], c4: [3], c5: [4], c6: [5], } compressor = cls( compressor=ChunksCompressor(verbose=True), verbose=True, ) r = compressor.run(groups) assert set(r.chunk_offsets) == {c1, c2, c3, c4, c5, c6} for c, gs in groups.items(): for g in gs: offset = r.offsets[g] assert c == r.data[offset : offset + len(c)], ( c, r.data[offset : offset + len(c)], ) ################################################################################ # Solutions ################################################################################ @dataclass class SimpleSolution(Generic[T]): data_block_size_log2: int data_int_size: int data_overlap: int data: tuple[T, ...] offsets1_block_size_log2: int offsets1_int_size: int offsets1: tuple[int, ...] offsets2_int_size: int offsets2: tuple[int, ...] max: int total: int @classmethod def zeros(cls) -> Self: return cls( data_block_size_log2=0, data_int_size=0, data_overlap=0, data=(), offsets1_block_size_log2=0, offsets1_int_size=0, offsets1=(), offsets2_int_size=0, offsets2=(), max=0, total=0, ) @property def case(self) -> str: return "both" @property def data_size(self) -> int: return len(self.data) * self.data_int_size def _convert(self, op: Callable[[X, T], X], x: X) -> X: mask1 = (1 << self.data_block_size_log2) - 1 mask2 = (1 << self.offsets1_block_size_log2) - 1 cpʹ = x >> self.data_block_size_log2 offset = self.offsets2[cpʹ >> self.offsets1_block_size_log2] + (cpʹ & mask2) return op(x, self.data[self.offsets1[offset] + (x & mask1)]) class SimpleSolutionCombinedMappings(SimpleSolution[Entry], metaclass=ABCMeta): @property @abstractmethod def type(self) -> str: ... def to_lower(self, x: X) -> X: return self._convert(lambda a, e: e.to_lower(a), x) def to_upper(self, x: X) -> X: return self._convert(lambda a, e: e.to_upper(a), x) class SimpleSolutionKeysymsCombinedMappings(SimpleSolutionCombinedMappings): @property def type(self) -> str: return "legacy_keysyms" def test(self, config: Config) -> bool: # Check legacy keysyms r = True for ks in map(Keysym, range(0, self.max + 1)): if not (char := xkbcommon.keysym_to_str(ks)): continue cp = ord(char) # Lower if ks <= self.max: expected = Entry.to_lower_char(char) ksʹ = xkbcommon.keysym_from_char(expected) ksʹʹ = self.to_lower(ks) got = xkbcommon.keysym_to_str(ksʹʹ) ok = got == expected data = ( hex(ks), hex(cp), char, expected, char.lower(), hex(ksʹ), hex(ksʹʹ), got, ) if config.check_error: assert ok, data elif not ok: print("Error:", data) r = False # Upper if ks <= self.max: expected = Entry.to_upper_char(char) ksʹ = xkbcommon.keysym_from_char(expected) ksʹʹ = self.to_upper(ks) got = xkbcommon.keysym_to_str(ksʹʹ) ok = got == expected data = ( hex(ks), hex(cp), char, expected, char.upper(), hex(ksʹ), hex(ksʹʹ), got, ) if config.check_error: assert ok, data elif not ok: print("Error:", data) r = False return r class SimpleSolutionUnicodeCombinedMappings(SimpleSolutionCombinedMappings): @property def type(self) -> str: return "unicode" def test(self, config: Config) -> bool: # Check Unicode keysyms unicode_min = ( xkbcommon.XKB_KEYSYM_UNICODE_MIN - xkbcommon.XKB_KEYSYM_UNICODE_OFFSET ) r = True for cp in map(CodePoint, range(unicode_min, self.max + 1)): char = chr(cp) # Lower if cp <= self.max: expected = Entry.to_lower_char(char) got = chr(self.to_lower(cp)) ok = got == expected dataʹ = (hex(cp), char, expected, char.lower(), got) if config.check_error: assert ok, dataʹ elif not ok: print("Error:", dataʹ) r = False # Upper if cp <= self.max: expected = Entry.to_upper_char(char) got = chr(self.to_upper(cp)) ok = got == expected dataʹ = (hex(cp), char, expected, char.upper(), got) if config.check_error: assert ok, dataʹ elif not ok: print("Error:", dataʹ) r = False return r S = TypeVar("S", bound=SimpleSolutionCombinedMappings) @dataclass class SeparateLegacyKeysymsAndUnicodeCombinedCaseMappings: legacy_keysyms: SimpleSolutionKeysymsCombinedMappings unicode: SimpleSolutionUnicodeCombinedMappings def __iter__(self) -> Generator[SimpleSolutionCombinedMappings, None, None]: yield self.legacy_keysyms yield self.unicode @property def total(self) -> int: return sum(s.total for s in self) def test(self, config: Config) -> bool: r = True if self.legacy_keysyms.data: r &= self.legacy_keysyms.test(config) if self.unicode.data: r &= self.unicode.test(config) return r @classmethod def optimize_groups( cls, data: tuple[Entry, ...], data_max: int, total0: int, config: Config, cls_: type[S], ) -> S: chunks_compressor = ChunksCompressor(verbose=config.verbose) total = total0 max_int_size = sys.maxsize solution: S | None = None for k1 in range(1, 9): block_size1 = 2**k1 if config.verbose: print("".center(80, "-")) print(f"{block_size1=} Step 1: Generating 1st compression level…") ca1 = ArrayCompressor.compress( compressor=chunks_compressor, block_size=block_size1, data=data, default=Entry.zeros(), verbose=config.verbose, ) stats1 = ca1.stats(int_size=lambda x: _int_size(x, offset=2)) if config.verbose: print("Step 1 done.") print( f"{block_size1=} Step 1:", f"data_overlap={stats1.data_overlap} data_length={stats1.data_length} data_size={stats1.data_size}", f"total={stats1.total}", ) current_total = stats1.total if config.verbose: print(f"{current_total=}") if (data_size := stats1.data_size) >= total: if config.verbose: print(f"We cannot beat the current solution {data_size=} {total=}") continue current_int_size = max(stats1.data_int_size, stats1.offsets1_int_size) if current_total <= total and ( current_total != total or current_int_size < max_int_size ): total = current_total max_int_size = current_int_size if config.verbose: print(f"✨ New best solution: {block_size1=} {total=}") # TODO: 1st level solution for k2 in range(7, 1, -1): block_size2 = 2**k2 if config.verbose: print( f"{block_size1=} {block_size2=} Step 2: 2nd level compression… ", flush=True, ) ca2 = ArrayCompressor.compress( compressor=chunks_compressor, block_size=block_size2, data=ca1.offsets, default=0, verbose=config.verbose, ) stats2 = ca2.stats(int_size=_int_size) stats = Stats( data_length=stats1.data_length, data_int_size=stats1.data_int_size, data_overlap=stats1.data_overlap, offsets1_length=stats2.data_length, offsets1_int_size=stats2.data_int_size, offsets2_length=stats2.offsets1_length, offsets2_int_size=stats2.offsets1_int_size, ) current_total = stats.total if config.verbose: print( f"{block_size1=} {block_size2=} Step 2:", f"data_overlap={stats.data_overlap} data_length={stats.data_length} data_size={stats.data_size}", f"total={stats.total}", ) print("Step 2 done.", flush=True) current_int_size = max( stats.data_int_size, stats.offsets1_int_size, stats.offsets2_int_size, ) if current_total < total or ( current_total == total and current_int_size < max_int_size ): total = current_total max_int_size = current_int_size if config.verbose: print( f"✨ New best solution: {block_size1=} {block_size2=} {total=}" ) solution = cls_( data_block_size_log2=k1, data_int_size=stats.data_int_size, data=ca1.data, data_overlap=stats.data_overlap, offsets1_block_size_log2=k2, offsets1=ca2.data, offsets1_int_size=stats.offsets1_int_size, offsets2=ca2.offsets, offsets2_int_size=stats.offsets2_int_size, max=data_max, total=stats.total, ) assert solution if config.verbose: print(" Finished ".center(80, "*")) print( f"Best solution ({solution.case}):", f"data_block_size={2**solution.data_block_size_log2}", f"data_overlap={solution.data_overlap}", f"offsets1_block_size={2**solution.offsets1_block_size_log2}", f"total={solution.total}", ) print("Total:", solution.total) print("".center(80, "*")) return solution @classmethod def optimize( cls, config: Config, path: Path | None = None, ) -> Self: print("Computing deltas… ", end="", flush=True) entries = Entries.compute(config=config, path=path) print("Done.", flush=True) keysyms = cls.optimize_groups( config=config, data=entries.keysyms, data_max=entries.keysym_max, total0=32 * len(entries.keysyms), cls_=SimpleSolutionKeysymsCombinedMappings, ) unicode = cls.optimize_groups( config=config, data=entries.unicode, data_max=entries.unicode_max, total0=32 * len(entries.unicode), cls_=SimpleSolutionUnicodeCombinedMappings, ) result = cls(legacy_keysyms=keysyms, unicode=unicode) print(" Finished ".center(90, "*")) for s in result: if s.data: print( f"✨ {s.type}:", f"max: 0x{s.max:0>4x}", f"data_block_size={2**s.data_block_size_log2}", f"offsets_block_size={2**s.offsets1_block_size_log2}", f"data={len(s.data)} (int size: {s.data_int_size})", f"data_overlap={s.data_overlap}", f"offsets1={len(s.offsets1)} (uint size: {s.offsets1_int_size})", f"offsets2={len(s.offsets2)} (uint size: {s.offsets2_int_size})", f"total={s.total} ({s.total // 8})", ) print(f"Total: {result.total} ({result.total // 8})") print("".center(90, "*")) return result @classmethod def generate(cls, root: Path, write: bool, config: Config) -> None: s = cls.optimize( config=config, path=root / "data/keysyms.yaml", ) s.test(config) if write: s.write(root) MAPPING_TEMPLATE = """\ static const struct CaseMappings {prefix}data[{data_length}] = {{ {data} }}; static const uint{offsets1_int_size}_t {prefix}offsets1[{offsets1_length}] = {{ {offsets1} }}; static const uint{offsets2_int_size}_t {prefix}offsets2[{offsets2_length}] = {{ {offsets2} }}; static inline const struct CaseMappings * get_{prefix}entry(xkb_keysym_t ks) {{ return &{prefix}data[{prefix}offsets1[{prefix}offsets2[ks >> {k12}] + ((ks >> {k1}) & 0x{mask2:0>2x})] + (ks & 0x{mask1:0>2x})]; }}\ """ TEMPLATE = """\ // NOTE: This file has been generated automatically by “{python_script}”. // Do not edit manually! /* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ /* Case mappings for Unicode {unicode_version} * {doc} */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "utils.h" #include "keysym.h" struct CaseMappings{{ bool lower:1; bool upper:1; int{data_int_size}_t offset:{data_int_size_with_offset}; }}; {legacy_keysyms_mappings} {unicode_mappings} xkb_keysym_t xkb_keysym_to_lower(xkb_keysym_t ks) {{ if (ks <= 0x{max_non_unicode:0>4x}) {{ const struct CaseMappings *m = get_legacy_keysym_entry(ks); return (m->lower) ? ks + m->offset : ks; }} else if ({min_unicode} <= ks && ks <= 0x{max_unicode:0>8x}) {{ const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET); if (m->lower) {{ ks = ks + m->offset; return (ks < {min_unicode}) ? ks - XKB_KEYSYM_UNICODE_OFFSET : ks; }} else {{ return ks; }} }} else {{ return ks; }} }} xkb_keysym_t xkb_keysym_to_upper(xkb_keysym_t ks) {{ if (ks <= 0x{max_non_unicode:0>4x}) {{ const struct CaseMappings *m = get_legacy_keysym_entry(ks); return (m->upper) ? ks - m->offset : ks; }} else if ({min_unicode} <= ks && ks <= 0x{max_unicode:0>8x}) {{ const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET); if (m->upper) {{ ks = ks - m->offset; return (ks < {min_unicode}) ? ks - XKB_KEYSYM_UNICODE_OFFSET : ks; }} else {{ return ks; }} }} else {{ return ks; }} }} bool xkb_keysym_is_lower(xkb_keysym_t ks) {{ /* This predicate matches keysyms with their corresponding Unicode code point * having the Unicode property “Lowercase”. * * Here: a keysym is lower case if it has an upper case and no lower case. * Note: title case letters may have both. Example for U+01F2: * • U+01F1 DZ: upper case * • U+01F2 Dz: title case * • U+01F3 dz: lower case */ if (ks <= 0x{max_non_unicode:0>4x}) {{ const struct CaseMappings *m = get_legacy_keysym_entry(ks); return m->upper && !m->lower; }} else if ({min_unicode} <= ks && ks <= 0x{max_unicode:0>8x}) {{ const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET); return m->upper && !m->lower; }} else {{ return false; }} }} bool xkb_keysym_is_upper_or_title(xkb_keysym_t ks) {{ /* This predicate matches keysyms with their corresponding Unicode code point * having the Unicode properties “Uppercase” or General Category “Lt”. * * Here: a keysym is upper case or title case if it has a lower case. */ if (ks <= 0x{max_non_unicode:0>4x}) {{ return get_legacy_keysym_entry(ks)->lower; }} else if ({min_unicode} <= ks && ks <= 0x{max_unicode:0>8x}) {{ return get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET)->lower; }} else {{ return false; }} }} """ @staticmethod def myHex(n: int, max_hex_length: int) -> str: return ( f"""{"-" if n < 0 else " "}0x{hex(abs(n))[2:].rjust(max_hex_length, "0")}""" ) @classmethod def make_char_case_mappings(cls, e: Entry, max_hex_length: int) -> str: # If the entry has both lower and upper mappings, they must be equal. if e.lower and e.upper and e.lower != e.upper: raise ValueError(e) has_lower = e.is_upper or bool(e.lower) has_upper = e.is_lower or bool(e.upper) return f"{{{int(has_lower)}, {int(has_upper)},{cls.myHex(e.lower or e.upper, max_hex_length)}}}" def generate_mapping(self, prefix: str, sol: SimpleSolutionCombinedMappings) -> str: if not sol.offsets1_block_size_log2: raise ValueError(f"generate_mapping: {prefix}") max_data = max(max(abs(e.lower), abs(e.upper)) for e in sol.data) max_hex_length = 1 + (int(math.log2(max_data)) >> 2) return self.MAPPING_TEMPLATE.format( prefix=prefix, data_length=len(sol.data), data=",\n ".join( ", ".join( "".join(self.make_char_case_mappings(x, max_hex_length)) for x in xs ) for xs in itertools.batched(sol.data, 4) ), offsets1_int_size=sol.offsets1_int_size, offsets1_length=len(sol.offsets1), offsets1=",\n ".join( ", ".join(f"0x{x:0>4x}" for x in xs) for xs in itertools.batched(sol.offsets1, 10) ), offsets2_int_size=sol.offsets2_int_size, offsets2_length=len(sol.offsets2), offsets2=",\n ".join( ", ".join(f"0x{x:0>4x}" for x in xs) for xs in itertools.batched(sol.offsets2, 10) ), k1=sol.data_block_size_log2, k2=sol.offsets1_block_size_log2, k12=sol.data_block_size_log2 + sol.offsets1_block_size_log2, mask1=(1 << sol.data_block_size_log2) - 1, mask2=(1 << sol.offsets1_block_size_log2) - 1, ) def write(self, root: Path) -> None: path = root / "src/keysym-case-mappings.c" keysyms = self.generate_mapping("legacy_keysym_", self.legacy_keysyms) unicode = self.generate_mapping("unicode_", self.unicode) assert self.legacy_keysyms.data_int_size == self.unicode.data_int_size doc = textwrap.indent( textwrap.indent(__doc__.strip(), prefix=" "), prefix=" *", predicate=lambda _: True, ) content = self.TEMPLATE.format( python_script=Path(__file__).name, unicode_version=icu.UNICODE_VERSION, doc=doc, data_int_size=self.legacy_keysyms.data_int_size, data_int_size_with_offset=self.legacy_keysyms.data_int_size - 2, legacy_keysyms_mappings=keysyms, unicode_mappings=unicode, max_non_unicode=self.legacy_keysyms.max, min_unicode="XKB_KEYSYM_UNICODE_MIN", max_unicode=XKBCOMMON.XKB_KEYSYM_UNICODE_OFFSET + self.unicode.max, keysym_unicode_offset="XKB_KEYSYM_UNICODE_OFFSET", ) with path.open("wt", encoding="utf-8") as fd: fd.write(content) unicode_version_array = ", ".join( (icu.UNICODE_VERSION + ".0.0.0").split(".")[:4] ) path = root / "src/keysym.h.jinja" with path.open("rt", encoding="utf-8") as fd: content = fd.read() pattern: re.Pattern[str] = re.compile( r"^(#define\s+XKB_KEYSYM_UNICODE_VERSION\s+\{\s*)(?:\d+(?:,\s*\d+)*)*(\s*\})", re.MULTILINE, ) def replace(m: re.Match[str]) -> str: return f"{m.group(1)}{unicode_version_array}{m.group(2)}" content = pattern.sub(replace, content) with path.open("wt", encoding="utf-8") as fd: fd.write(content) ################################################################################ # Strategy ################################################################################ @unique class Strategy(Enum): Default = SeparateLegacyKeysymsAndUnicodeCombinedCaseMappings def __str__(self) -> str: return self.value.__name__ @classmethod def parse(cls, str: str) -> Self: for s in cls: if s.name == str: return s else: raise ValueError(str) @classmethod def run( cls, root: Path, config: Config, strategies: list[Self], write: bool ) -> None: # FIXME: more generic type results: list[SeparateLegacyKeysymsAndUnicodeCombinedCaseMappings] = [] best_total = math.inf best_solution: SeparateLegacyKeysymsAndUnicodeCombinedCaseMappings | None = None for strategy in strategies: print(f" Optimizing using {strategy.name} ".center(90, "=")) sol = strategy.value.optimize( config=config, path=root / "data/keysyms.yaml" ) sol.test(config) results.append(sol) if sol.total < best_total: best_total = sol.total best_solution = sol assert best_solution assert best_solution for strategy, sol in zip(strategies, results): print( f"{strategy.name}: {sol.total} ({sol.total // 8})", "✨✨✨" if sol is best_solution else "", ) best_solution.test(config) if write: best_solution.write(root) cls.write_tests(root) @classmethod def write_tests(cls, root: Path) -> None: # Configure Jinja template_loader = jinja2.FileSystemLoader(root, encoding="utf-8") jinja_env = jinja2.Environment( loader=template_loader, keep_trailing_newline=True, trim_blocks=True, lstrip_blocks=True, ) def code_point_name_constant(c: str, padding: int = 0) -> str: if not (name := unicodedata.name(c)): raise ValueError(f"No Unicode name for code point: U+{ord(c):0>4X}") name = name.replace("-", "_").replace(" ", "_").upper() return name.ljust(padding) jinja_env.filters["code_point"] = lambda c: f"0x{ord(c):0>4x}" jinja_env.filters["code_point_name_constant"] = code_point_name_constant path = root / "test/keysym-case-mapping.h" template_path = path.with_suffix(f"{path.suffix}.jinja") template = jinja_env.get_template(str(template_path.relative_to(root))) with path.open("wt", encoding="utf-8") as fd: fd.writelines( template.generate( upper_exceptions=Entry.to_upper_exceptions, script=SCRIPT.relative_to(root), ) ) def import_from_path(module_name: str, file_path: Path): spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) sys.modules[module_name] = module spec.loader.exec_module(module) return module ################################################################################ # Main ################################################################################ if __name__ == "__main__": # Root of the project ROOT = Path(__file__).parent.parent # Parse commands parser = argparse.ArgumentParser(description="Generate keysyms case mapping files") parser.add_argument( "--root", type=Path, default=ROOT, help="Path to the root of the project (default: %(default)s)", ) parser.add_argument( "--ucd", type=Path, help="Path to UCD directory to replace ICU", required=icu is None, ) parser.add_argument( "--ucd-version", type=str, help="Version of the UCD", required=icu is None, ) parser.add_argument( "--strategy", type=Strategy.parse, default=list(Strategy), nargs="+", choices=Strategy, help="Strategy (default: %(default)s)", dest="strategies", ) parser.add_argument( "--dry", action="store_true", help="Do not write (default: %(default)s)", ) parser.add_argument( "--verbose", action="store_true", help="Verbose (default: %(default)s)", ) parser.add_argument( "--no-check", action="store_true", help="Do not check errors (default: %(default)s)", ) args = parser.parse_args() if ucd_path := args.ucd: # Use a local UCD instead of ICU. # Useful when ICU is not available or when it does not support the latest # Unicode version. # Data are available at: https://www.unicode.org/Public//ucd/ icu = import_from_path( module_name="icu", file_path=Path(__file__).with_stem("ucd") ) if ucd_version := args.ucd_version: icu.UNICODE_VERSION = ucd_version icu.Char = icu.DB.parse_ucd(ucd_path) config = Config( check_error=not args.no_check, verbose=args.verbose, ) Strategy.run( root=args.root, config=config, write=not args.dry, strategies=args.strategies ) xkbcommon-libxkbcommon-54ee7ac/scripts/update-keysyms-definitions.py000077500000000000000000000146301510033435100262300ustar00rootroot00000000000000#!/usr/bin/env python3 """ Convert X11 keysyms headers into our keysyms header. """ from __future__ import print_function import re import os from pathlib import Path XORG_KEY_PREFIX = "XK_" KEY_PREFIX = "XKB_KEY_" EVDEV_MACRO = "_EVDEVK" EXTRA_SPACES = " " * (len(KEY_PREFIX) - len(XORG_KEY_PREFIX)) # Expected format: # #define XF86XK_FooBar 0x1234 /* some optional comment */ # or: # #define XF86XK_FooBar _EVDEVK(0x123) /* some optional comment */ # We also need to match commented evdev entries: # /* Use: XF86XK_FooBar _EVDEVK(0x123) some optional comment */ # /* TODO: … _EVDEVK(0x123) some optional comment */ keysym_entry_pattern = re.compile( rf"""^ (?:(?P\#define)\s+|(?P/\*\s+Use:)\s+|(?P/\*\s+TODO:)) (?(todo) (?P(?:\s+(?!{EVDEV_MACRO}|0x)\S+)+) | (?:(?P\w*){XORG_KEY_PREFIX}|(?=NoSymbol))(?P\w+) ) (?P\s+) (?P{EVDEV_MACRO}\()?(?P0x[0-9A-Fa-f]+)(?(evdev)\)) """, re.VERBOSE, ) # Match keysym guarded by #ifndef keysym_ifndef_pattern = re.compile( rf"^#ifndef\s+(?P\w*){XORG_KEY_PREFIX}(?P\w+)\s*$" ) # Match remaining XK_ references in the comments, e.g we will replace: # XF86XK_CamelCaseKernelName _EVDEVK(kernel value) # #define XKB_KEY_SunCompose 0x0000FF20 /* Same as XK_Multi_key */ # with: # XKB_KEY_XF86CamelCaseKernelName _EVDEVK(kernel value) # #define XKB_KEY_SunCompose 0x0000FF20 /* Same as XKB_KEY_Multi_key */ xorgproto_keysym_prefix_pattern = re.compile( rf"\b(?P\w*){XORG_KEY_PREFIX}(?!KOREAN\b)" ) alias_pattern = re.compile( rf"(?P(?:(?:D|d)eprecated )?(?:a|A)lias for ){KEY_PREFIX}(?P[^\*]+)" ) def make_keysym_name(m: re.Match[str]) -> str: return m.group("prefix") + m.group("name") def make_keysym_entry(m: re.Match[str]) -> str: """ Perform the substitutions """ if m.group("evdev"): if m.group("define"): # Replace the xorgproto _EVDEVK macro with the actual value: # 0x10081000 is the base, the evdev hex code is added to that. # We replace to make parsing of the keys later easier. value = 0x10081000 + int(m.group("value"), 16) value_str = f"{value:#x} " else: value_str = f"""{EVDEV_MACRO}({m.group("value")})""" else: value_str = m.group("value") spacing = m.group("spacing") if todo := m.group("todo"): todo_comment = m.group("todo_comment") todo_commentʹ = xorgproto_keysym_prefix_pattern.sub( rf"{KEY_PREFIX}\1", todo_comment ) if todo_commentʹ != todo_comment: diff = len(todo_commentʹ) - len(todo_comment) if diff != len(EXTRA_SPACES): raise ValueError() todo_comment = todo_commentʹ else: spacing += EXTRA_SPACES return f"""{todo}{todo_comment}{spacing}{value_str}""" else: prefix = m.group("prefix") or "" name = m.group("name") define = m.group("define") or m.group("use") if m.group("use") and name == "NoSymbol": spacing += EXTRA_SPACES key_prefix = "" else: key_prefix = KEY_PREFIX return f"""{define} {key_prefix}{prefix}{name}{spacing}{value_str}""" def fix_alias(m: re.Match[str]) -> str: alias = m.group("alias") comment = m.group("comment") if len(comment) - len(comment.rstrip()) > 1: spaces = " " * len(XORG_KEY_PREFIX) else: spaces = "" return f"{alias}{comment}{spaces}" prefix = Path(os.environ.get("X11_HEADERS_PREFIX", "/usr")) HEADERS = ( prefix / "include/X11/keysymdef.h", prefix / "include/X11/XF86keysym.h", prefix / "include/X11/Sunkeysym.h", prefix / "include/X11/DECkeysym.h", prefix / "include/X11/HPkeysym.h", ) print( f"""#ifndef _XKBCOMMON_KEYSYMS_H #define _XKBCOMMON_KEYSYMS_H /* This file is autogenerated; please do not commit directly. */ /** * @file * Key symbols (keysyms) definitions. */ #define {KEY_PREFIX}NoSymbol 0x000000 /* Special KeySym */ """ ) keysyms: set[str] = set() for path in HEADERS: pending_guarded_keysym: str | None = None with path.open("rt", encoding="utf-8") as header: for line in header: # Duplicate keysym name guard if m := keysym_ifndef_pattern.match(line): if pending_guarded_keysym: raise ValueError(f"Nested #ifndef {pending_guarded_keysym}") pending_guarded_keysym = make_keysym_name(m) continue # Ignore C macro #ifdef/#ifndef elif line.startswith("#ifdef") or line.startswith("#ifndef"): if pending_guarded_keysym: raise ValueError(f"Nested C macro {pending_guarded_keysym}") continue # Ignore C macro #endif and check end of keysym name guard elif line.startswith("#endif"): if pending_guarded_keysym: pending_guarded_keysym = None continue # Ignore C macro #undef elif line.startswith("#undef"): continue # Remove #define _OSF_Keysyms and such. elif line.startswith("#define _"): continue # Keysym entry: proceed various tests if line.startswith("#") and (m := keysym_entry_pattern.match(line)): name = make_keysym_name(m) # Check expected guarded keysym, if relevant if pending_guarded_keysym and name != pending_guarded_keysym: raise ValueError(f"{path}: Malformed keysym name guard: {line}") # Check if name already defined elif name in keysyms: if pending_guarded_keysym: # Ignore guarded keysym continue else: raise ValueError(f"{path}: Unguarded redefinition: {line}") else: keysyms.add(name) # Perform _EVDEV and XK_ substitutions line = keysym_entry_pattern.sub(make_keysym_entry, line) line = xorgproto_keysym_prefix_pattern.sub(rf"{KEY_PREFIX}\1", line) line = alias_pattern.sub(fix_alias, line) print(line.rstrip(), end="\n") print() print("#endif") xkbcommon-libxkbcommon-54ee7ac/scripts/update-keysyms-derived-headers.py000077500000000000000000000111731510033435100267470ustar00rootroot00000000000000#!/usr/bin/env python3 """ Generate headers related to keysyms bounds """ import argparse import itertools import re import sys from collections import defaultdict from pathlib import Path from typing import Any, TypeAlias import jinja2 KEYSYM_PATTERN = re.compile( r"^#define\s+XKB_KEY_(?P\w+)\s+(?P0x[0-9a-fA-F]+)\s" ) MAX_AMBIGUOUS_NAMES = 3 KeysymsBounds: TypeAlias = dict[str, int | str] KeysymsCaseFoldedNames: TypeAlias = dict[str, list[str]] def load_keysyms(path: Path) -> tuple[KeysymsBounds, KeysymsCaseFoldedNames]: # Load the keysyms header keysym_min = sys.maxsize keysym_max = 0 min_unicode_keysym = 0x01000100 max_unicode_keysym = 0x0110FFFF names: dict[int, set[str]] = defaultdict(set) canonical_names: dict[int, str] = {} casefolded_names: dict[str, list[str]] = defaultdict(list) max_unicode_name = "U10FFFF" max_keysym_name = "0x1fffffff" # XKB_KEYSYM_MAX with path.open("rt", encoding="utf-8") as fd: for line in fd: if m := KEYSYM_PATTERN.match(line): value = int(m.group("value"), 16) keysym_min = min(keysym_min, value) keysym_max = max(keysym_max, value) name = m.group("name") names[value].add(name) casefolded_names[name.casefold()].append(name) if value not in canonical_names: canonical_names[value] = name XKB_KEYSYM_LONGEST_CANONICAL_NAME = max( max(canonical_names.values(), key=len), max_unicode_name, max_keysym_name, key=len, ) XKB_KEYSYM_LONGEST_NAME = max( max(itertools.chain.from_iterable(casefolded_names.values()), key=len), max_unicode_name, max_keysym_name, key=len, ) XKB_KEYSYM_EXPLICIT_ALIASES_MAX = max(map(len, names.values())) # Keep only ambiguous case-insensitive names and sort them for name in tuple(casefolded_names.keys()): count = len(casefolded_names[name]) if count < 2: del casefolded_names[name] elif count > MAX_AMBIGUOUS_NAMES: raise ValueError( f"""Expected max {MAX_AMBIGUOUS_NAMES} keysyms for "{name}", got: {count}""" ) else: casefolded_names[name].sort() return ( { "XKB_KEYSYM_MIN_ASSIGNED": min(keysym_min, min_unicode_keysym), "XKB_KEYSYM_MAX_ASSIGNED": max(keysym_max, max_unicode_keysym), "XKB_KEYSYM_MIN_EXPLICIT": keysym_min, "XKB_KEYSYM_MAX_EXPLICIT": keysym_max, "XKB_KEYSYM_COUNT_EXPLICIT": len(canonical_names), # Extra byte for terminating NULL "XKB_KEYSYM_NAME_MAX_SIZE": len(XKB_KEYSYM_LONGEST_CANONICAL_NAME) + 1, "XKB_KEYSYM_LONGEST_CANONICAL_NAME": XKB_KEYSYM_LONGEST_CANONICAL_NAME, "XKB_KEYSYM_LONGEST_NAME": XKB_KEYSYM_LONGEST_NAME, "XKB_KEYSYM_EXPLICIT_ALIASES_MAX": XKB_KEYSYM_EXPLICIT_ALIASES_MAX, }, casefolded_names, ) def generate( env: jinja2.Environment, data: dict[str, Any], root: Path, file: Path, ) -> None: """Generate a file from its Jinja2 template""" template_path = file.with_suffix(f"{file.suffix}.jinja") template = env.get_template(str(template_path)) path = root / file with path.open("wt", encoding="utf-8") as fd: fd.writelines(template.generate(**data)) # Root of the project SCRIPT = Path(__file__) ROOT = SCRIPT.parent.parent # Parse commands parser = argparse.ArgumentParser( description="Generate C header files related to keysyms bounds" ) parser.add_argument( "--root", type=Path, default=ROOT, help="Path to the root of the project (default: %(default)s)", ) args = parser.parse_args() # Configure Jinja template_loader = jinja2.FileSystemLoader(args.root, encoding="utf-8") jinja_env = jinja2.Environment( loader=template_loader, keep_trailing_newline=True, trim_blocks=True, lstrip_blocks=True, ) jinja_env.filters["keysym"] = lambda ks: f"0x{ks:0>8x}" # Load keysyms keysyms_bounds, keysyms_ambiguous_case_insensitive_names = load_keysyms( args.root / "include/xkbcommon/xkbcommon-keysyms.h" ) # Generate the files generate( jinja_env, dict( keysyms_bounds, script=SCRIPT.relative_to(ROOT), ), args.root, Path("src/keysym.h"), ) generate( jinja_env, dict( keysyms_bounds, ambiguous_case_insensitive_names=keysyms_ambiguous_case_insensitive_names, MAX_AMBIGUOUS_NAMES=MAX_AMBIGUOUS_NAMES, script=SCRIPT.relative_to(ROOT), ), args.root, Path("test/keysym.h"), ) xkbcommon-libxkbcommon-54ee7ac/scripts/update-keysyms-names-handling.py000077500000000000000000000333401510033435100266010ustar00rootroot00000000000000#!/usr/bin/env python3 """ Generate C file to handle keysym names """ import argparse import itertools import random import re import sys from collections import defaultdict from dataclasses import dataclass from enum import Enum from pathlib import Path from typing import DefaultDict, Generator, Iterable, Iterator import perfect_hash # Root of the project SCRIPT = Path(__file__) ROOT = SCRIPT.parent.parent # Parse commands parser = argparse.ArgumentParser(description="Generate C file to handle keysym names") parser.add_argument( "c_header", type=Path, help="Path to the libxkbcommon keysym header" ) parser.add_argument("gperf", type=Path, help="Path to the gperf file") args = parser.parse_args() # Set the seed explicitly, so we reduce diff random.seed(b"libxkbcommon") KEYSYM_ENTRY_PATTERN = re.compile( r""" ^\#define\s+ XKB_KEY_(?P\w+)\s+ (?P0x[0-9a-fA-F]+)\s* (?:/\*\s* (?: (?P(?:D|d)eprecated)| \([0-9a-fA-F]{4,}>)\)| \(U\+(?P[0-9a-fA-F]{4,})\s(?:\s|\w|-)+\)| .* ) )? """, re.VERBOSE, ) class Deprecation(Enum): NONE = "none" "No deprecation" EXPLICIT = "explicit" "Explicit deprecation in comment: /* deprecated */" IMPLICIT = "implicit" """ Implicit deprecation: the keysym has already been defined with a previous name, and the present name has not been declared explicitly as an alias. """ @dataclass class Keysym: name: str value: int deprecated: Deprecation alias: bool def parse_keysyms(path: Path) -> Iterator[Keysym]: with path.open("rt", encoding="utf-8") as fd: for line in fd: if m := KEYSYM_ENTRY_PATTERN.match(line): yield Keysym( name=m.group("name"), value=int(m.group("value"), 16), deprecated=Deprecation.EXPLICIT if m.group("deprecated") or m.group("deprecated_unicode") else Deprecation.NONE, alias="alias for" in line.casefold() or m.group("unicode_alt_semantics"), ) def get_keysyms(path: Path) -> dict[int, list[Keysym]]: keysyms: DefaultDict[int, list[Keysym]] = defaultdict(list) for keysym in parse_keysyms(path): if ( (ks := keysyms.get(keysym.value)) and keysym.deprecated is Deprecation.NONE and not keysym.alias # deal with first name being deprecated and any(k.deprecated is Deprecation.NONE for k in ks) ): keysym.deprecated = Deprecation.IMPLICIT keysyms[keysym.value].append(keysym) return keysyms keysyms_by_value = get_keysyms(args.c_header) entries = tuple(itertools.chain.from_iterable(keysyms_by_value.values())) # Sort based on the keysym name: # 1. Sort by the casefolded name: e.g. kana_ya < kana_YO. # 2. If same casefolded name, then sort by cased name, i.e for # ASCII: upper before lower: e.g kana_YA < kana_ya. # E.g. kana_YA < kana_ya < kana_YO < kana_yo # WARNING: this sort must not be changed, as some functions e.g. # xkb_keysym_from_name rely on upper case variant occuring first. entries_isorted = sorted(entries, key=lambda e: (e.name.casefold(), e.name)) # Sort based on keysym value. Sort is stable so in case of duplicate, the first # keysym occurence stays first. entries_kssorted = sorted(entries, key=lambda e: e.value) print( f""" /** * This file comes from libxkbcommon and was generated by {SCRIPT.name} * You can always fetch the latest version from: * https://raw.github.com/xkbcommon/libxkbcommon/master/src/ks_tables.h */ #pragma once """ ) entry_offsets: dict[str, int] = {} UINT16_MAX = (1 << 16) - 1 UNICODE_KEYSYM = UINT16_MAX - 1 DEPRECATED_KEYSYM = UINT16_MAX MAX_EXPLICIT_DEPRECATED_ALIAS_INDEX_LOG2 = 8 MAX_EXPLICIT_DEPRECATED_ALIAS_INDEX = 1 << MAX_EXPLICIT_DEPRECATED_ALIAS_INDEX_LOG2 MAX_EXPLICIT_DEPRECATED_ALIAS_COUNT_LOG2 = 4 MAX_EXPLICIT_DEPRECATED_ALIAS_COUNT = 1 << MAX_EXPLICIT_DEPRECATED_ALIAS_COUNT_LOG2 MAX_OFFSET = UNICODE_KEYSYM - 1 XKB_KEYSYM_UNICODE_MIN = 0x01000100 XKB_KEYSYM_UNICODE_MAX = 0x0110FFFF print( """ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverlength-strings" #endif static const char *keysym_names = """.strip() ) offs = 0 for keysym in entries_isorted: if offs >= MAX_OFFSET: raise ValueError(f"Offset must be kept under {MAX_OFFSET}, got: {offs}.") entry_offsets[keysym.name] = offs print(f' "{keysym.name}\\0"') offs += len(keysym.name) + 1 print( """ ; #ifdef __GNUC__ #pragma GCC diagnostic pop #endif """.strip() ) template = r""" static const uint16_t keysym_name_G[] = { $G }; static size_t keysym_name_hash_f(const char *key, const char *T) { size_t sum = 0; for (size_t i = 0; key[i] != '\0'; i++) sum += (size_t) (T[i % $NS] * key[i]); return sum % $NG; } static inline size_t keysym_name_perfect_hash(const char *key) { return ( keysym_name_G[keysym_name_hash_f(key, "$S1")] + keysym_name_G[keysym_name_hash_f(key, "$S2")] ) % $NG; } """ print( perfect_hash.generate_code( keys=[keysym.name for keysym in entries_isorted], template=template, ) ) print( """ struct name_keysym { xkb_keysym_t keysym; uint16_t offset; };\n""" ) def print_entries(entries: Iterable[Keysym]): for entry in entries: print( " {{ 0x{value:08x}, {offs} }}, /* {name} */".format( offs=entry_offsets[entry.name], value=entry.value, name=entry.name ) ) print("static const struct name_keysym name_to_keysym[] = {") print_entries(entries_isorted) print("};\n") # *.sort() is stable so we always get the first keysym for duplicate print("static const struct name_keysym keysym_to_name[] = {") print_entries( next(g[1]) for g in itertools.groupby(entries_kssorted, key=lambda e: e.value) ) print("};\n") def make_deprecated_entry( value, keysyms: list[Keysym], entry_offsets: dict[str, int], explicit_deprecated_aliases_index: int, ) -> tuple[str | None, tuple[int, ...]]: assert keysyms non_deprecated_ks = tuple(k for k in keysyms if k.deprecated is Deprecation.NONE) explicit_deprecated_aliases: tuple[int, ...] = () if non_deprecated_ks: # Keysym is not deprecated. Check if none of its aliases are. if len(keysyms) == 1 or all( ks.alias and ks.deprecated is Deprecation.NONE for ks in keysyms[1:] ): return None, () ref = non_deprecated_ks[0].name canonical_name = f"Reference: {ref}. " assert ref in entry_offsets canonical_index = str(entry_offsets[ref]) deprecated_ks = tuple(k for k in keysyms if k not in non_deprecated_ks) if any(ks.alias and ks.deprecated is Deprecation.NONE for ks in keysyms[1:]): # keysym has both explicit and deprecated aliases explicit_deprecated_aliases = tuple( entry_offsets[ks.name] for ks in keysyms[1:] if ks.deprecated is not Deprecation.NONE ) assert ( explicit_deprecated_aliases_index < MAX_EXPLICIT_DEPRECATED_ALIAS_INDEX ) assert ( len(explicit_deprecated_aliases) < MAX_EXPLICIT_DEPRECATED_ALIAS_COUNT ) else: explicit_deprecated_aliases_index = 0 else: # Keysym is deprecated canonical_name = "" canonical_index = ( "DEPRECATED_KEYSYM" if value < XKB_KEYSYM_UNICODE_MIN or value > XKB_KEYSYM_UNICODE_MAX else "UNICODE_KEYSYM" ) deprecated_ks = keysyms explicit_deprecated_aliases_index = 0 if non_deprecated_ks[1:]: non_deprecated = ( "Non deprecated aliases: " + ", ".join(ks.name for ks in non_deprecated_ks[1:]) + ". " ) else: non_deprecated = "" deprecated = ", ".join(ks.name for ks in deprecated_ks) comment = f"{canonical_name}{non_deprecated}Deprecated: {deprecated}" return ( f" {{ 0x{value:0>8x}, {canonical_index: <17}, {explicit_deprecated_aliases_index}, {len(explicit_deprecated_aliases)} }}, /* {comment} */", explicit_deprecated_aliases, ) def generate_deprecated_keysyms( keysyms_by_value: dict[int, list[Keysym]], entry_offsets: dict[str, int] ) -> Generator[tuple[int, ...], None, None]: explicit_deprecated_aliases_index = 0 for value, keysyms in sorted(keysyms_by_value.items(), key=lambda e: e[0]): assert keysyms c_entry, explicit_deprecated_aliases = make_deprecated_entry( value, keysyms, entry_offsets, explicit_deprecated_aliases_index ) if c_entry is not None: print(c_entry) if explicit_deprecated_aliases: yield explicit_deprecated_aliases explicit_deprecated_aliases_index += len(explicit_deprecated_aliases) def generate_mixed_aliases(aliases: Iterable[Iterable[int]]): for xs in aliases: for x in xs: print(f" {x},") print(f"#define UNICODE_KEYSYM 0x{UNICODE_KEYSYM:x}") print(f"#define DEPRECATED_KEYSYM 0x{DEPRECATED_KEYSYM:x}") # NOTE: Alternative implementation, useful the day the indices do not fit uint16_t. # print(f""" # struct deprecated_keysym {{ # xkb_keysym_t keysym; # union {{ # uint32_t offset; # struct {{ # uint32_t offset:{MAX_OFFSET_LOG2}; # /* Explicit deprecated aliases start index & count */ # uint8_t explicit_index:{MAX_EXPLICIT_DEPRECATED_ALIAS_INDEX_LOG2}; # uint8_t explicit_count:{MAX_EXPLICIT_DEPRECATED_ALIAS_COUNT_LOG2}; # }} details; # }}; # }}; # """) print(""" struct deprecated_keysym { xkb_keysym_t keysym; uint16_t offset; /* Explicit deprecated aliases start index & count */ uint8_t explicit_index; uint8_t explicit_count; }; """) print("static const struct deprecated_keysym deprecated_keysyms[] = {") explicit_deprecated_aliases = tuple( generate_deprecated_keysyms(keysyms_by_value, entry_offsets) ) print("};\n") print("static const uint32_t explicit_deprecated_aliases[] = {") generate_mixed_aliases(explicit_deprecated_aliases) print("};") print(f"max name offset: {max(entry_offsets.values())}", file=sys.stderr) # Check that the keywords of our XKB parser that clash with keysyms are handled properly def parse_gperf_keywords(path: Path) -> Iterator[str]: with path.open("rt", encoding="utf-8") as fd: in_keyword_section = False for line in fd: if line.startswith(r"%%"): # This is a boundary of the keywords section if in_keyword_section: break in_keyword_section = True elif in_keyword_section: # Parse the keywords keyword, *_ = line.split(",") yield keyword.strip().casefold() # Skip any line until we reach the keywords else: raise ValueError("Parse error: keywords section boundary not found") SUPPORTED_KEYWORDS_CLASHES = {"section"} UNSUPPORTED_KEYWORDS_CLASHES = frozenset(parse_gperf_keywords(args.gperf)).difference( SUPPORTED_KEYWORDS_CLASHES ) expected_clashes: set[str] = set() errors = 0 for entry in entries: if entry.name.casefold() in UNSUPPORTED_KEYWORDS_CLASHES: print( f"ERROR: keysym “{entry.name}” (0x{entry.value:0>4x}) clashes with keywords", "and cannot be parsed properly.", file=sys.stderr, ) errors += 1 elif (lower := entry.name.lower()) in SUPPORTED_KEYWORDS_CLASHES: if not entry.name.islower(): # Keywords’s atoms are registered in *lower* case, so the keysym will be # replaced by the keysym with the corresponding name, but they may not match. entry2: Keysym = Keysym("NoSymbol", 0, Deprecation.NONE, False) if any( e.name == lower for e in keysyms_by_value[entry.value] if e.name != entry.value ): # There is a keysym in lower case that is an alias print( f"WARNING: keysym “{entry.name}”", f"will be parsed as “{lower}” (expected)", file=sys.stderr, ) else: # Lookup the keysym mismatch for e in entries: if e.name == lower: entry2 = e break print( f"ERROR: keysym “{entry.name}” (0x{entry.value:0>4x})", r"clashes with keywords and will be replaced by", f"“{entry2.name}” (0x{entry2.value:0>4x}).", file=sys.stderr, ) errors += 1 else: print( f"WARNING: keysym “{entry.name}” clashing with keywords (expected)", file=sys.stderr, ) expected_clashes.add(entry.name) if diff := SUPPORTED_KEYWORDS_CLASHES.difference(expected_clashes): print(f"ERROR: Unexpected missing clashing keysyms: {diff}", file=sys.stderr) errors += 1 if errors: print( f" {errors} ERRORS ".center(80, "-"), "Please update the parser file `parser.y` to handle keysyms causing clashes.", "The relevant entries are:", "- Keysym", "- Element (for modmap, parsed via: Expr -> Term -> Lhs -> FieldSpec -> Element)", file=sys.stderr, sep="\n", ) exit(1) xkbcommon-libxkbcommon-54ee7ac/scripts/update-keywords000077500000000000000000000002641510033435100234310ustar00rootroot00000000000000#!/bin/sh # Run this if you add/remove a new keyword to the xkbcomp scanner, # or just want to regenerate the gperf file. gperf src/xkbcomp/keywords.gperf > src/xkbcomp/keywords.c xkbcommon-libxkbcommon-54ee7ac/scripts/update-merge-modes-tests.py000077500000000000000000002737371510033435100255760ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2025 Pierre Le Marre # SPDX-License-Identifier: MIT """ This script generate tests for merge modes. """ from __future__ import annotations from abc import ABCMeta, abstractmethod import argparse from collections import defaultdict from collections.abc import Callable, Generator, Iterable, Iterator, Sequence import dataclasses import itertools import re import textwrap from dataclasses import dataclass from enum import Flag, IntFlag, StrEnum, auto, unique from pathlib import Path from string import Template from typing import Any, ClassVar, NewType, Self import jinja2 SCRIPT = Path(__file__) # Root of the project ROOT = SCRIPT.parent.parent ################################################################################ # # XKB compiler # ################################################################################ @dataclass class XkbCompiler: name: str extended_syntax: bool default: ClassVar[str] = "xkbcommon" @property def is_default(self) -> bool: return self.name == self.default @property def suffix(self) -> str: return "" if self.is_default else "-" + self.name @classmethod def parse(cls, name: str) -> Self: match name: case cls.default: return cls(name=name, extended_syntax=True) case "xkbcomp": return cls(name=name, extended_syntax=False) case "kbvm": return cls(name=name, extended_syntax=True) case _: raise ValueError(f"Invalid XKB compiler: {name}") ################################################################################ # # Merge modes # ################################################################################ @unique class MergeMode(StrEnum): Default = auto() Augment = auto() Override = auto() Replace = auto() @property def include(self) -> str: if self is self.__class__.Default: return "include" else: return self @property def char(self) -> str: match self: case self.__class__.Default: return "+" case self.__class__.Augment: return "|" case self.__class__.Override: return "+" case self.__class__.Replace: return "^" case _: raise ValueError(self) INDENT = "\t" ################################################################################ # # Components # ################################################################################ @unique class Component(StrEnum): keycodes = auto() types = auto() compat = auto() symbols = auto() def render_keymap(self, content) -> Generator[str]: yield "xkb_keymap {" for component in self.__class__: yield from ( textwrap.indent(t, INDENT) for t in self.render(component, content if component is self else "") ) yield "};" @classmethod def render(cls, component: Self, content: str, name: str = "") -> Generator[str]: if not content: match component: case cls.keycodes: pass case cls.types: pass case cls.compat: content = "interpret.repeat= True;" case cls.symbols: pass if name: name = f' "{name}"' if content: yield f'xkb_{component}{name} "" {{' yield textwrap.indent(content, INDENT) yield "};" else: yield f'xkb_{component}{name} "" {{}};' class ComponentTemplate(Template): def __init__(self, template) -> Self: super().__init__(textwrap.dedent(template).strip()) def __bool__(self) -> bool: return bool(self.template) def render(self, merge: MergeMode) -> str: mode = "" if merge is MergeMode.Default else f"{merge} " return self.substitute(mode=mode) def __add__(self, other: Any) -> Self: if isinstance(other, str): return self.__class__(self.template + "\n" + other) elif isinstance(other, Template): return self.__class__(self.template + "\n" + other.template) else: return NotImplemented def __radd__(self, other: Any) -> Self: if isinstance(other, str): return self.__class__(other + "\n" + self.template) elif isinstance(other, Template): return self.__class__(other.template + "\n" + self.template) else: return NotImplemented ################################################################################ # # Test templates # ################################################################################ @dataclass class Test: title: str file: Path content: str expected: str @dataclass class TestGroup: title: str tests: Sequence[Test] c_template: ClassVar[Path] = Path("test/merge_modes.c.jinja") SLUG_PATTERN: ClassVar[re.Pattern[str]] = re.compile(r"[^-\w()]+") @classmethod def file(cls, title: str) -> Path: return Path(cls.SLUG_PATTERN.sub("-", title.lower().replace(" ", "_"))) @classmethod def _write( cls, root: Path, jinja_env: jinja2.Environment, path: Path, **kwargs, ) -> None: template_path = root / cls.c_template template = jinja_env.get_template(template_path.relative_to(root).as_posix()) with path.open("wt", encoding="utf-8") as fd: fd.writelines(template.generate(script=SCRIPT.relative_to(ROOT), **kwargs)) @classmethod def write_c( cls, root: Path, jinja_env: jinja2.Environment, path: Path, compiler: XkbCompiler, tests: Sequence[TestGroup], ) -> None: return cls._write( root=root, jinja_env=jinja_env, path=path, compiler=compiler, tests=tests ) @classmethod def write_data( cls, root: Path, compiler: XkbCompiler, tests: Sequence[TestGroup], ) -> None: tests_: dict[Path, list[Test]] = defaultdict(list) suffix = compiler.suffix for group in tests: for test in group.tests: file = test.file.parent file = file.with_name(file.name + suffix) tests_[file].append(test) for file, group_ in tests_.items(): path = root / "test" / "data" / file with path.open("wt", encoding="utf-8") as fd: fd.write( "// WARNING: This file was auto-generated by: " f"{SCRIPT.relative_to(ROOT)}\n" ) for test in group_: fd.write(test.content) @dataclass class TestTemplate(metaclass=ABCMeta): title: str _plain: ClassVar[str] = "plain" _include: ClassVar[str] = "include" _base: ClassVar[str] = "base" _update: ClassVar[str] = "update" _file: ClassVar[str] = "merge_modes" def make_title(self, name: str) -> str: return f"{self.title}: {name}" @classmethod def make_file(cls, name: str) -> Path: return TestGroup.file(name) @abstractmethod def generate_tests(self) -> TestGroup: ... @abstractmethod def generate_data(self) -> TestGroup: ... @classmethod @abstractmethod def write( cls, root: Path, jinja_env: jinja2.Environment, c_file: Path | None, xkb: bool, compiler: XkbCompiler, tests: Sequence[Self], debug: bool, ): ... @dataclass class ComponentTestTemplate(TestTemplate): component: Component # Templates to test base_template: ComponentTemplate update_template: ComponentTemplate # Expected result augment: str override: str replace: str = "" def __post_init__(self): self.augment = textwrap.dedent(self.augment).strip() self.override = textwrap.dedent(self.override).strip() if not self.replace: self.replace = self.override else: self.replace = textwrap.dedent(self.replace).strip() def expected(self, mode: MergeMode) -> str: match mode: case MergeMode.Default: return self.override case MergeMode.Augment: return self.augment case MergeMode.Override: return self.override case MergeMode.Replace: return self.replace case _: raise ValueError(mode) def _make_section_name(self, type: str, mode: MergeMode) -> str: file = self.make_file(f"{self.title}-{mode}" if self.title else mode) return f"{type}-{file}" def _make_file(self, type: str, mode: MergeMode) -> Path: section_name = self._make_section_name(type, mode) return Path(self.component) / self._file / section_name def render_section(self, content: str, name: str = "") -> str: return "\n".join(self.component.render(self.component, content, name)) def render_keymap(self, content: str) -> str: return "\n".join(self.component.render_keymap(content)) def _generate_tests( self, render: Callable[[str], str], compiler: XkbCompiler ) -> Generator[Test]: include_suffix = compiler.suffix for base_mode, update_mode in itertools.product(MergeMode, MergeMode): # Plain content = ( self.base_template.render(base_mode) + ("\n" if self.base_template else "") + self.update_template.render(update_mode) ) yield Test( title=self.make_title( f"{self._plain} ({base_mode}) - {self._plain} ({update_mode})" ), file=self.make_file(self.title) / self.make_file(update_mode), content=render(content), expected=render(self.expected(update_mode)), ) for base_mode, update_mode in itertools.product( (MergeMode.Default,), MergeMode ): # Plain + Include file = self._make_file(self._update, update_mode) section = file.name file = file.parent.name for mode in MergeMode: yield Test( title=self.make_title( f"{self._plain} ({base_mode}) - {mode.include} ({update_mode})" ), file=self.make_file(self.title) / self.make_file(mode), content=render( self.base_template.render(base_mode) + ( f'\n{mode.include} "{file}{include_suffix}({section})"' if self.base_template else "" ) ), # Include does not leak local merge modes expected=render(self.expected(mode)), ) # for base_mode, update_mode in itertools.product(MergeMode, MergeMode): # # Include + Plain # file = self._make_file(self.base, base_mode) # section = file.name # file = file.parent.name # for mode in (MergeMode.default,): # yield Test( # title=self.make_title( # f"{mode.include} ({base_mode}) - {self.plain} ({update_mode})" # ), # file=self.make_file(self.title) # / self.make_file( # f"{mode.include}({base_mode})-{self.plain}({update_mode})" # ), # content=render( # f'{mode.include} "{file}{include_suffix}({section})"\n' # + self.update_template.render(update_mode) # ), # expected=render(self.expected(update_mode)), # ) # for base_mode, update_mode in itertools.product((MergeMode.Default,), MergeMode): # # Include + Include # mode = MergeMode.Default # base_file = self._make_file(self.base, mode) # base_section = base_file.name # base_file = base_file.parent.name # update_file = self._make_file(self.update, mode) # update_section = update_file.name # update_file = update_file.parent.name # yield Test( # title=self.make_title( # f"{base_mode.include} ({mode}) - {update_mode.include} ({mode})" # ), # file=self.make_file(self.title) # / self.make_file( # f"{base_mode.include}({mode})-{update_mode.include}({mode})" # ), # content=render( # f'{base_mode.include} "{base_file}{include_suffix}({base_section})"\n' # + f'{update_mode.include} "{update_file}{include_suffix}({update_section})"' # ), # expected=render(self.expected(update_mode)), # ) for base_mode, update_mode in itertools.product(MergeMode, MergeMode): # Multi-include base_file = self._make_file(self._base, base_mode) base_section = base_file.name base_file = base_file.parent.name update_file = self._make_file(self._update, update_mode) update_section = update_file.name update_file = update_file.parent.name for mode in (MergeMode.Override, MergeMode.Augment, MergeMode.Replace): yield Test( title=self.make_title( f"{self._include} ({base_mode} {mode.char} {update_mode})" ), file=self.make_file(self.title) / self.make_file(mode), content=render( f'{base_mode.include} "{base_file}{include_suffix}({base_section})' + mode.char + f'{update_file}{include_suffix}({update_section})"' ), expected=render(self.expected(mode)), ) def _generate_data(self) -> Generator[Test]: for type, template in ( (self._base, self.base_template), (self._update, self.update_template), ): for mode in MergeMode: section_name = self._make_section_name(type, mode) file = self._make_file(type, mode) content = template.render(mode) content = self.render_section(content=content, name=section_name) + "\n" yield Test(title="", file=file, content=content, expected="") def generate_tests( self, compiler: XkbCompiler, as_keymap: bool = False ) -> TestGroup: if as_keymap: def render(content: str) -> str: return self.render_keymap(content) else: def render(content: str) -> str: return self.render_section(content) return TestGroup(self.title, tuple(self._generate_tests(render, compiler))) def generate_data(self) -> TestGroup: return TestGroup(self.title, tuple(self._generate_data())) @classmethod def write( cls, root: Path, jinja_env: jinja2.Environment, c_file: Path | None, xkb: bool, compiler: XkbCompiler, tests: Sequence[Self], debug: bool = False, ): if c_file is not None and c_file.name: c_data = tuple( t.generate_tests(as_keymap=True, compiler=compiler) for t in tests ) TestGroup.write_c( root=root, jinja_env=jinja_env, path=c_file, compiler=compiler, tests=c_data, ) if xkb: xkb_data = tuple(t.generate_data() for t in tests) TestGroup.write_data(root=root, compiler=compiler, tests=xkb_data) KeymapTemplate = Template( """\ xkb_keymap { ${keycodes} ${types} ${compat} ${symbols} };""" ) @dataclass class KeymapTestTemplate(TestTemplate): keycodes: ComponentTestTemplate | None = None types: ComponentTestTemplate | None = None compat: ComponentTestTemplate | None = None symbols: ComponentTestTemplate | None = None def __post_init__(self): if self.keycodes: self.keycodes = dataclasses.replace(self.keycodes, title="") if self.types: self.types = dataclasses.replace(self.types, title="") if self.compat: self.compat = dataclasses.replace(self.compat, title="") if self.symbols: self.symbols = dataclasses.replace(self.symbols, title="") def __iter__(self) -> Generator[ComponentTestTemplate]: def make_empty_template(component: Component) -> ComponentTestTemplate: return ComponentTestTemplate( title="", component=component, base_template=ComponentTemplate(""), update_template=ComponentTemplate(""), augment="", override="", ) yield self.keycodes or make_empty_template(Component.keycodes) yield self.types or make_empty_template(Component.types) yield self.compat or make_empty_template(Component.compat) yield self.symbols or make_empty_template(Component.symbols) def _generate_tests(self, compiler: XkbCompiler) -> Generator[Test]: groups = tuple( c.generate_tests(as_keymap=False, compiler=compiler) for c in self ) keycodes: Test types: Test compat: Test symbols: Test for keycodes, types, compat, symbols in zip(*(g.tests for g in groups)): title = self.title + keycodes.title file = keycodes.file content = KeymapTemplate.substitute( keycodes=textwrap.indent(keycodes.content, INDENT), types=textwrap.indent(types.content, INDENT), compat=textwrap.indent(compat.content, INDENT), symbols=textwrap.indent(symbols.content, INDENT), ) expected = KeymapTemplate.substitute( keycodes=textwrap.indent(keycodes.expected, INDENT), types=textwrap.indent(types.expected, INDENT), compat=textwrap.indent(compat.expected, INDENT), symbols=textwrap.indent(symbols.expected, INDENT), ) yield Test(title=title, file=file, content=content, expected=expected) def generate_tests(self, compiler: XkbCompiler) -> TestGroup: return TestGroup(self.title, tuple(self._generate_tests(compiler))) def _generate_data(self) -> Generator[Test]: for component in self: yield from component.generate_data().tests def generate_data(self) -> TestGroup: return TestGroup(self.title, tuple(self._generate_data())) @classmethod def write( cls, root: Path, jinja_env: jinja2.Environment, c_file: Path | None, xkb: bool, compiler: XkbCompiler, tests: Sequence[Self], debug: bool = False, ): if c_file is not None and c_file.name: c_data = tuple(t.generate_tests(compiler) for t in tests) TestGroup.write_c( root=root, jinja_env=jinja_env, path=c_file, compiler=compiler, tests=c_data, ) if xkb: xkb_data = tuple(t.generate_data() for t in tests) TestGroup.write_data(root=root, compiler=compiler, tests=xkb_data) ################################################################################ # # Key types tests # ################################################################################ TYPES_TESTS = ComponentTestTemplate( "Types", component=Component.types, base_template=ComponentTemplate( """ ${mode}virtual_modifiers NumLock, LevelThree=none, LevelFive=Mod3; ${mode}virtual_modifiers U1, U2, U3; // ${mode}virtual_modifiers U4, U5, U6; ${mode}virtual_modifiers Z1=none, Z2=none, Z3=none; // ${mode}virtual_modifiers Z4=none, Z5=none, Z6=none; ${mode}virtual_modifiers M1=0x1000, M2=0x2000, M3=0x3000; // ${mode}virtual_modifiers M4=0x4000, M5=0x5000, M6=0x6000; ${mode}type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; ${mode}type "TWO_LEVEL" { modifiers = Shift; map[Shift] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; ${mode}type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift] = Level2; map[Lock] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; ${mode}type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; ${mode}type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; ${mode}type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; ${mode}type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; ${mode}type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; map[Lock] = 2; map[LevelThree] = 3; level_name[1] = "1"; level_name[2] = "2"; level_name[3] = "3"; }; """ ), update_template=ComponentTemplate( """\ ${mode}virtual_modifiers NumLock=Mod2; // Changed: now mapped ${mode}virtual_modifiers LevelThree=Mod5; // Changed: altered mapping (from 0) ${mode}virtual_modifiers LevelFive=Mod3; // Unhanged: same mapping ${mode}virtual_modifiers U7, Z7=0, M7=0x700000; // Changed: new ${mode}virtual_modifiers U1; // Unchanged (unmapped) ${mode}virtual_modifiers U2 = none; // Changed: now mapped ${mode}virtual_modifiers U3 = 0x300000; // Changed: now mapped // ${mode}virtual_modifiers U4; // Unchanged (unmapped) // ${mode}virtual_modifiers U5 = none; // Changed: now mapped // ${mode}virtual_modifiers U6 = 0x600000; // Changed: now mapped ${mode}virtual_modifiers Z1; // Unchanged (= 0) ${mode}virtual_modifiers Z2 = none; // Unchanged (same mapping) ${mode}virtual_modifiers Z3 = 0x310000; // Changed: altered mapping (from 0) // ${mode}virtual_modifiers Z4; // Unchanged (= 0) // ${mode}virtual_modifiers Z5 = none; // Unchanged (same mapping) // ${mode}virtual_modifiers Z6 = 0x610000; // Changed: altered mapping (from 0) ${mode}virtual_modifiers M1; // Unchanged (≠ 0) ${mode}virtual_modifiers M2 = none; // Changed: reset ${mode}virtual_modifiers M3 = 0x320000; // Changed: altered mapping (from ≠ 0) // ${mode}virtual_modifiers M4; // Unchanged (≠ 0) // ${mode}virtual_modifiers M5 = none; // Changed: reset // ${mode}virtual_modifiers M6 = 0x620000; // Changed: altered mapping (from ≠ 0) ${mode}type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; // Change name }; ${mode}type "TWO_LEVEL" { modifiers = Shift+M1; // Changed map[Shift] = Level2; map[M1] = Level2; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; ${mode}type "ALPHABETIC" { modifiers = Lock; // Changed map[None] = Level2; // Changed map[Lock] = Level1; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; ${mode}type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; // Changed map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; // Unchanged ${mode}type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; ${mode}type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; ${mode}type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; ${mode}type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; // map[Lock] = 2; // Changed // map[LevelThree] = 3; map[LevelThree] = 1; // Changed map[Shift+LevelThree] = 4; // Changed level_name[1] = "A"; // Changed level_name[2] = "2"; level_name[3] = "3"; level_name[4] = "4"; // Changed }; // New ${mode}type "YYY" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; }; """ ), augment=""" virtual_modifiers NumLock=Mod2,LevelThree=none,LevelFive=Mod3; virtual_modifiers U1,U2=0,U3=0x300000; // virtual_modifiers U4,U5=0,U6=0x600000; virtual_modifiers Z1=0,Z2=0,Z3=0; // virtual_modifiers Z4=0,Z5=0,Z6=0; virtual_modifiers M1=0x1000,M2=0x2000,M3=0x3000; // virtual_modifiers M4=0x4000,M5=0x5000,M6=0x6000; virtual_modifiers U7,Z7=0,M7=0x700000; type "ONE_LEVEL" { modifiers= none; map[none]= 1; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[none]= 1; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[none]= 1; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[None]= 1; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; map[Lock] = 2; map[LevelThree] = 3; level_name[1] = "1"; level_name[2] = "2"; level_name[3] = "3"; }; type "YYY" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; }; """, override=""" virtual_modifiers NumLock=Mod2,LevelThree=Mod5,LevelFive=Mod3; virtual_modifiers U1,U2=0,U3=0x300000; // virtual_modifiers U4,U5=0,U6=0x600000; virtual_modifiers Z1=0,Z2=0,Z3=0x310000; // virtual_modifiers Z4=0,Z5=0,Z6=0x610000; virtual_modifiers M1=0x1000,M2=0,M3=0x320000; // virtual_modifiers M4=0x4000,M5=0,M6=0x620000; virtual_modifiers U7,Z7=0,M7=0x700000; type "ONE_LEVEL" { modifiers= none; map[None] = Level1; level_name[1]= "New"; }; type "TWO_LEVEL" { modifiers= Shift+M1; map[Shift]= 2; map[M1]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Lock; map[none]= 2; map[Lock]= 1; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift] = Level2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[None]= 1; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree] = Level4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[None]= 1; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; // map[LevelThree] = 3; map[LevelThree] = 1; map[Shift+LevelThree] = 4; level_name[1] = "A"; level_name[2] = "2"; level_name[3] = "3"; level_name[4] = "4"; }; type "YYY" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; }; """, ) ################################################################################ # # Compat tests # ################################################################################ COMPAT_TESTS = ComponentTestTemplate( "Compat", component=Component.compat, base_template=ComponentTemplate( """ ${mode}virtual_modifiers NumLock; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; ${mode}interpret Any + Any { action= SetMods(modifiers=modMapMods); }; ${mode}interpret Caps_Lock { action = LockMods(modifiers = Lock); }; ${mode}indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; ${mode}indicator "Num Lock" { !allowExplicit; whichModState= Locked; modifiers= NumLock; }; """ ), update_template=ComponentTemplate( """ ${mode}virtual_modifiers NumLock; ${mode}interpret.repeat= False; ${mode}setMods.clearLocks= False; // Changed // Unchanged ${mode}interpret Any + Any { action= SetMods(modifiers=modMapMods); }; // Changed ${mode}interpret Caps_Lock { action = LockMods(modifiers = NumLock); }; // Unchanged ${mode}indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; // Changed ${mode}indicator "Num Lock" { !allowExplicit; whichModState= Base; modifiers= Lock; }; // New ${mode}indicator "Kana" { !allowExplicit; whichModState= Locked; modifiers= Control; }; """ ), augment=""" virtual_modifiers NumLock; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Kana" { whichModState= locked; modifiers= Control; }; """, override=""" virtual_modifiers NumLock; interpret.repeat= False; setMods.clearLocks= False; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=NumLock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Kana" { whichModState= locked; modifiers= Control; }; indicator "Num Lock" { whichModState= base; modifiers= Lock; }; """, ) ################################################################################ # # Symbols tests # ################################################################################ LINUX_EVENT_CODES = ( None, "ESC", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "MINUS", "EQUAL", "BACKSPACE", "TAB", "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "LEFTBRACE", "RIGHTBRACE", "ENTER", "LEFTCTRL", "A", "S", "D", "F", "G", "H", "J", "K", "L", "SEMICOLON", "APOSTROPHE", "GRAVE", "LEFTSHIFT", "BACKSLASH", "Z", "X", "C", "V", "B", "N", "M", "COMMA", "DOT", "SLASH", "RIGHTSHIFT", "KPASTERISK", "LEFTALT", "SPACE", "CAPSLOCK", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "NUMLOCK", "SCROLLLOCK", "KP7", "KP8", "KP9", "KPMINUS", "KP4", "KP5", "KP6", "KPPLUS", "KP1", "KP2", "KP3", "KP0", "KPDOT", None, "ZENKAKUHANKAKU", "102ND", "F11", "F12", "RO", "KATAKANA", "HIRAGANA", "HENKAN", "KATAKANAHIRAGANA", "MUHENKAN", "KPJPCOMMA", "KPENTER", "RIGHTCTRL", "KPSLASH", "SYSRQ", "RIGHTALT", "LINEFEED", "HOME", "UP", "PAGEUP", "LEFT", "RIGHT", "END", "DOWN", "PAGEDOWN", "INSERT", "DELETE", "MACRO", "MUTE", "VOLUMEDOWN", "VOLUMEUP", "POWER", "KPEQUAL", "KPPLUSMINUS", "PAUSE", "SCALE", "KPCOMMA", "HANGEUL", "HANJA", "YEN", "LEFTMETA", "RIGHTMETA", "COMPOSE", "STOP", "AGAIN", "PROPS", "UNDO", "FRONT", "COPY", "OPEN", "PASTE", "FIND", "CUT", "HELP", "MENU", "CALC", "SETUP", "SLEEP", "WAKEUP", "FILE", "SENDFILE", "DELETEFILE", "XFER", "PROG1", "PROG2", "WWW", "MSDOS", "COFFEE", "DIRECTION", "CYCLEWINDOWS", "MAIL", "BOOKMARKS", "COMPUTER", "BACK", "FORWARD", "CLOSECD", "EJECTCD", "EJECTCLOSECD", "NEXTSONG", "PLAYPAUSE", "PREVIOUSSONG", "STOPCD", "RECORD", "REWIND", "PHONE", "ISO", "CONFIG", "HOMEPAGE", "REFRESH", "EXIT", "MOVE", "EDIT", "SCROLLUP", "SCROLLDOWN", "KPLEFTPAREN", "KPRIGHTPAREN", "NEW", "REDO", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24", None, None, None, None, None, "PLAYCD", "PAUSECD", "PROG3", "PROG4", "DASHBOARD", "SUSPEND", "CLOSE", "PLAY", "FASTFORWARD", "BASSBOOST", "PRINT", "HP", "CAMERA", "SOUND", "QUESTION", ) Comment = NewType("Comment", str) @dataclass(frozen=True) class KeyCode: _evdev: str _xkb: str @property def c(self) -> str: return f"KEY_{self._evdev}" @property def xkb(self) -> str: return f"<{self._xkb}>" class Keysym(str): @property def c(self) -> str: return f"XKB_KEY_{self}" @classmethod def parse(cls, raw: str | None) -> Self: if not raw: return cls("NoSymbol") else: return cls(raw) NoSymbol = Keysym("NoSymbol") class Modifier(IntFlag): NoModifier = 0 Shift = 1 << 0 Lock = 1 << 1 Control = 1 << 2 Mod1 = 1 << 3 Mod2 = 1 << 4 Mod3 = 1 << 5 Mod4 = 1 << 6 Mod5 = 1 << 7 LevelThree = Mod5 def __iter__(self) -> Iterator[Self]: for m in self.__class__: if m & self: yield m def __str__(self) -> str: return "+".join(m.name for m in self) class Action(metaclass=ABCMeta): @abstractmethod def __bool__(self) -> bool: ... @classmethod def parse(cls, raw: Any) -> Self: if raw is None: return GroupAction.parse(None) elif isinstance(raw, Modifier): return ModAction.parse(raw) elif isinstance(raw, int): return GroupAction.parse(raw) else: raise ValueError(raw) @abstractmethod def action_to_keysym(self, index: int, level: int) -> Keysym: ... @dataclass class GroupAction(Action): """ SetGroup or NoAction """ group: int keysyms: ClassVar[dict[tuple[int, int, int], Keysym]] = { (2, 0, 0): Keysym("a"), (2, 0, 1): Keysym("A"), (2, 1, 0): Keysym("b"), (2, 1, 1): Keysym("B"), (3, 0, 0): Keysym("Greek_alpha"), (3, 0, 1): Keysym("Greek_ALPHA"), (3, 1, 0): Keysym("Greek_beta"), (3, 1, 1): Keysym("Greek_BETA"), } def __str__(self) -> str: if self.group > 0: return f"SetGroup(group={self.group})" else: return "NoAction()" def __bool__(self) -> bool: return bool(self.group) @classmethod def parse(cls, raw: int | None) -> Self: if not raw: return cls(0) else: return cls(raw) def action_to_keysym(self, index: int, level: int) -> Keysym: if not self.group: return NoSymbol else: if ( keysym := self.keysyms.get((self.group % 4, index % 2, level % 2)) ) is None: raise ValueError((self, index, level)) return keysym @dataclass class ModAction(Action): """ SetMod or NoAction """ mods: Modifier keysyms: ClassVar[dict[tuple[Modifier, int, int], Keysym]] = { (Modifier.Control, 0, 0): Keysym("x"), (Modifier.Control, 0, 1): Keysym("X"), (Modifier.Control, 1, 0): Keysym("y"), (Modifier.Control, 1, 1): Keysym("Y"), (Modifier.Mod5, 0, 0): Keysym("Greek_xi"), (Modifier.Mod5, 0, 1): Keysym("Greek_XI"), (Modifier.Mod5, 1, 0): Keysym("Greek_upsilon"), (Modifier.Mod5, 1, 1): Keysym("Greek_UPSILON"), } def __str__(self) -> str: if self.mods is Modifier.NoModifier: return "NoAction()" else: return f"SetMods(mods={self.mods})" def __bool__(self) -> bool: return self.mods is Modifier.NoModifier @classmethod def parse(cls, raw: Modifier | None) -> Self: if not raw: return cls(Modifier.NoModifier) else: return cls(raw) def action_to_keysym(self, index: int, level: int) -> Keysym: if self.mods is Modifier.NoModifier: return NoSymbol else: if (keysym := self.keysyms.get((self.mods, index % 2, level % 2))) is None: raise ValueError((self, index, level)) return keysym @dataclass class Level: keysyms: tuple[Keysym, ...] actions: tuple[Action, ...] @staticmethod def _c(default: str, xs: Iterable[Any]) -> str: match len(xs): case 0: return default case 1: return xs[0].c case _: return ", ".join(map(lambda x: x.c, xs)) @staticmethod def _xkb(default: str, xs: Iterable[Any]) -> str: match len(xs): case 0: return default case 1: return str(xs[0]) case _: return "{" + ", ".join(map(str, xs)) + "}" @classmethod def has_empty_symbols(cls, keysyms: tuple[Keysym, ...]) -> bool: return all(ks == NoSymbol for ks in keysyms) @property def empty_symbols(self) -> bool: return self.has_empty_symbols(self.keysyms) @property def keysyms_c(self) -> str: if not self.keysyms and self.actions: return self._c( NoSymbol.c, tuple(itertools.repeat(NoSymbol, len(self.actions))) ) return self._c(NoSymbol.c, self.keysyms) @property def keysyms_xkb(self) -> str: return self._xkb(NoSymbol, self.keysyms) @classmethod def has_empty_actions(cls, actions: tuple[Action, ...]) -> bool: return not any(actions) @property def empty_actions(self) -> bool: return self.has_empty_actions(self.actions) @property def actions_xkb(self) -> str: return self._xkb("NoAction()", self.actions) @classmethod def Keysyms(cls, *keysyms: str | None) -> Self: return cls.Mix(keysyms, ()) @classmethod def Actions(cls, *actions: int | Modifier | None) -> Self: return cls.Mix((), actions) @classmethod def Mix( cls, keysyms: tuple[str | None, ...], actions: tuple[int | Modifier | None,] ) -> Self: return cls(tuple(map(Keysym.parse, keysyms)), tuple(map(Action.parse, actions))) def add_keysyms(self, keep_actions: bool, level: int) -> Self: return self.__class__( keysyms=tuple( a.action_to_keysym(index=k, level=level) for k, a in enumerate(self.actions) ), actions=self.actions if keep_actions else (), ) @property def target_group(self) -> int: for a in self.actions: if isinstance(a, GroupAction) and a.group > 1: return a.group else: return 0 @property def target_level(self) -> int: for a in self.actions: if isinstance(a, ModAction) and a.mods: match a.mods: case Modifier.LevelThree: return 2 case _: return 0 else: return 0 @dataclass class KeyEntry: levels: tuple[Level, ...] def __init__(self, *levels: Level): self.levels = levels @property def xkb(self) -> Iterator[str]: if not self.levels: yield "" return keysyms = tuple(l.keysyms for l in self.levels) has_keysyms = any(not Level.has_empty_symbols(s) for s in keysyms) no_keysyms = all(not s for s in keysyms) actions = tuple(l.actions for l in self.levels) has_actions = any(not Level.has_empty_actions(a) for a in actions) if has_keysyms or (not no_keysyms and not has_actions): yield "[" yield ", ".join(l.keysyms_xkb for l in self.levels) yield "]" if has_actions or no_keysyms: if has_keysyms: yield ", " yield "[" yield ", ".join(l.actions_xkb for l in self.levels) yield "]" def add_keysyms(self, keep_actions: bool) -> Self: return self.__class__( *( l.add_keysyms(keep_actions=keep_actions, level=k) for k, l in enumerate(self.levels) ) ) class TestType(IntFlag): KeysymsOnly = auto() ActionsOnly = auto() KeysymsAndActions = auto() All = ActionsOnly | KeysymsOnly | KeysymsAndActions @dataclass class TestId: type: TestType base: int = 0 _last_base: ClassVar[int] = 0 _max_type: ClassVar[int] = TestType.KeysymsAndActions >> 1 _forbidden_keys: tuple[str, ...] = ("LEFTSHIFT", "RIGHTALT") def __post_init__(self): if self.base == -1: self.base = self.__class__._last_base elif self.base < 0: raise ValueError(self.base) elif self.base == 0: self.__class__._last_base += 1 self.base = self.__class__._last_base while not self.check_linux_keys(self._base_id): self.__class__._last_base += 1 self.base = self.__class__._last_base else: self.__class__._last_base = max(self.__class__._last_base, self.base) assert self.linux_key, self # print(self.base, self.id, self.xkb_key) def __hash__(self) -> int: return self.id @property def _base_id(self) -> int: return (self.base - 1) * (self._max_type + 1) + 1 @property def id(self) -> int: # return (self.base << 2) | (self.type >> 1) return self._base_id + (self.type >> 1) def with_type(self, type: TestType) -> Self: return dataclasses.replace(self, type=type) @property def xkb_key(self) -> str: return f"T{self.id:0>3}" @classmethod def check_linux_key(cls, idx: int) -> bool: if idx >= len(LINUX_EVENT_CODES): raise ValueError("Not enough Linux keys available!") key: str | None = LINUX_EVENT_CODES[idx] return bool(key) and key not in cls._forbidden_keys @classmethod def check_linux_keys(cls, base_id) -> bool: return all( cls.check_linux_key(base_id + k) for k in range(0, cls._max_type + 1) ) @property def linux_key(self) -> str: if self.id >= len(LINUX_EVENT_CODES): raise ValueError("Not enough Linux keys available!") return LINUX_EVENT_CODES[self.id] @property def key(self) -> KeyCode: return KeyCode(self.linux_key, self.xkb_key) @unique class Implementation(Flag): x11 = auto() xkbcommon = auto() all = x11 | xkbcommon @dataclass class TestEntry: id: TestId key: KeyCode = dataclasses.field(init=False) base: KeyEntry update: KeyEntry augment: KeyEntry override: KeyEntry replace: KeyEntry types: TestType implementations: Implementation group_keysyms: ClassVar[tuple[tuple[str, str], ...]] = ( ("Ukrainian_i", "Ukrainian_I", "Ukrainian_yi", "Ukrainian_YI"), ("ch", "Ch", "c_h", "C_h"), ) def __init__( self, id: TestId | None, base: KeyEntry, update: KeyEntry, augment: KeyEntry, override: KeyEntry, types: TestType = TestType.All, replace: KeyEntry | None = None, implementations: Implementation = Implementation.all, ): self.id = TestId(0, 0) if id is None else id self.key = id.key self.base = base self.update = update self.augment = augment self.override = override self.types = types self.replace = self.update if replace is None else replace self.implementations = implementations @property def default(self) -> KeyEntry: return self.override def add_keysyms(self, keep_actions: bool) -> Self: types = TestType.KeysymsAndActions if keep_actions else TestType.KeysymsOnly return dataclasses.replace( self, id=self.id.with_type(types), base=self.base.add_keysyms(keep_actions=keep_actions), update=self.update.add_keysyms(keep_actions=keep_actions), augment=self.augment.add_keysyms(keep_actions=keep_actions), override=self.override.add_keysyms(keep_actions=keep_actions), replace=self.replace.add_keysyms(keep_actions=keep_actions), types=types, ) @classmethod def alt_keysym(cls, group: int, level: int) -> Keysym: return Keysym(cls.group_keysyms[group % 2][level % 4]) @classmethod def alt_keysyms(cls, group: int) -> Iterator[Keysym]: for keysym in cls.group_keysyms[group % 2]: yield Keysym(keysym) @dataclass class SymbolsTestGroup: name: str tests: tuple[TestEntry | Comment, ...] def _with_implementation( self, implementation: Implementation ) -> Iterable[TestEntry | Comment]: pending_comment: Comment | None = None for t in self.tests: if not isinstance(t, TestEntry): pending_comment = t elif t.implementations & implementation: if pending_comment is not None: yield pending_comment pending_comment = None yield t def with_implementation(self, implementation: Implementation) -> Self: return dataclasses.replace( self, tests=tuple(self._with_implementation(implementation)) ) @staticmethod def _add_keysyms(entry: TestEntry | Comment) -> Iterable[TestEntry | Comment]: if isinstance(entry, TestEntry) and entry.id.type is TestType.ActionsOnly: if entry.types & TestType.KeysymsOnly: yield entry.add_keysyms(keep_actions=False) yield entry if entry.types & TestType.KeysymsAndActions: yield entry.add_keysyms(keep_actions=True) else: yield entry def add_keysyms(self, name: str = "") -> Self: return dataclasses.replace( self, name=name or self.name, tests=tuple(t for ts in self.tests for t in self._add_keysyms(ts)), ) def __add__(self, other: Any) -> Self: if isinstance(other, tuple): return dataclasses.replace(self, tests=self.tests + other) elif isinstance(other, self.__class__): return dataclasses.replace(self, tests=self.tests + other.tests) else: return NotImplemented def get_keycodes(self, base: ComponentTestTemplate) -> ComponentTestTemplate: ids: set[TestId] = set(t.id for t in self.tests if isinstance(t, TestEntry)) base_template = Template( "\n".join(f"${{mode}}<{id.xkb_key}> = {id.id + 8};" for id in ids) + "\n" ) keycodes = base_template.substitute(mode="") return dataclasses.replace( base, base_template=base_template + base.base_template, update_template=base.update_template, augment=keycodes + base.augment, override=keycodes + base.override, replace=keycodes + base.replace, ) def _get_symbols(self, type: str, debug: bool) -> Generator[str]: for entry in self.tests: if isinstance(entry, str): if type == "update": yield f"\n////// {entry} //////" else: data: KeyEntry = getattr(entry, type) if debug: yield f"// base: {''.join(entry.base.xkb) or '(empty)'}" yield "// key to merge / replace result" yield f"${{mode}}key {entry.key.xkb} {{ {''.join(data.xkb)} }};" if debug: yield f"// override: {''.join(entry.override.xkb) or '(empty)'}" yield f"// augment: {''.join(entry.augment.xkb) or '(empty)'}" def get_symbols(self, debug: bool = False) -> ComponentTestTemplate: base_template = ComponentTemplate("\n".join(self._get_symbols("base", False))) update_template = ComponentTemplate( "\n".join(self._get_symbols("update", debug)) ) augment = ComponentTemplate( "\n".join(self._get_symbols("augment", False)) ).substitute(mode="") override = ComponentTemplate( "\n".join(self._get_symbols("override", False)) ).substitute(mode="") replace = ComponentTemplate( "\n".join(self._get_symbols("replace", False)) ).substitute(mode="") return ComponentTestTemplate( title=self.name, component=Component.symbols, base_template=base_template, update_template=update_template, augment=augment, override=override, replace=replace, ) SYMBOLS_TESTS_BOTH = SymbolsTestGroup( "", ( Comment("Trivial cases"), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(), update=KeyEntry(), augment=KeyEntry(), override=KeyEntry(), ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(), update=KeyEntry(Level.Actions(3)), augment=KeyEntry(Level.Actions(3)), override=KeyEntry(Level.Actions(3)), ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2)), update=KeyEntry(), augment=KeyEntry(Level.Actions(2)), override=KeyEntry(Level.Actions(2)), ), Comment("Same key"), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2)), update=KeyEntry(Level.Actions(2)), augment=KeyEntry(Level.Actions(2)), override=KeyEntry(Level.Actions(2)), ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), update=KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), augment=KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), override=KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), implementations=Implementation.xkbcommon, ), Comment("Mismatch levels count"), ( TEST_BOTH_Q := TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(2)), update=KeyEntry( Level.Actions(3), Level.Actions(None), Level.Actions(None) ), augment=KeyEntry( Level.Actions(3), Level.Actions(2), Level.Actions(None) ), override=KeyEntry( Level.Actions(3), Level.Actions(2), Level.Actions(None) ), # X11 and xkbcommon handle keysyms-only case differently types=TestType.ActionsOnly | TestType.KeysymsAndActions, ) ), # Trailing NoSymbols are discarded in xkbcomp dataclasses.replace( TEST_BOTH_Q, augment=KeyEntry(Level.Actions(3), Level.Actions(2)), override=KeyEntry(Level.Actions(3), Level.Actions(2)), replace=KeyEntry(Level.Actions(3)), implementations=Implementation.x11, ).add_keysyms(keep_actions=False), dataclasses.replace( TEST_BOTH_Q, implementations=Implementation.xkbcommon ).add_keysyms(keep_actions=False), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(2)), update=KeyEntry(Level.Actions(3), Level.Actions(None), Level.Actions(None)), augment=KeyEntry(Level.Actions(3), Level.Actions(2), Level.Actions(None)), override=KeyEntry(Level.Actions(3), Level.Actions(2), Level.Actions(None)), # X11 and xkbcommon handle keysyms-only case differently types=TestType.ActionsOnly | TestType.KeysymsAndActions, ), ( TEST_BOTH_W := TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(2), Level.Actions(None)), update=KeyEntry(Level.Actions(3), Level.Actions(None)), augment=KeyEntry( Level.Actions(3), Level.Actions(2), Level.Actions(None) ), override=KeyEntry( Level.Actions(3), Level.Actions(2), Level.Actions(None) ), # X11 and xkbcommon handle keysyms-only case differently types=TestType.ActionsOnly | TestType.KeysymsAndActions, ) ), dataclasses.replace( TEST_BOTH_W, augment=KeyEntry(Level.Actions(3), Level.Actions(2)), override=KeyEntry(Level.Actions(3), Level.Actions(2)), replace=KeyEntry(Level.Actions(3)), implementations=Implementation.x11, ).add_keysyms(keep_actions=False), dataclasses.replace( TEST_BOTH_W, implementations=Implementation.xkbcommon ).add_keysyms(keep_actions=False), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(3), Level.Actions(3), Level.Actions(3)), augment=KeyEntry(Level.Actions(2), Level.Actions(2), Level.Actions(3)), override=KeyEntry(Level.Actions(3), Level.Actions(3), Level.Actions(3)), ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(3), Level.Actions(3)), augment=KeyEntry(Level.Actions(2), Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(3), Level.Actions(3), Level.Actions(2)), ), Comment("Single keysyms -> single keysyms"), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(None), Level.Actions(None)), augment=KeyEntry(Level.Actions(None), Level.Actions(None)), override=KeyEntry(Level.Actions(None), Level.Actions(None)), ), ( TEST_BOTH_Y := TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(3), Level.Actions(None)), augment=KeyEntry(Level.Actions(3), Level.Actions(None)), override=KeyEntry(Level.Actions(3), Level.Actions(None)), # X11 and xkbcommon handle keysyms-only case differently types=TestType.ActionsOnly | TestType.KeysymsAndActions, ) ), dataclasses.replace( TEST_BOTH_Y, augment=KeyEntry(Level.Actions(3)), override=KeyEntry(Level.Actions(3)), replace=KeyEntry(Level.Actions(3)), implementations=Implementation.x11, ).add_keysyms(keep_actions=False), dataclasses.replace( TEST_BOTH_Y, implementations=Implementation.xkbcommon ).add_keysyms(keep_actions=False), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(None), Level.Actions(3)), augment=KeyEntry(Level.Actions(None), Level.Actions(3)), override=KeyEntry(Level.Actions(None), Level.Actions(3)), ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(3), Level.Actions(3)), augment=KeyEntry(Level.Actions(3), Level.Actions(3)), override=KeyEntry(Level.Actions(3), Level.Actions(3)), ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(None), Level.Actions(None)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(2), Level.Actions(2)), ), ( TEST_BOTH_P := TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(3), Level.Actions(None)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(3), Level.Actions(2)), # X11 and xkbcommon handle keysyms-only case differently types=TestType.ActionsOnly | TestType.KeysymsAndActions, ) ), dataclasses.replace( TEST_BOTH_P, augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(3), Level.Actions(2)), replace=KeyEntry(Level.Actions(3)), implementations=Implementation.x11, ).add_keysyms(keep_actions=False), dataclasses.replace( TEST_BOTH_P, implementations=Implementation.xkbcommon ).add_keysyms(keep_actions=False), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(None), Level.Actions(3)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(2), Level.Actions(3)), ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(3), Level.Actions(3)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(3), Level.Actions(3)), ), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Keysyms("a"), Level.Actions(2)), update=KeyEntry(Level.Actions(3), Level.Keysyms("X")), augment=KeyEntry(Level.Mix(("a"), (3,)), Level.Mix(("X",), (2,))), override=KeyEntry(Level.Mix(("a"), (3,)), Level.Mix(("X",), (2,))), ), Comment("Single keysyms -> multiple keysyms"), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(3, None), Level.Actions(None)), augment=KeyEntry(Level.Actions(3, None), Level.Actions(None)), override=KeyEntry(Level.Actions(3, None), Level.Actions(None)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(3, None), Level.Actions(None, None)), augment=KeyEntry(Level.Actions(3, None), Level.Actions(None)), override=KeyEntry(Level.Actions(3, None), Level.Actions(None)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(None), Level.Actions(3, None)), augment=KeyEntry(Level.Actions(None), Level.Actions(3, None)), override=KeyEntry(Level.Actions(None), Level.Actions(3, None)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(None, None), Level.Actions(3, None)), augment=KeyEntry(Level.Actions(None), Level.Actions(3, None)), override=KeyEntry(Level.Actions(None), Level.Actions(3, None)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), augment=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), override=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None), Level.Actions(None)), update=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), augment=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), override=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(3, None), Level.Actions(None)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(3, None), Level.Actions(2)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(3, None), Level.Actions(None, None)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(3, None), Level.Actions(2)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(None), Level.Actions(3, None)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(2), Level.Actions(3, None)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(None, None), Level.Actions(3, None)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(2), Level.Actions(3, None)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2), Level.Actions(2)), update=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), augment=KeyEntry(Level.Actions(2), Level.Actions(2)), override=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), implementations=Implementation.xkbcommon, ), Comment("Multiple keysyms -> multiple keysyms"), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None, None), Level.Actions(None, None)), update=KeyEntry( Level.Actions(None, None), Level.Actions(3, Modifier.LevelThree) ), augment=KeyEntry( Level.Actions(None, None), Level.Actions(3, Modifier.LevelThree) ), override=KeyEntry( Level.Actions(None, None), Level.Actions(3, Modifier.LevelThree) ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None, None), Level.Actions(None, None)), update=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), augment=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), override=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None, None), Level.Actions(2, Modifier.Control)), update=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), augment=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(2, Modifier.Control), ), override=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), update=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), augment=KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), override=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), update=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(Modifier.LevelThree, 3), ), augment=KeyEntry( Level.Actions(2, None), Level.Actions(None, 2), ), override=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(Modifier.LevelThree, 3), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(2, Modifier.Control) ), update=KeyEntry( Level.Actions(None, None), Level.Actions(3, Modifier.LevelThree) ), augment=KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(2, Modifier.Control) ), override=KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(3, Modifier.LevelThree), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, 2) ), update=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), augment=KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, 2) ), override=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None, None), Level.Actions(None, None, None)), update=KeyEntry(Level.Actions(None, None, None), Level.Actions(None, None)), augment=KeyEntry( Level.Actions(None, None), Level.Actions(None, None, None) ), override=KeyEntry( Level.Actions(None, None), Level.Actions(None, None, None) ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None, None), Level.Actions(None, None, None)), update=KeyEntry( Level.Actions(3, None, Modifier.LevelThree), Level.Actions(Modifier.LevelThree, 3), ), augment=KeyEntry( Level.Actions(3, None, Modifier.LevelThree), Level.Actions(Modifier.LevelThree, 3), ), override=KeyEntry( Level.Actions(3, None, Modifier.LevelThree), Level.Actions(Modifier.LevelThree, 3), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, None, 2), ), update=KeyEntry(Level.Actions(None, None, None), Level.Actions(None, None)), augment=KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, None, 2), ), override=KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, None, 2), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, None, 2), ), update=KeyEntry( Level.Actions(3, None, Modifier.LevelThree), Level.Actions(Modifier.LevelThree, 3), ), augment=KeyEntry( Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, None, 2), ), override=KeyEntry( Level.Actions(3, None, Modifier.LevelThree), Level.Actions(Modifier.LevelThree, 3), ), implementations=Implementation.xkbcommon, ), Comment("Multiple keysyms -> single keysyms"), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None, None), Level.Actions(2, Modifier.Control)), update=KeyEntry(Level.Actions(None), Level.Actions(None)), augment=KeyEntry( Level.Actions(None, None), Level.Actions(2, Modifier.Control) ), override=KeyEntry( Level.Actions(None, None), Level.Actions(2, Modifier.Control) ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(None, None), Level.Actions(2, Modifier.Control)), update=KeyEntry(Level.Actions(3), Level.Actions(3)), augment=KeyEntry(Level.Actions(3), Level.Actions(2, Modifier.Control)), override=KeyEntry(Level.Actions(3), Level.Actions(3)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), update=KeyEntry(Level.Actions(None), Level.Actions(None)), augment=KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), override=KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.ActionsOnly), KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), update=KeyEntry(Level.Actions(3), Level.Actions(3)), augment=KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), override=KeyEntry(Level.Actions(3), Level.Actions(3)), implementations=Implementation.xkbcommon, ), Comment("Mix"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Actions(2)), update=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), augment=KeyEntry(Level.Actions(2), Level.Actions(3, Modifier.LevelThree)), override=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3, Modifier.LevelThree), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Actions(2, Modifier.Control)), update=KeyEntry(Level.Actions(3, Modifier.LevelThree), Level.Actions(3)), augment=KeyEntry(Level.Actions(2, Modifier.Control), Level.Actions(3)), override=KeyEntry(Level.Actions(3, Modifier.LevelThree), Level.Actions(3)), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), update=KeyEntry(Level.Actions(3, Modifier.LevelThree), Level.Actions(3)), augment=KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), override=KeyEntry(Level.Actions(3, Modifier.LevelThree), Level.Actions(3)), implementations=Implementation.xkbcommon, ), Comment("Mix"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Keysyms("a"), Level.Actions(2)), update=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Keysyms("X", "Y") ), augment=KeyEntry( Level.Mix(("a",), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (2,)), ), override=KeyEntry( Level.Mix(("a",), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (2,)), ), implementations=Implementation.xkbcommon, ), Comment("Multiple keysyms/actions –> single"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Keysyms("a", "b"), Level.Actions(2, Modifier.Control)), update=KeyEntry(Level.Actions(3), Level.Keysyms("X")), augment=KeyEntry( Level.Mix(("a", "b"), (3,)), Level.Mix(("X",), (2, Modifier.Control)), ), override=KeyEntry( Level.Mix(("a", "b"), (3,)), Level.Mix(("X",), (2, Modifier.Control)), ), implementations=Implementation.xkbcommon, ), Comment("Multiple keysyms/actions –> multiple (xor)"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Keysyms("a", "b"), Level.Actions(2, Modifier.Control)), update=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Keysyms("X", "Y") ), augment=KeyEntry( Level.Mix(("a", "b"), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (2, Modifier.Control)), ), override=KeyEntry( Level.Mix(("a", "b"), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (2, Modifier.Control)), ), implementations=Implementation.xkbcommon, ), Comment("Multiple keysyms/actions –> multiple (mix)"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Keysyms("a", None), Level.Actions(2, None)), update=KeyEntry( Level.Mix(("x", "y"), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (3, Modifier.LevelThree)), ), augment=KeyEntry( Level.Mix(("a", None), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (2, None)), ), override=KeyEntry( Level.Mix(("x", "y"), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (3, Modifier.LevelThree)), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Keysyms("a", "b"), Level.Actions(2, Modifier.Control)), update=KeyEntry( Level.Mix(("x", None), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (3, None)), ), augment=KeyEntry( Level.Mix(("a", "b"), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (2, Modifier.Control)), ), override=KeyEntry( Level.Mix(("x", None), (3, Modifier.LevelThree)), Level.Mix(("X", "Y"), (3, None)), ), implementations=Implementation.xkbcommon, ), Comment("Multiple (mix) –> multiple keysyms/actions"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry( Level.Mix(("a", "b"), (2, Modifier.Control)), Level.Mix(("A", "B"), (2, Modifier.Control)), ), update=KeyEntry(Level.Keysyms("x", None), Level.Actions(3, None)), augment=KeyEntry( Level.Mix(("a", "b"), (2, Modifier.Control)), Level.Mix(("A", "B"), (2, Modifier.Control)), ), override=KeyEntry( Level.Mix(("x", None), (2, Modifier.Control)), Level.Mix(("A", "B"), (3, None)), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry( Level.Mix(("a", None), (2, Modifier.Control)), Level.Mix(("A", "B"), (2, None)), ), update=KeyEntry( Level.Keysyms("x", "y"), Level.Actions(3, Modifier.LevelThree) ), augment=KeyEntry( Level.Mix(("a", None), (2, Modifier.Control)), Level.Mix(("A", "B"), (2, None)), ), override=KeyEntry( Level.Mix(("x", "y"), (2, Modifier.Control)), Level.Mix(("A", "B"), (3, Modifier.LevelThree)), ), implementations=Implementation.xkbcommon, ), Comment("Multiple (mix) –> multiple (mix)"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry( Level.Mix(("a", "b"), (2, Modifier.Control)), Level.Mix((None, "B"), (2, None)), ), update=KeyEntry( Level.Mix((None, "y"), (3, None)), Level.Mix(("X", "Y"), (3, Modifier.LevelThree)), ), augment=KeyEntry( Level.Mix(("a", "b"), (2, Modifier.Control)), Level.Mix((None, "B"), (2, None)), ), override=KeyEntry( Level.Mix((None, "y"), (3, None)), Level.Mix(("X", "Y"), (3, Modifier.LevelThree)), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry( Level.Mix(("a", None), (2, None)), Level.Mix((None, "B"), (None, Modifier.Control)), ), update=KeyEntry( Level.Mix((None, "y"), (None, Modifier.LevelThree)), Level.Mix(("X", None), (3, None)), ), augment=KeyEntry( Level.Mix(("a", None), (2, None)), Level.Mix((None, "B"), (None, Modifier.Control)), ), override=KeyEntry( Level.Mix((None, "y"), (None, Modifier.LevelThree)), Level.Mix(("X", None), (3, None)), ), implementations=Implementation.xkbcommon, ), Comment("Mismatch count with mix"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry( Level.Keysyms("a"), Level.Keysyms("A", "B"), ), update=KeyEntry( Level.Actions(3, Modifier.LevelThree), Level.Actions(3), ), augment=KeyEntry( Level.Mix(("a"), (3, Modifier.LevelThree)), Level.Mix(("A", "B"), (3,)), ), override=KeyEntry( Level.Mix(("a"), (3, Modifier.LevelThree)), Level.Mix(("A", "B"), (3,)), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry( Level.Actions(3), Level.Actions(3, Modifier.LevelThree), ), update=KeyEntry( Level.Keysyms("A", "B"), Level.Keysyms("a"), ), augment=KeyEntry( Level.Mix(("A", "B"), (3,)), Level.Mix(("a"), (3, Modifier.LevelThree)), ), override=KeyEntry( Level.Mix(("A", "B"), (3,)), Level.Mix(("a"), (3, Modifier.LevelThree)), ), implementations=Implementation.xkbcommon, ), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry( Level.Mix(("a",), (2,)), Level.Mix(("A", "B"), (2, Modifier.Control)), ), update=KeyEntry( Level.Mix(("x", "y"), (3, Modifier.LevelThree)), Level.Mix(("X",), (3,)), ), augment=KeyEntry( Level.Mix(("a",), (2,)), Level.Mix(("A", "B"), (2, Modifier.Control)), ), override=KeyEntry( Level.Mix(("x", "y"), (3, Modifier.LevelThree)), Level.Mix(("X",), (3,)), ), implementations=Implementation.xkbcommon, ), Comment("Issue #564"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Keysyms("A")), update=KeyEntry(Level.Mix(("A", "A"), (3, Modifier.LevelThree))), augment=KeyEntry(Level.Mix(("A",), (3, Modifier.LevelThree))), override=KeyEntry(Level.Mix(("A", "A"), (3, Modifier.LevelThree))), implementations=Implementation.xkbcommon, ), Comment("Drop NoSymbol/NoAction"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Mix(("A",), (2,))), update=KeyEntry(Level.Mix((None, "Y", None), (None, 3, None))), augment=KeyEntry(Level.Mix(("A",), (2,))), override=KeyEntry(Level.Mix(("Y",), (3,))), implementations=Implementation.xkbcommon, ), Comment("Drop NoSymbol/NoAction and invalid keysyms"), TestEntry( TestId(TestType.KeysymsAndActions), KeyEntry(Level.Mix(("notAKeysym", None, "thisEither"), (None, None))), update=KeyEntry(Level.Mix((None, None), (None, None))), augment=KeyEntry(Level.Keysyms(None)), override=KeyEntry(Level.Keysyms(None)), replace=KeyEntry(Level.Keysyms(None)), implementations=Implementation.xkbcommon, ), ), ).add_keysyms() ################################################################################ # # Keycodes tests # ################################################################################ KEYCODES_TESTS_BASE = ComponentTestTemplate( "Keycodes", component=Component.keycodes, base_template=ComponentTemplate( """ ${mode}<1> = 241; ${mode}<2> = 242; ${mode}alias = <1>; ${mode}alias = <2>; ${mode}indicator 1 = "Caps Lock"; ${mode}indicator 2 = "Num Lock"; ${mode}indicator 3 = "Scroll Lock"; ${mode}indicator 4 = "Compose"; ${mode}indicator 5 = "Kana"; """ ), update_template=ComponentTemplate( """ ${mode}<1> = 241; // Unchanged ${mode}<2> = 244; // Changed ${mode}<3> = 243; // New ${mode}alias = <1>; // Unchanged ${mode}alias = <3>; // Changed ${mode}alias = <3>; // New ${mode}indicator 1 = "Caps Lock"; // Unchanged ${mode}indicator 6 = "Num Lock"; // Changed index (free) ${mode}indicator 5 = "Scroll Lock"; // Changed index (not free) ${mode}indicator 4 = "XXXX"; // Changed name ${mode}indicator 7 = "Suspend"; // New """ ), augment=""" <1> = 241; <2> = 242; <3> = 243; alias = <1>; alias = <2>; alias = <3>; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 7 = "Suspend"; """, override=""" <1> = 241; <2> = 244; <3> = 243; alias = <1>; alias = <3>; alias = <3>; indicator 1 = "Caps Lock"; indicator 4 = "XXXX"; indicator 5 = "Scroll Lock"; indicator 6 = "Num Lock"; indicator 7 = "Suspend"; """, ) ################################################################################ # # Main # ################################################################################ if __name__ == "__main__": # Parse commands parser = argparse.ArgumentParser(description="Generate merge mode tests") parser.add_argument( "compiler", type=XkbCompiler.parse, nargs="?", default="xkbcommon", help="XKB compiler to use", ) parser.add_argument( "--root", type=Path, default=ROOT, help="Path to the root of the project (default: %(default)s)", ) parser.add_argument( "--c-out", type=Path, # default=ROOT / TestGroup.c_template.stem, help="Path to the output C test file (default: %(default)s)", ) parser.add_argument("--no-xkb", action="store_true", help="Do not update XKB data") parser.add_argument("--debug", action="store_true", help="Activate debug mode") args = parser.parse_args() # Prepare data template_loader = jinja2.FileSystemLoader(args.root, encoding="utf-8") jinja_env = jinja2.Environment( loader=template_loader, keep_trailing_newline=True, trim_blocks=True, lstrip_blocks=True, ) def escape_quotes(s: str) -> str: return s.replace('"', '\\"') jinja_env.filters["escape_quotes"] = escape_quotes compiler: XkbCompiler = args.compiler SYMBOLS_TESTS = SYMBOLS_TESTS_BOTH.with_implementation( Implementation.xkbcommon if compiler.extended_syntax else Implementation.x11 ) KEYCODES_TESTS = SYMBOLS_TESTS.get_keycodes(KEYCODES_TESTS_BASE) TESTS = ( KeymapTestTemplate( title="", keycodes=KEYCODES_TESTS, types=TYPES_TESTS, compat=COMPAT_TESTS, symbols=SYMBOLS_TESTS.get_symbols(debug=args.debug), ), ) # Write tests TESTS[0].write( root=args.root, jinja_env=jinja_env, c_file=args.c_out, xkb=not args.no_xkb, compiler=compiler, tests=TESTS, ) xkbcommon-libxkbcommon-54ee7ac/scripts/update-message-registry.py000077500000000000000000000222451510033435100255060ustar00rootroot00000000000000#!/usr/bin/env python3 from __future__ import annotations import argparse import random import re from dataclasses import astuple, dataclass from pathlib import Path from typing import Any, Callable, ClassVar, Generic, Sequence, TypeAlias, TypeVar import jinja2 import yaml @dataclass(order=True) class Version: """A semantic version number: MAJOR.MINOR.PATCH.""" UNKNOWN_VERSION: ClassVar[str] = "ALWAYS" DEFAULT_VERSION: ClassVar[str] = "1.0.0" major: int minor: int patch: int = 0 def __str__(self) -> str: return ".".join(map(str, astuple(self))) @classmethod def parse(cls, raw_version: str) -> Version: if raw_version == cls.UNKNOWN_VERSION: raw_version = cls.DEFAULT_VERSION version = raw_version.split(".") assert 2 <= len(version) <= 3 and all(n.isdecimal() for n in version), ( raw_version ) return Version(*map(int, version)) @dataclass class Example: """An example in a message entry.""" name: str description: str before: str | None after: str | None @classmethod def parse(cls, entry: dict[str, Any]) -> Example: name = entry.get("name") assert name, entry description = entry.get("description") assert description before = entry.get("before") after = entry.get("after") # Either none or both of them assert not (bool(before) ^ bool(after)) return Example(name=name, description=description, before=before, after=after) @dataclass class Entry: """An xkbcommon message entry in the message registry""" VALID_TYPES = ("warning", "error") code: int """A unique strictly positive integer identifier""" id: str """A unique short human-readable string identifier""" type: str """Log level of the message""" description: str """A short description of the meaning of the message""" details: str """A long description of the meaning of the message""" added: Version """Version of xkbcommon the message has been added""" removed: Version | None """Version of xkbcommon the message has been removed""" examples: tuple[Example, ...] """ Optional examples of situations in which the message occurs. If the message is an error or a warning, also provide hints on how to fix it. """ @classmethod def parse(cls, entry: dict[str, Any]) -> Entry: code = entry.get("code") assert code is not None and isinstance(code, int) and code > 0, entry id = entry.get("id") assert id is not None, entry type_ = entry.get("type") assert type_ in cls.VALID_TYPES, entry description = entry.get("description") assert description is not None, entry details = entry.get("details", "") raw_added = entry.get("added", "") assert raw_added, entry added = Version.parse(raw_added) assert added, entry if removed := entry.get("removed"): removed = Version.parse(removed) assert added < removed, entry if examples := entry.get("examples", ()): examples = tuple(map(Example.parse, examples)) return Entry( code=code, id=id, type=type_, description=description, added=added, removed=removed, details=details, examples=examples, ) @property def message_code(self) -> str: """Format the message code for display""" return f"XKB-{self.code:0>3}" @property def message_code_constant(self: Entry) -> str: """Returns the C enumeration member denoting the message code""" id = self.id.replace("-", "_").upper() return f"XKB_{self.type.upper()}_{id}" @property def message_name(self: Entry) -> str: """Format the message string identifier for display""" return self.id.replace("-", " ").capitalize() Registry: TypeAlias = Sequence[Entry] def prepend_todo(text: str) -> str: if text.startswith("TODO"): return f"""{text[:5]}{text[5:]}""" else: return text def load_message_registry( env: jinja2.Environment, constants: dict[str, int], path: Path ) -> Registry: # Load the message registry YAML file as a Jinja2 template registry_template = env.get_template(str(path)) # Load message registry message_registry = sorted( map(Entry.parse, yaml.safe_load(registry_template.render(constants))), key=lambda e: e.code, ) # Check message codes and identifiers are unique codes: set[int] = set() identifiers: set[str] = set() for n, entry in enumerate(message_registry): if entry.code in codes: raise ValueError(f"Duplicated code in entry #{n}: {entry.code}") if entry.id in identifiers: raise ValueError(f"Duplicated identifier in entry #{n}: {entry.id}") codes.add(entry.code) identifiers.add(entry.id) return message_registry def generate_file( registry: Registry, env: jinja2.Environment, root: Path, file: Path, skip_removed: bool = False, ) -> None: """Generate a file from its Jinja2 template and the message registry""" template_path = file.with_suffix(f"{file.suffix}.jinja") template = env.get_template(str(template_path)) path = root / file script = Path(__file__).name with path.open("wt", encoding="utf-8") as fd: entries = ( tuple(filter(lambda e: e.removed is None, registry)) if skip_removed else registry ) fd.writelines(template.generate(entries=entries, script=script)) T = TypeVar("T") @dataclass class Constant(Generic[T]): name: str pattern: re.Pattern[str] conversion: Callable[[str], T] def read_constants(path: Path, patterns: Sequence[Constant[T]]) -> dict[str, T]: constants: dict[str, T] = {} patternsʹ = list(patterns) with path.open("rt", encoding="utf-8") as fd: for line in fd: for k, constant in enumerate(patternsʹ): if m := constant.pattern.match(line): constants[constant.name] = constant.conversion(m.group(1)) del patternsʹ[k] continue # Expect only one match per line if not patternsʹ: # No more pattern to match break for constant in patternsʹ: print(f"ERROR: could not find constant: {constant.name}.") if patternsʹ: raise ValueError("Some constants were not found.") return constants def generate( args: argparse.Namespace, registry: Registry, jinja_env: jinja2.Environment ): """ Generate the files """ generate_file( registry, jinja_env, args.root, Path("src/messages-codes.h"), skip_removed=True, ) generate_file( registry, jinja_env, args.root, Path("tools/messages.c"), skip_removed=True ) generate_file(registry, jinja_env, args.root, Path("doc/message-registry.md")) def get_new_code( args: argparse.Namespace, registry: Registry, jinja_env: jinja2.Environment ): """ Get a free code """ # Get all codes codes = frozenset(entry.code for entry in registry) # Filter free ones free = tuple(code for code in range(args.min, args.max + 1) if code not in codes) print(*random.sample(free, k=args.count)) # Root of the project ROOT = Path(__file__).parent.parent # Parse commands parser = argparse.ArgumentParser(description="Generate files from the message registry") parser.add_argument( "--root", type=Path, default=ROOT, help="Path to the root of the project (default: %(default)s)", ) parser.set_defaults(func=generate) subparsers = parser.add_subparsers() new_id_parser = subparsers.add_parser("get-new-code", help="Get a new message codes") new_id_parser.set_defaults(func=get_new_code) new_id_parser.add_argument("--min", type=int, default=1, help="default: %(default)s") new_id_parser.add_argument("--max", type=int, default=999, help="default: %(default)s") new_id_parser.add_argument("--count", type=int, default=10, help="default: %(default)s") generate_parser = subparsers.add_parser("generate", help="Generate files") args = parser.parse_args() # Read some constants from libxkbcommon that we need constants = read_constants( Path(__file__).parent.parent / "src" / "keymap.h", ( Constant( "XKB_MAX_GROUPS", re.compile(r"^#define\s+XKB_MAX_GROUPS\s+(\d+)"), int, ), Constant( "XKB_MAX_GROUPS_X11", re.compile(r"^#define\s+XKB_MAX_GROUPS_X11\s+(\d+)"), int, ), ), ) # Configure Jinja template_loader = jinja2.FileSystemLoader(args.root, encoding="utf-8") jinja_env = jinja2.Environment( loader=template_loader, keep_trailing_newline=True, trim_blocks=True, lstrip_blocks=True, ) jinja_env.filters["prepend_todo"] = prepend_todo # Load message registry message_registry = load_message_registry( jinja_env, constants, Path("doc/message-registry.yaml") ) args.func(args=args, registry=message_registry, jinja_env=jinja_env) xkbcommon-libxkbcommon-54ee7ac/src/000077500000000000000000000000001510033435100174525ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/src/atom.c000066400000000000000000000076011510033435100205620ustar00rootroot00000000000000/* * For MIT-open-group: * Copyright 1987, 1998 The Open Group * * For LicenseRef-digital-equipment-corporation: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. * * For HPND: * Copyright 1994 by Silicon Graphics Computer Systems, Inc. * * SPDX-License-Identifier: MIT-open-group AND LicenseRef-digital-equipment-corporation AND HPND */ #include "config.h" #include #include #include "atom.h" #include "darray.h" #include "utils.h" /* FNV-1a (http://www.isthe.com/chongo/tech/comp/fnv/). */ static inline uint32_t hash_buf(const char *string, size_t len) { uint32_t hash = UINT32_C(2166136261); for (size_t i = 0; i < (len + 1) / 2; i++) { hash ^= (uint8_t) string[i]; hash *= 0x01000193; hash ^= (uint8_t) string[len - 1 - i]; hash *= 0x01000193; } return hash; } /* * The atom table is an insert-only linear probing hash table * mapping strings to atoms. Another array maps the atoms to * strings. The atom value is the position in the strings array. */ struct atom_table { xkb_atom_t *index; size_t index_size; darray(char *) strings; }; struct atom_table * atom_table_new(void) { struct atom_table *table = calloc(1, sizeof(*table)); if (!table) return NULL; darray_init(table->strings); darray_append(table->strings, NULL); table->index_size = 4; table->index = calloc(table->index_size, sizeof(*table->index)); return table; } void atom_table_free(struct atom_table *table) { if (!table) return; char **string; darray_foreach(string, table->strings) free(*string); darray_free(table->strings); free(table->index); free(table); } darray_size_t atom_table_size(struct atom_table *table) { return darray_size(table->strings); } const char * atom_text(struct atom_table *table, xkb_atom_t atom) { assert(atom < darray_size(table->strings)); return darray_item(table->strings, atom); } xkb_atom_t atom_intern(struct atom_table *table, const char *string, size_t len, bool add) { /* len(string) > 0.8 * index_size */ if (darray_size(table->strings) > (table->index_size / 5) * 4) { table->index_size *= 2; table->index = realloc(table->index, table->index_size * sizeof(*table->index)); memset(table->index, 0, table->index_size * sizeof(*table->index)); for (darray_size_t j = 1; j < darray_size(table->strings); j++) { const char *s = darray_item(table->strings, j); uint32_t hash = hash_buf(s, strlen(s)); for (size_t i = 0; i < table->index_size; i++) { size_t index_pos = (hash + i) & (table->index_size - 1); if (index_pos == 0) continue; xkb_atom_t atom = table->index[index_pos]; if (atom == XKB_ATOM_NONE) { table->index[index_pos] = j; break; } } } } uint32_t hash = hash_buf(string, len); for (size_t i = 0; i < table->index_size; i++) { size_t index_pos = (hash + i) & (table->index_size - 1); if (index_pos == 0) continue; xkb_atom_t existing_atom = table->index[index_pos]; if (existing_atom == XKB_ATOM_NONE) { if (add) { xkb_atom_t new_atom = darray_size(table->strings); darray_append(table->strings, strndup(string, len)); table->index[index_pos] = new_atom; return new_atom; } else { return XKB_ATOM_NONE; } } const char *existing_value = darray_item(table->strings, existing_atom); if (strncmp(existing_value, string, len) == 0 && existing_value[len] == '\0') return existing_atom; } assert(!"couldn't find an empty slot during probing"); return XKB_ATOM_NONE; } xkbcommon-libxkbcommon-54ee7ac/src/atom.h000066400000000000000000000013411510033435100205620ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include #include #include "darray.h" #include "utils.h" /** Atoms are indexes into a `darray` */ typedef darray_size_t xkb_atom_t; #define XKB_ATOM_NONE 0 struct atom_table; XKB_EXPORT_PRIVATE struct atom_table * atom_table_new(void); XKB_EXPORT_PRIVATE void atom_table_free(struct atom_table *table); XKB_EXPORT_PRIVATE darray_size_t atom_table_size(struct atom_table *table); XKB_EXPORT_PRIVATE xkb_atom_t atom_intern(struct atom_table *table, const char *string, size_t len, bool add); XKB_EXPORT_PRIVATE const char * atom_text(struct atom_table *table, xkb_atom_t atom); xkbcommon-libxkbcommon-54ee7ac/src/compose/000077500000000000000000000000001510033435100211175ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/src/compose/constants.h000066400000000000000000000004371510033435100233100ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once #define COMPOSE_MAX_LHS_LEN 10 #define COMPOSE_MAX_INCLUDE_DEPTH 5 /** Maximum size of the string returned by xkb_compose_state_get_utf8() */ #define XKB_COMPOSE_MAX_STRING_SIZE 256 xkbcommon-libxkbcommon-54ee7ac/src/compose/dump.c000066400000000000000000000036571510033435100222430ustar00rootroot00000000000000/* * Copyright © 2021 Ran Benita * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include "src/darray.h" #include #include #include #include "xkbcommon/xkbcommon-compose.h" #include "parser.h" #include "escape.h" #include "dump.h" #include "src/keysym.h" bool print_compose_table_entry(FILE *file, struct xkb_compose_table_entry *entry) { size_t nsyms; const xkb_keysym_t *syms = xkb_compose_table_entry_sequence(entry, &nsyms); char buf[XKB_KEYSYM_NAME_MAX_SIZE]; for (size_t i = 0; i < nsyms; i++) { xkb_keysym_get_name(syms[i], buf, sizeof(buf)); fprintf(file, "<%s>", buf); if (i + 1 < nsyms) { fprintf(file, " "); } } fprintf(file, " : "); const char *utf8 = xkb_compose_table_entry_utf8(entry); if (*utf8 != '\0') { char *escaped = escape_utf8_string_literal(utf8); if (!escaped) { fprintf(stderr, "ERROR: Cannot escape the string: allocation error\n"); return false; } else { fprintf(file, " \"%s\"", escaped); free(escaped); } } const xkb_keysym_t keysym = xkb_compose_table_entry_keysym(entry); if (keysym != XKB_KEY_NoSymbol) { xkb_keysym_get_name(keysym, buf, sizeof(buf)); fprintf(file, " %s", buf); } fprintf(file, "\n"); return true; } bool xkb_compose_table_dump(FILE *file, struct xkb_compose_table *table) { struct xkb_compose_table_entry *entry; struct xkb_compose_table_iterator *iter = xkb_compose_table_iterator_new(table); if (!iter) return false; bool ok = true; while ((entry = xkb_compose_table_iterator_next(iter))) { if (!print_compose_table_entry(file, entry)) { ok = false; break; } } xkb_compose_table_iterator_free(iter); return ok; } xkbcommon-libxkbcommon-54ee7ac/src/compose/dump.h000066400000000000000000000005461510033435100222420ustar00rootroot00000000000000/* * Copyright © 2021 Ran Benita * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include "table.h" bool print_compose_table_entry(FILE *file, struct xkb_compose_table_entry *entry); bool xkb_compose_table_dump(FILE *file, struct xkb_compose_table *table); xkbcommon-libxkbcommon-54ee7ac/src/compose/escape.h000066400000000000000000000045571510033435100225430ustar00rootroot00000000000000/* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include "src/utils.h" /* Ad-hoc escaping for UTF-8 string * * Note that it only escapes the strict minimum to get a valid Compose file. * It also escapes hexadecimal digits after an hexadecimal escape. This is not * strictly needed by the current implementation: "\x0abcg" parses as "␊bcg", * but better be cautious than sorry and produce "\x0a\x62\x63g" instead. * In the latter string there is no ambiguity and no need to know the maximum * number of digits supported by the escape sequence. */ static inline char* escape_utf8_string_literal(const char *from) { const size_t length = strlen(from); /* Longest escape is converting ASCII character to "\xNN" */ char* to = calloc(4 * length + 1, sizeof(*to)); if (!to) return NULL; size_t t = 0; bool previous_is_hex_escape = false; uint8_t nbytes = 0; for (size_t f = 0; f < length;) { if ((unsigned char) from[f] < 0x80) { /* ASCII */ if (from[f] <= 0x10 || from[f] == 0x7f || (is_xdigit(from[f]) && previous_is_hex_escape)) { /* Control character or hexadecimal digit following an hexadecimal escape */ snprintf_safe(&to[t], 5, "\\x%02x", from[f]); t += 4; previous_is_hex_escape = true; } else if (from[f] == '"' || from[f] == '\\') { /* Quote and backslash */ snprintf_safe(&to[t], 3, "\\%c", from[f]); t += 2; previous_is_hex_escape = false; } else { /* Other characters */ to[t++] = from[f]; previous_is_hex_escape = false; } f++; continue; } /* Test next byte for the next Unicode codepoint’s bytes count */ else if ((unsigned char) from[f] < 0xe0) nbytes = 2; else if ((unsigned char) from[f] < 0xf0) nbytes = 3; else nbytes = 4; memcpy(&to[t], &from[f], nbytes); t += nbytes; f += nbytes; previous_is_hex_escape = false; } to[t++] = '\0'; char* ret = realloc(to, t); if (!ret) free(to); return ret; } xkbcommon-libxkbcommon-54ee7ac/src/compose/parser.c000066400000000000000000000644111510033435100225650ustar00rootroot00000000000000/* * For HPND-sell-variant: * Copyright 1992 by Oki Technosystems Laboratory, Inc. * Copyright 1992 by Fuji Xerox Co., Ltd. * * For MIT: * Copyright © 2013 Ran Benita * * SPDX-License-Identifier: HPND-sell-variant AND MIT * * Author: Yasuhiro Kawai Oki Technosystems Laboratory * Author: Kazunori Nishihara Fuji Xerox */ #include "config.h" #include #include #include "xkbcommon/xkbcommon-keysyms.h" #include "darray.h" #include "messages-codes.h" #include "utils.h" #include "constants.h" #include "table.h" #include "scanner-utils.h" #include "paths.h" #include "utf8.h" #include "parser.h" #include "keysym.h" /* * Grammar adapted from libX11/modules/im/ximcp/imLcPrs.c. * See also the XCompose(5) manpage. * * FILE ::= { [PRODUCTION] [COMMENT] "\n" | INCLUDE } * INCLUDE ::= "include" '"' INCLUDE_STRING '"' * PRODUCTION ::= LHS ":" RHS [ COMMENT ] * COMMENT ::= "#" {} * LHS ::= EVENT { EVENT } * EVENT ::= [MODIFIER_LIST] "<" keysym ">" * MODIFIER_LIST ::= (["!"] {MODIFIER} ) | "None" * MODIFIER ::= ["~"] MODIFIER_NAME * MODIFIER_NAME ::= ("Ctrl"|"Lock"|"Caps"|"Shift"|"Alt"|"Meta") * RHS ::= ( STRING | keysym | STRING keysym ) * STRING ::= '"' { CHAR } '"' * CHAR ::= GRAPHIC_CHAR | ESCAPED_CHAR * GRAPHIC_CHAR ::= locale (codeset) dependent code * ESCAPED_CHAR ::= ('\\' | '\"' | OCTAL | HEX ) * OCTAL ::= '\' OCTAL_CHAR [OCTAL_CHAR [OCTAL_CHAR]] * OCTAL_CHAR ::= (0|1|2|3|4|5|6|7) * HEX ::= '\' (x|X) HEX_CHAR [HEX_CHAR]] * HEX_CHAR ::= (0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F|a|b|c|d|e|f) * * INCLUDE_STRING is a filesystem path, with the following %-expansions: * %% - '%'. * %H - The user's home directory (the $HOME environment variable). * %L - The name of the locale specific Compose file (e.g., * "/usr/share/X11/locale//Compose"). * %S - The name of the system directory for Compose files (e.g., * "/usr/share/X11/locale"). */ enum rules_token { TOK_END_OF_FILE = 0, TOK_END_OF_LINE, TOK_INCLUDE, TOK_INCLUDE_STRING, TOK_LHS_KEYSYM, TOK_COLON, TOK_BANG, TOK_TILDE, TOK_STRING, TOK_IDENT, TOK_ERROR }; /* Values returned with some tokens, like yylval. */ union lvalue { struct { /* Still \0-terminated. */ const char *str; size_t len; } string; }; static enum rules_token lex(struct scanner *s, union lvalue *val) { skip_more_whitespace_and_comments: /* Skip spaces. */ while (is_space(scanner_peek(s))) if (scanner_next(s) == '\n') return TOK_END_OF_LINE; /* Skip comments. */ if (scanner_chr(s, '#')) { scanner_skip_to_eol(s); goto skip_more_whitespace_and_comments; } /* See if we're done. */ if (scanner_eof(s)) return TOK_END_OF_FILE; /* New token. */ s->token_pos = s->pos; s->buf_pos = 0; /* LHS Keysym. */ if (scanner_chr(s, '<')) { while (scanner_peek(s) != '>' && !scanner_eol(s) && !scanner_eof(s)) scanner_buf_append(s, scanner_next(s)); if (!scanner_chr(s, '>')) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "unterminated keysym literal"); return TOK_ERROR; } if (!scanner_buf_append(s, '\0')) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "keysym literal is too long"); return TOK_ERROR; } val->string.str = s->buf; val->string.len = s->buf_pos; return TOK_LHS_KEYSYM; } /* Colon. */ if (scanner_chr(s, ':')) return TOK_COLON; if (scanner_chr(s, '!')) return TOK_BANG; if (scanner_chr(s, '~')) return TOK_TILDE; /* String literal. */ if (scanner_chr(s, '\"')) { while (!scanner_eof(s) && !scanner_eol(s) && scanner_peek(s) != '\"') { if (scanner_chr(s, '\\')) { uint8_t o; size_t start_pos = s->pos; if (scanner_chr(s, '\\')) { scanner_buf_append(s, '\\'); } else if (scanner_chr(s, '"')) { scanner_buf_append(s, '"'); } else if (scanner_chr(s, 'x') || scanner_chr(s, 'X')) { if (scanner_hex(s, &o) && is_valid_char((char) o)) { scanner_buf_append(s, (char) o); } else { scanner_warn(s, XKB_WARNING_INVALID_ESCAPE_SEQUENCE, "illegal hexadecimal escape sequence " "\"%.*s\" in string literal", (int) (s->pos - start_pos + 1), &s->s[start_pos - 1]); } } else if (scanner_oct(s, &o) && is_valid_char((char) o)) { scanner_buf_append(s, (char) o); } else if (s->pos > start_pos) { scanner_warn(s, XKB_WARNING_INVALID_ESCAPE_SEQUENCE, "illegal octal escape sequence \"%.*s\" " "in string literal", (int) (s->pos - start_pos + 1), &s->s[start_pos - 1]); /* Ignore. */ } else { scanner_warn(s, XKB_WARNING_UNKNOWN_CHAR_ESCAPE_SEQUENCE, "unknown escape sequence \"\\%c\" " "in string literal", scanner_peek(s)); /* Ignore. */ } } else { scanner_buf_append(s, scanner_next(s)); } } if (!scanner_chr(s, '\"')) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "unterminated string literal"); return TOK_ERROR; } if (!scanner_buf_append(s, '\0')) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "string literal is too long"); return TOK_ERROR; } if (!is_valid_utf8(s->buf, s->buf_pos - 1)) { scanner_err(s, XKB_ERROR_INVALID_FILE_ENCODING, "string literal is not a valid UTF-8 string"); return TOK_ERROR; } val->string.str = s->buf; val->string.len = s->buf_pos; return TOK_STRING; } /* Identifier or include. */ if (is_alpha(scanner_peek(s)) || scanner_peek(s) == '_') { s->buf_pos = 0; while (is_alnum(scanner_peek(s)) || scanner_peek(s) == '_') scanner_buf_append(s, scanner_next(s)); if (!scanner_buf_append(s, '\0')) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "identifier is too long"); return TOK_ERROR; } if (streq(s->buf, "include")) return TOK_INCLUDE; val->string.str = s->buf; val->string.len = s->buf_pos; return TOK_IDENT; } scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "unrecognized token"); /* Discard rest of line. */ scanner_skip_to_eol(s); return TOK_ERROR; } static enum rules_token lex_include_string(struct scanner *s, struct xkb_compose_table *table, union lvalue *val_out) { while (is_space(scanner_peek(s))) if (scanner_next(s) == '\n') return TOK_END_OF_LINE; s->token_pos = s->pos; s->buf_pos = 0; if (!scanner_chr(s, '\"')) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "include statement must be followed by a path"); return TOK_ERROR; } while (!scanner_eof(s) && !scanner_eol(s) && scanner_peek(s) != '\"') { if (scanner_chr(s, '%')) { if (scanner_chr(s, '%')) { scanner_buf_append(s, '%'); } else if (scanner_chr(s, 'H')) { const char *home = xkb_context_getenv(table->ctx, "HOME"); if (!home) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "%%H was used in an include statement, " "but the HOME environment variable is not set"); return TOK_ERROR; } if (!scanner_buf_appends(s, home)) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "include path after expanding %%H is too long"); return TOK_ERROR; } } else if (scanner_chr(s, 'L')) { char *path = get_locale_compose_file_path(table->ctx, table->locale); if (!path) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_LOCALE, "failed to expand %%L to the locale Compose file"); return TOK_ERROR; } if (!scanner_buf_appends(s, path)) { free(path); scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "include path after expanding %%L is too long"); return TOK_ERROR; } free(path); } else if (scanner_chr(s, 'S')) { const char *xlocaledir = get_xlocaledir_path(table->ctx); if (!scanner_buf_appends(s, xlocaledir)) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "include path after expanding %%S is too long"); return TOK_ERROR; } } else { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "unknown %% format (%c) in include statement", scanner_peek(s)); return TOK_ERROR; } } else { scanner_buf_append(s, scanner_next(s)); } } if (!scanner_chr(s, '\"')) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "unterminated include statement"); return TOK_ERROR; } if (!scanner_buf_append(s, '\0')) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "include path is too long"); return TOK_ERROR; } val_out->string.str = s->buf; val_out->string.len = s->buf_pos; return TOK_INCLUDE_STRING; } struct production { xkb_keysym_t lhs[COMPOSE_MAX_LHS_LEN]; unsigned int len; xkb_keysym_t keysym; char string[XKB_COMPOSE_MAX_STRING_SIZE]; /* At least one of these is true. */ bool has_keysym; bool has_string; /* The matching is as follows: (active_mods & modmask) == mods. */ xkb_mod_mask_t modmask; xkb_mod_mask_t mods; }; static void add_production(struct xkb_compose_table *table, struct scanner *s, const struct production *production) { unsigned int lhs_pos = 0; uint32_t curr = darray_size(table->nodes) == 1 ? 0 : 1; uint32_t *pptr = NULL; struct compose_node *node = NULL; /* Warn before potentially going over the limit, discard silently after. */ if (darray_size(table->nodes) + production->len + COMPOSE_MAX_LHS_LEN > MAX_COMPOSE_NODES) scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "too many sequences for one Compose file; " "will ignore further lines"); if (darray_size(table->nodes) + production->len >= MAX_COMPOSE_NODES) return; /* * Insert the sequence to the ternary search tree, creating new nodes as * needed. * * TODO: We insert in the order given, this means some inputs can create * long O(n) chains, which results in total O(n^2) parsing time. We should * ensure the tree is reasonably balanced somehow. */ while (true) { const xkb_keysym_t keysym = production->lhs[lhs_pos]; const bool last = lhs_pos + 1 == production->len; if (curr == 0) { /* * Create a new node and update the parent pointer to it. * Update the pointer first because the append invalidates it. */ struct compose_node new = { .keysym = keysym, .lokid = 0, .hikid = 0, .internal = { .eqkid = 0, .is_leaf = false, }, }; curr = darray_size(table->nodes); if (pptr != NULL) { *pptr = curr; pptr = NULL; } darray_append(table->nodes, new); } node = &darray_item(table->nodes, curr); if (keysym < node->keysym) { pptr = &node->lokid; curr = node->lokid; } else if (keysym > node->keysym) { pptr = &node->hikid; curr = node->hikid; } else if (!last) { if (node->is_leaf) { scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "a sequence already exists which is a prefix of " "this sequence; overriding"); node->internal.eqkid = 0; node->internal.is_leaf = false; } lhs_pos++; pptr = &node->internal.eqkid; curr = node->internal.eqkid; } else { if (node->is_leaf) { bool same_string = (node->leaf.utf8 == 0 && !production->has_string) || ( node->leaf.utf8 != 0 && production->has_string && streq(&darray_item(table->utf8, node->leaf.utf8), production->string) ); bool same_keysym = (node->leaf.keysym == XKB_KEY_NoSymbol && !production->has_keysym) || ( node->leaf.keysym != XKB_KEY_NoSymbol && production->has_keysym && node->leaf.keysym == production->keysym ); if (same_string && same_keysym) { scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "this compose sequence is a duplicate of another; " "skipping line"); return; } else { scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "this compose sequence already exists; overriding"); } } else if (node->internal.eqkid != 0) { scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "this compose sequence is a prefix of another; " "overriding"); node->internal.eqkid = 0; } /* NOTE: If there was a previous entry, its string may *not* be * reused in the UTF8 table and the corresponding memory is then * wasted! */ if (production->has_string) { const size_t len = strlen(production->string); if (node->is_leaf && node->leaf.utf8 && len <= strlen(&darray_item(table->utf8, node->leaf.utf8))) { /* There is a previous entry with an overwritable string */ memcpy(&darray_item(table->utf8, node->leaf.utf8), production->string, len + 1); } else { /* Cannot reuse string: allocate new one */ node->leaf.utf8 = darray_size(table->utf8); darray_append_items(table->utf8, production->string, (darray_size_t)strlen(production->string) + 1); } } else { /* Ensure we reset possible previous entry */ node->leaf.utf8 = 0; } if (production->has_keysym) { node->leaf.keysym = production->keysym; } else { /* Ensure we reset possible previous entry */ node->leaf.keysym = XKB_KEY_NoSymbol; } node->is_leaf = true; return; } } } /* Should match resolve_modifier(). */ #define ALL_MODS_MASK ((1u << 0) | (1u << 1) | (1u << 2) | (1u << 3)) static xkb_mod_index_t resolve_modifier(const char *name) { static const struct { const char *name; xkb_mod_index_t mod; } mods[] = { { "Shift", 0 }, { "Ctrl", 2 }, { "Alt", 3 }, { "Meta", 3 }, { "Lock", 1 }, { "Caps", 1 }, }; for (unsigned int i = 0; i < ARRAY_SIZE(mods); i++) if (streq(name, mods[i].name)) return mods[i].mod; return XKB_MOD_INVALID; } /* Parse a string literal ("...") and return the corresponding unescaped string, * or NULL if it fails. * This is aimed only for testing (un)escaping characters. */ char * parse_string_literal(struct xkb_context *ctx, const char *string) { struct scanner s; union lvalue val; scanner_init(&s, ctx, string, strlen(string), "(unnamed)", NULL); switch (lex(&s, &val)) { case TOK_STRING: return strdup(val.string.str); default: fprintf(stderr, "ERROR: %s\n", s.s); return NULL; } } static bool parse(struct xkb_compose_table *table, struct scanner *s, unsigned int include_depth); static bool do_include(struct xkb_compose_table *table, struct scanner *s, const char *path, unsigned int include_depth) { FILE *file; bool ok; char *string; size_t size; struct scanner new_s; if (include_depth >= COMPOSE_MAX_INCLUDE_DEPTH) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "maximum include depth (%u) exceeded; maybe there is an include loop?", COMPOSE_MAX_INCLUDE_DEPTH); return false; } file = fopen(path, "rb"); if (!file) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "failed to open included Compose file \"%s\": %s", path, strerror(errno)); return false; } ok = map_file(file, &string, &size); if (!ok) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "failed to read included Compose file \"%s\": %s", path, strerror(errno)); goto err_file; } scanner_init(&new_s, table->ctx, string, size, path, s->priv); ok = parse(table, &new_s, include_depth + 1); if (!ok) goto err_unmap; err_unmap: unmap_file(string, size); err_file: fclose(file); return ok; } static bool parse(struct xkb_compose_table *table, struct scanner *s, unsigned int include_depth) { enum rules_token tok; union lvalue val; xkb_keysym_t keysym; struct production production; enum { MAX_ERRORS = 10 }; int num_errors = 0; /* Basic detection of wrong character encoding. The first character relevant to the grammar must be ASCII: whitespace, include, modifier list, keysym, comment */ if (!scanner_check_supported_char_encoding(s)) { scanner_err(s, XKB_ERROR_INVALID_FILE_ENCODING, "This could be a file encoding issue. " "Supported file encodings are ASCII and UTF-8."); goto fail; } initial: production.len = 0; production.has_keysym = false; production.has_string = false; production.mods = 0; production.modmask = 0; /* fallthrough */ initial_eol: switch (tok = lex(s, &val)) { case TOK_END_OF_LINE: goto initial_eol; case TOK_END_OF_FILE: goto finished; case TOK_INCLUDE: goto include; default: goto lhs_tok; } include: switch (tok = lex_include_string(s, table, &val)) { case TOK_INCLUDE_STRING: goto include_eol; default: goto unexpected; } include_eol: switch (tok = lex(s, &val)) { case TOK_END_OF_LINE: if (!do_include(table, s, val.string.str, include_depth)) goto fail; goto initial; default: goto unexpected; } lhs: tok = lex(s, &val); lhs_tok: switch (tok) { case TOK_COLON: if (production.len <= 0) { scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "expected at least one keysym on left-hand side; " "skipping line"); goto skip; } goto rhs; case TOK_IDENT: if (streq(val.string.str, "None")) { production.mods = 0; production.modmask = ALL_MODS_MASK; goto lhs_keysym; } goto lhs_mod_list_tok; case TOK_TILDE: goto lhs_mod_list_tok; case TOK_BANG: production.modmask = ALL_MODS_MASK; goto lhs_mod_list; default: goto lhs_keysym_tok; } lhs_keysym: tok = lex(s, &val); lhs_keysym_tok: switch (tok) { case TOK_LHS_KEYSYM: keysym = xkb_keysym_from_name(val.string.str, XKB_KEYSYM_NO_FLAGS); if (keysym == XKB_KEY_NoSymbol) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "unrecognized keysym \"%s\" on left-hand side", val.string.str); goto error; } check_deprecated_keysyms(scanner_warn, s, s->ctx, keysym, val.string.str, val.string.str, "%s", ""); if (production.len + 1 > COMPOSE_MAX_LHS_LEN) { scanner_warn(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "too many keysyms (%u) on left-hand side; skipping line", COMPOSE_MAX_LHS_LEN + 1); goto skip; } production.lhs[production.len++] = keysym; production.mods = 0; production.modmask = 0; goto lhs; default: goto unexpected; } lhs_mod_list: tok = lex(s, &val); lhs_mod_list_tok: { bool tilde = false; xkb_mod_index_t mod; if (tok != TOK_TILDE && tok != TOK_IDENT) goto lhs_keysym_tok; if (tok == TOK_TILDE) { tilde = true; tok = lex(s, &val); } if (tok != TOK_IDENT) goto unexpected; mod = resolve_modifier(val.string.str); if (mod == XKB_MOD_INVALID) { scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "unrecognized modifier \"%s\"", val.string.str); goto error; } production.modmask |= UINT32_C(1) << mod; if (tilde) production.mods &= ~(UINT32_C(1) << mod); else production.mods |= UINT32_C(1) << mod; goto lhs_mod_list; } rhs: switch (tok = lex(s, &val)) { case TOK_STRING: if (production.has_string) { scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "right-hand side can have at most one string; " "skipping line"); goto skip; } if (val.string.len <= 0) { scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "right-hand side string must not be empty; " "skipping line"); goto skip; } if (val.string.len > sizeof(production.string)) { scanner_warn(s, XKB_LOG_MESSAGE_NO_ID, "right-hand side string is too long: " "expected max: %zu, got: %zu; skipping line", sizeof(production.string) - 1, val.string.len - 1); goto skip; } memcpy(production.string, val.string.str, val.string.len); production.has_string = true; goto rhs; case TOK_IDENT: keysym = xkb_keysym_from_name(val.string.str, XKB_KEYSYM_NO_FLAGS); if (keysym == XKB_KEY_NoSymbol) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "unrecognized keysym \"%s\" on right-hand side", val.string.str); goto error; } check_deprecated_keysyms(scanner_warn, s, s->ctx, keysym, val.string.str, val.string.str, "%s", ""); if (production.has_keysym) { scanner_warn(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "right-hand side can have at most one keysym; " "skipping line"); goto skip; } production.keysym = keysym; production.has_keysym = true; /* fallthrough */ case TOK_END_OF_LINE: if (!production.has_string && !production.has_keysym) { scanner_warn(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "right-hand side must have at least one of string " "or keysym; skipping line"); goto skip; } add_production(table, s, &production); goto initial; default: goto unexpected; } unexpected: if (tok != TOK_ERROR) scanner_err(s, XKB_ERROR_INVALID_COMPOSE_SYNTAX, "unexpected token"); error: num_errors++; if (num_errors <= MAX_ERRORS) goto skip; scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "too many errors"); goto fail; fail: scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "failed to parse file"); return false; skip: while (tok != TOK_END_OF_LINE && tok != TOK_END_OF_FILE) tok = lex(s, &val); goto initial; finished: return true; } bool parse_string(struct xkb_compose_table *table, const char *string, size_t len, const char *file_name) { struct scanner s; scanner_init(&s, table->ctx, string, len, file_name, NULL); if (!parse(table, &s, 0)) return false; /* Maybe the allocator can use the excess space. */ darray_shrink(table->nodes); darray_shrink(table->utf8); return true; } bool parse_file(struct xkb_compose_table *table, FILE *file, const char *file_name) { bool ok; char *string; size_t size; ok = map_file(file, &string, &size); if (!ok) { log_err(table->ctx, XKB_LOG_MESSAGE_NO_ID, "Couldn't read Compose file %s: %s\n", file_name, strerror(errno)); return false; } ok = parse_string(table, string, size, file_name); unmap_file(string, size); return ok; } xkbcommon-libxkbcommon-54ee7ac/src/compose/parser.h000066400000000000000000000011411510033435100225610ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-compose.h" #include "src/utils.h" XKB_EXPORT_PRIVATE char * parse_string_literal(struct xkb_context *ctx, const char *string); bool parse_string(struct xkb_compose_table *table, const char *string, size_t len, const char *file_name); bool parse_file(struct xkb_compose_table *table, FILE *file, const char *file_name); xkbcommon-libxkbcommon-54ee7ac/src/compose/paths.c000066400000000000000000000150071510033435100224050ustar00rootroot00000000000000/* * Copyright © 2014 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "messages-codes.h" #include "utils.h" #include "utils-paths.h" #include "context.h" #include "paths.h" enum resolve_name_direction { LEFT_TO_RIGHT, RIGHT_TO_LEFT, }; const char * get_xlocaledir_path(struct xkb_context *ctx) { const char *dir = xkb_context_getenv(ctx, "XLOCALEDIR"); if (!dir) dir = XLOCALEDIR; return dir; } /* * Files like compose.dir have the format LEFT: RIGHT. Lookup @name in * such a file and return its matching value, according to @direction. * @filename is relative to the xlocaledir. */ static char * resolve_name(struct xkb_context *ctx, const char *filename, enum resolve_name_direction direction, const char *name) { int ret; bool ok; const char *xlocaledir; char path[512]; FILE *file; char *string; size_t string_size; const char *end; const char *s, *left, *right; char *match; size_t left_len, right_len, name_len; xlocaledir = get_xlocaledir_path(ctx); ret = snprintf(path, sizeof(path), "%s/%s", xlocaledir, filename); if (ret < 0 || (size_t) ret >= sizeof(path)) return NULL; file = fopen(path, "rb"); if (!file) return NULL; ok = map_file(file, &string, &string_size); fclose(file); if (!ok) return NULL; s = string; end = string + string_size; name_len = strlen(name); match = NULL; while (s < end) { /* Skip spaces. */ while (s < end && is_space(*s)) s++; /* Skip comments. */ if (s < end && *s == '#') { while (s < end && *s != '\n') s++; continue; } /* Get the left value. */ left = s; while (s < end && !is_space(*s) && *s != ':') s++; left_len = s - left; /* There's an optional colon between left and right. */ if (s < end && *s == ':') s++; /* Skip spaces. */ while (s < end && is_space(*s)) s++; /* Get the right value. */ right = s; while (s < end && !is_space(*s)) s++; right_len = s - right; /* Discard rest of line. */ while (s < end && *s != '\n') s++; if (direction == LEFT_TO_RIGHT) { if (left_len == name_len && memcmp(left, name, left_len) == 0) { match = strndup(right, right_len); break; } } else if (direction == RIGHT_TO_LEFT) { if (right_len == name_len && memcmp(right, name, right_len) == 0) { match = strndup(left, left_len); break; } } } unmap_file(string, string_size); return match; } char * resolve_locale(struct xkb_context *ctx, const char *locale) { char *alias = resolve_name(ctx, "locale.alias", LEFT_TO_RIGHT, locale); return alias ? alias : strdup(locale); } char * get_xcomposefile_path(struct xkb_context *ctx) { return strdup_safe(xkb_context_getenv(ctx, "XCOMPOSEFILE")); } char * get_xdg_xcompose_file_path(struct xkb_context *ctx) { const char *xdg_config_home; const char *home; xdg_config_home = xkb_context_getenv(ctx, "XDG_CONFIG_HOME"); if (!xdg_config_home || !is_absolute_path(xdg_config_home)) { home = xkb_context_getenv(ctx, "HOME"); if (!home) return NULL; return asprintf_safe("%s/.config/XCompose", home); } return asprintf_safe("%s/XCompose", xdg_config_home); } char * get_home_xcompose_file_path(struct xkb_context *ctx) { const char *home; home = xkb_context_getenv(ctx, "HOME"); if (!home) return NULL; return asprintf_safe("%s/.XCompose", home); } char * get_locale_compose_file_path(struct xkb_context *ctx, const char *locale) { char *resolved; char *path; /* * WARNING: Random workaround ahead. * * We currently do not support non-UTF-8 Compose files. The C/POSIX * locale is specified to be the default fallback locale with an * ASCII charset. But for some reason the compose.dir points the C * locale to the iso8859-1/Compose file, which is not ASCII but * ISO8859-1. Since this is bound to happen a lot, and since our API * is UTF-8 based, and since 99% of the time a C locale is really just * a misconfiguration for UTF-8, let's do the most helpful thing. */ static const char * const fallback = "en_US.UTF-8"; static const char * const registry = "compose.dir"; if (streq(locale, "C")) locale = fallback; resolved = resolve_name(ctx, registry, RIGHT_TO_LEFT, locale); if (!resolved) { #ifdef HAVE_NEWLOCALE /* * There is no extension mechanism for X11 Compose locales. * Instead of failing, we just use `en_US.UTF-8` as a fallback because * it is what most locales use anyway. * But we still want to fail if the locale is invalid in the system, * so that we can catch missing system locales and typos. */ locale_t loc = newlocale(LC_ALL_MASK, locale, (locale_t) 0); if (loc == (locale_t) 0) { log_err(ctx, XKB_ERROR_INVALID_COMPOSE_LOCALE, "No Compose file for locale \"%s\": " "locale is either invalid or not installed\n", locale); return NULL; } else { /* * The locale is legit but have no entry in the X11 Compose registry, * so use the `en_US.UTF-8` fallback. */ freelocale(loc); resolved = resolve_name(ctx, registry, RIGHT_TO_LEFT, fallback); if (!resolved) { log_err(ctx, XKB_ERROR_INVALID_COMPOSE_LOCALE, "No Compose file for locale \"%s\": " "failed to use fallback \"%s\"\n", locale, fallback); return NULL; } else { log_warn(ctx, XKB_ERROR_INVALID_COMPOSE_LOCALE, "No Compose file for locale \"%s\": " "using locale fallback \"%s\"\n", locale, fallback); } } #else return NULL; #endif } if (is_absolute_path(resolved)) { path = resolved; } else { const char *xlocaledir = get_xlocaledir_path(ctx); path = asprintf_safe("%s/%s", xlocaledir, resolved); free(resolved); } return path; } xkbcommon-libxkbcommon-54ee7ac/src/compose/paths.h000066400000000000000000000010461510033435100224100ustar00rootroot00000000000000/* * Copyright © 2014 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include "xkbcommon/xkbcommon.h" char * resolve_locale(struct xkb_context *ctx, const char *locale); const char * get_xlocaledir_path(struct xkb_context *ctx); char * get_xcomposefile_path(struct xkb_context *ctx); char * get_xdg_xcompose_file_path(struct xkb_context *ctx); char * get_home_xcompose_file_path(struct xkb_context *ctx); char * get_locale_compose_file_path(struct xkb_context *ctx, const char *locale); xkbcommon-libxkbcommon-54ee7ac/src/compose/state.c000066400000000000000000000113021510033435100224000ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "table.h" #include "utils.h" #include "keysym.h" struct xkb_compose_state { int refcnt; enum xkb_compose_state_flags flags; struct xkb_compose_table *table; /* * Offsets into xkb_compose_table::nodes. * * They maintain the current and previous position in the trie; see * xkb_compose_state_feed(). * * This is also sufficient for inferring the current status; see * xkb_compose_state_get_status(). */ uint32_t prev_context; uint32_t context; }; struct xkb_compose_state * xkb_compose_state_new(struct xkb_compose_table *table, enum xkb_compose_state_flags flags) { struct xkb_compose_state *state; state = calloc(1, sizeof(*state)); if (!state) return NULL; state->refcnt = 1; state->table = xkb_compose_table_ref(table); state->flags = flags; state->prev_context = 0; state->context = 0; return state; } struct xkb_compose_state * xkb_compose_state_ref(struct xkb_compose_state *state) { assert(state->refcnt > 0); state->refcnt++; return state; } void xkb_compose_state_unref(struct xkb_compose_state *state) { assert(!state || state->refcnt > 0); if (!state || --state->refcnt > 0) return; xkb_compose_table_unref(state->table); free(state); } struct xkb_compose_table * xkb_compose_state_get_compose_table(struct xkb_compose_state *state) { return state->table; } enum xkb_compose_feed_result xkb_compose_state_feed(struct xkb_compose_state *state, xkb_keysym_t keysym) { uint32_t context; const struct compose_node *node; /* * Modifiers do not affect the sequence directly. In particular, * they do not cancel a sequence; otherwise it'd be impossible to * have a sequence like (needs Shift in the middle). * * The following test is not really accurate - in order to test if * a key is "modifier key", we really need the keymap, but we don't * have it here. However, this is (approximately) what libX11 does * as well. */ if (xkb_keysym_is_modifier(keysym)) return XKB_COMPOSE_FEED_IGNORED; node = &darray_item(state->table->nodes, state->context); context = (node->is_leaf ? 1 : node->internal.eqkid); if (context == 1 && darray_size(state->table->nodes) == 1) context = 0; while (context != 0) { node = &darray_item(state->table->nodes, context); if (keysym < node->keysym) context = node->lokid; else if (keysym > node->keysym) context = node->hikid; else break; } state->prev_context = state->context; state->context = context; return XKB_COMPOSE_FEED_ACCEPTED; } void xkb_compose_state_reset(struct xkb_compose_state *state) { state->prev_context = 0; state->context = 0; } enum xkb_compose_status xkb_compose_state_get_status(struct xkb_compose_state *state) { const struct compose_node *prev_node, *node; prev_node = &darray_item(state->table->nodes, state->prev_context); node = &darray_item(state->table->nodes, state->context); if (state->context == 0 && !prev_node->is_leaf) return XKB_COMPOSE_CANCELLED; if (state->context == 0) return XKB_COMPOSE_NOTHING; if (!node->is_leaf) return XKB_COMPOSE_COMPOSING; return XKB_COMPOSE_COMPOSED; } int xkb_compose_state_get_utf8(struct xkb_compose_state *state, char *buffer, size_t size) { const struct compose_node *node = &darray_item(state->table->nodes, state->context); if (!node->is_leaf) goto fail; /* If there's no string specified, but only a keysym, try to do the * most helpful thing. */ if (node->leaf.utf8 == 0 && node->leaf.keysym != XKB_KEY_NoSymbol) { char utf8[XKB_KEYSYM_UTF8_MAX_SIZE]; int ret; ret = xkb_keysym_to_utf8(node->leaf.keysym, utf8, sizeof(utf8)); if (ret < 0 || ret == 0) { /* ret < 0 is impossible. * ret == 0 means the keysym has no string representation. */ goto fail; } return snprintf(buffer, size, "%s", utf8); } return snprintf(buffer, size, "%s", &darray_item(state->table->utf8, node->leaf.utf8)); fail: if (size > 0) buffer[0] = '\0'; return 0; } xkb_keysym_t xkb_compose_state_get_one_sym(struct xkb_compose_state *state) { const struct compose_node *node = &darray_item(state->table->nodes, state->context); if (!node->is_leaf) return XKB_KEY_NoSymbol; return node->leaf.keysym; } xkbcommon-libxkbcommon-54ee7ac/src/compose/table.c000066400000000000000000000265701510033435100223640ustar00rootroot00000000000000/* * Copyright © 2013,2021 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "messages-codes.h" #include "utils.h" #include "constants.h" #include "table.h" #include "parser.h" #include "paths.h" static struct xkb_compose_table * xkb_compose_table_new(struct xkb_context *ctx, const char *locale, enum xkb_compose_format format, enum xkb_compose_compile_flags flags) { char *resolved_locale; struct xkb_compose_table *table; struct compose_node dummy = {0}; resolved_locale = resolve_locale(ctx, locale); if (!resolved_locale) return NULL; table = calloc(1, sizeof(*table)); if (!table) { free(resolved_locale); return NULL; } table->refcnt = 1; table->ctx = xkb_context_ref(ctx); table->locale = resolved_locale; table->format = format; table->flags = flags; darray_init(table->nodes); darray_init(table->utf8); dummy.keysym = XKB_KEY_NoSymbol; dummy.leaf.is_leaf = true; dummy.leaf.utf8 = 0; dummy.leaf.keysym = XKB_KEY_NoSymbol; darray_append(table->nodes, dummy); darray_append(table->utf8, '\0'); return table; } struct xkb_compose_table * xkb_compose_table_ref(struct xkb_compose_table *table) { assert(table->refcnt > 0); table->refcnt++; return table; } void xkb_compose_table_unref(struct xkb_compose_table *table) { assert(!table || table->refcnt > 0); if (!table || --table->refcnt > 0) return; free(table->locale); darray_free(table->nodes); darray_free(table->utf8); xkb_context_unref(table->ctx); free(table); } struct xkb_compose_table * xkb_compose_table_new_from_file(struct xkb_context *ctx, FILE *file, const char *locale, enum xkb_compose_format format, enum xkb_compose_compile_flags flags) { struct xkb_compose_table *table; bool ok; if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized flags: %#x\n", flags); return NULL; } if (format != XKB_COMPOSE_FORMAT_TEXT_V1) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unsupported compose format: %d\n", format); return NULL; } table = xkb_compose_table_new(ctx, locale, format, flags); if (!table) return NULL; ok = parse_file(table, file, "(unknown file)"); if (!ok) { xkb_compose_table_unref(table); return NULL; } return table; } struct xkb_compose_table * xkb_compose_table_new_from_buffer(struct xkb_context *ctx, const char *buffer, size_t length, const char *locale, enum xkb_compose_format format, enum xkb_compose_compile_flags flags) { struct xkb_compose_table *table; bool ok; if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized flags: %#x\n", flags); return NULL; } if (format != XKB_COMPOSE_FORMAT_TEXT_V1) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unsupported compose format: %d\n", format); return NULL; } table = xkb_compose_table_new(ctx, locale, format, flags); if (!table) return NULL; ok = parse_string(table, buffer, length, "(input string)"); if (!ok) { xkb_compose_table_unref(table); return NULL; } return table; } struct xkb_compose_table * xkb_compose_table_new_from_locale(struct xkb_context *ctx, const char *locale, enum xkb_compose_compile_flags flags) { struct xkb_compose_table *table; char *path; FILE *file; bool ok; if (flags & ~(XKB_COMPOSE_COMPILE_NO_FLAGS)) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized flags: %#x\n", flags); return NULL; } table = xkb_compose_table_new(ctx, locale, XKB_COMPOSE_FORMAT_TEXT_V1, flags); if (!table) return NULL; path = get_xcomposefile_path(ctx); file = open_file(path); if (file) goto found_path; free(path); path = get_xdg_xcompose_file_path(ctx); file = open_file(path); if (file) goto found_path; free(path); path = get_home_xcompose_file_path(ctx); file = open_file(path); if (file) goto found_path; free(path); path = get_locale_compose_file_path(ctx, table->locale); file = open_file(path); if (file) goto found_path; free(path); log_err(ctx, XKB_ERROR_INVALID_COMPOSE_LOCALE, "couldn't find a Compose file for locale \"%s\" (mapped to \"%s\")\n", locale, table->locale); xkb_compose_table_unref(table); return NULL; found_path: ok = parse_file(table, file, path); fclose(file); if (!ok) { free(path); xkb_compose_table_unref(table); return NULL; } log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "created compose table from locale %s with path %s\n", table->locale, path); free(path); return table; } const xkb_keysym_t * xkb_compose_table_entry_sequence(struct xkb_compose_table_entry *entry, size_t *sequence_length) { *sequence_length = entry->sequence_length; return entry->sequence; } xkb_keysym_t xkb_compose_table_entry_keysym(struct xkb_compose_table_entry *entry) { return entry->keysym; } const char * xkb_compose_table_entry_utf8(struct xkb_compose_table_entry *entry) { return entry->utf8; } #if MAX_COMPOSE_NODES_LOG2 > 31 #error "Cannot implement bit field xkb_compose_table_iterator_pending_node.offset" #endif struct xkb_compose_table_iterator_pending_node { uint32_t offset:31; bool processed:1; }; struct xkb_compose_table_iterator { struct xkb_compose_table *table; /* Current entry */ struct xkb_compose_table_entry entry; /* Stack of pending nodes to process */ darray(struct xkb_compose_table_iterator_pending_node) pending_nodes; }; struct xkb_compose_table_iterator * xkb_compose_table_iterator_new(struct xkb_compose_table *table) { struct xkb_compose_table_iterator *iter; xkb_keysym_t *sequence; iter = calloc(1, sizeof(*iter)); if (!iter) { return NULL; } iter->table = xkb_compose_table_ref(table); sequence = calloc(COMPOSE_MAX_LHS_LEN, sizeof(xkb_keysym_t)); if (!sequence) { free(iter); return NULL; } iter->entry.sequence = sequence; iter->entry.sequence_length = 0; darray_init(iter->pending_nodes); /* Short-circuit if table contains only the dummy entry */ if (darray_size(table->nodes) == 1) { return iter; } /* Add root node */ struct xkb_compose_table_iterator_pending_node pending = { .offset = 1, .processed = false }; darray_append(iter->pending_nodes, pending); const struct compose_node *node = &darray_item(iter->table->nodes, pending.offset); /* Find the first left-most node and store intermediate nodes as pending */ while (node->lokid) { pending.offset = node->lokid; darray_append(iter->pending_nodes, pending); node = &darray_item(iter->table->nodes, pending.offset); }; return iter; } void xkb_compose_table_iterator_free(struct xkb_compose_table_iterator *iter) { xkb_compose_table_unref(iter->table); darray_free(iter->pending_nodes); free(iter->entry.sequence); free(iter); } struct xkb_compose_table_entry * xkb_compose_table_iterator_next(struct xkb_compose_table_iterator *iter) { /* Traversal algorithm (simplified): * 1. Resume last pending node from the stack as the current pending node. * 2. If the node is not yet processed, go to 5. * 3. Remove node from the stack and remove last keysym from the entry. * 4. If there is a right arrow, set it as the current pending node * (unprocessed) and go to 6; else go to 1. * 5. Follow down arrow: set the pending node as processed, then: * a) if it is a leaf, complete the entry and return it. * b) else append the child node to the stack and set it as the current * pending node. * 6. Find the next left-most arrow and store intermediate pending nodes. * 7. Go to 5. */ struct xkb_compose_table_iterator_pending_node *pending; const struct compose_node *node; /* Iterator is empty if there is no pending nodes */ if (unlikely(darray_empty(iter->pending_nodes))) { return NULL; } /* Resume to the last element in the stack */ pending = &darray_item(iter->pending_nodes, darray_size(iter->pending_nodes) - 1); node = &darray_item(iter->table->nodes, pending->offset); struct xkb_compose_table_iterator_pending_node new = { .processed = false, .offset = 0 }; /* Remove processed leaves until an unprocessed right arrow or parent * is found, then update entry accordingly */ while (pending->processed) { /* Remove last keysym */ iter->entry.sequence_length--; if (node->hikid) { /* Follow right arrow: replace current pending node */ pending->processed = false; pending->offset = node->hikid; /* Process child’s left arrow */ goto node_left; } else { /* Remove processed node */ darray_remove_last(iter->pending_nodes); if (unlikely(darray_empty(iter->pending_nodes))) { /* No more nodes to process */ return NULL; } /* Get parent node */ pending = &darray_item(iter->pending_nodes, darray_size(iter->pending_nodes) - 1); node = &darray_item(iter->table->nodes, pending->offset); } } while (1) { /* Follow down arrow */ pending->processed = true; iter->entry.sequence[iter->entry.sequence_length] = node->keysym; iter->entry.sequence_length++; if (node->is_leaf) { /* Leaf: return entry */ iter->entry.keysym = node->leaf.keysym; iter->entry.utf8 = &darray_item(iter->table->utf8, node->leaf.utf8); return &iter->entry; } /* Not a leaf: process child node */ new.offset = node->internal.eqkid; darray_append(iter->pending_nodes, new); pending = &darray_item(iter->pending_nodes, darray_size(iter->pending_nodes) - 1); node_left: node = &darray_item(iter->table->nodes, pending->offset); /* Find the next left-most arrow and store intermediate pending nodes */ while (node->lokid) { /* Follow left arrow */ new.offset = node->lokid; darray_append(iter->pending_nodes, new); pending = &darray_item(iter->pending_nodes, darray_size(iter->pending_nodes) - 1); node = &darray_item(iter->table->nodes, new.offset); } } } xkbcommon-libxkbcommon-54ee7ac/src/compose/table.h000066400000000000000000000061361510033435100223650ustar00rootroot00000000000000/* * Copyright © 2013,2021 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include "xkbcommon/xkbcommon-compose.h" #include "src/utils.h" #include "src/context.h" /* * The compose table data structure is a ternary search tree. * * Reference: https://www.drdobbs.com/database/ternary-search-trees/184410528 * Visualization: https://www.cs.usfca.edu/~galles/visualization/TST.html * * Short example. Given these sequences: * * : "first" dead_a * : "second" dead_b * : "third" dead_c * * the tree would look like: * * -------- []--------- * | | # * v V * -- [] -- [] -------- * # | # | | * v # -- [] -- * -- [] -- # | # * # | # v * # -- [] -- * # | # * # * * where: * - [] is a node for a sequence keysym . * - right arrows are `hikid` pointers. * - left arrows are `lokid` pointers. * - down arrows are `eqkid` pointers. * - # is a nil pointer. * * The nodes are all kept in a contiguous array. Pointers are represented * as integer offsets into this array. A nil pointer is represented as 0 * (which, helpfully, is the offset of an empty dummy node). * * Nodes without an eqkid are leaf nodes. Since a sequence cannot be a * prefix of another, these are exactly the nodes which terminate the * sequences (in a bijective manner). * * A leaf contains the result data of its sequence. The result keysym is * contained in the node struct itself; the result UTF-8 string is a byte * offset into an array of the form "\0first\0second\0third" (the initial * \0 is so offset 0 points to an empty string). */ /* 7 nodes for every potential Unicode character and then some should be * enough for all purposes. */ #define MAX_COMPOSE_NODES_LOG2 23 #define MAX_COMPOSE_NODES (1u << MAX_COMPOSE_NODES_LOG2) struct compose_node { xkb_keysym_t keysym; /* Offset into xkb_compose_table::nodes or 0. */ uint32_t lokid; /* Offset into xkb_compose_table::nodes or 0. */ uint32_t hikid; union { struct { uint32_t _pad:31; bool is_leaf:1; }; struct { uint32_t _pad:31; bool is_leaf:1; /* Offset into xkb_compose_table::nodes or 0. */ uint32_t eqkid; } internal; struct { /* Offset into xkb_compose_table::utf8. */ uint32_t utf8:31; bool is_leaf:1; xkb_keysym_t keysym; } leaf; }; }; struct xkb_compose_table { int refcnt; enum xkb_compose_format format; enum xkb_compose_compile_flags flags; struct xkb_context *ctx; char *locale; darray_char utf8; darray(struct compose_node) nodes; }; struct xkb_compose_table_entry { xkb_keysym_t *sequence; size_t sequence_length; xkb_keysym_t keysym; const char *utf8; }; xkbcommon-libxkbcommon-54ee7ac/src/context-priv.c000066400000000000000000000116711510033435100222660ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "atom.h" #include "darray.h" #include "context.h" #include "rmlvo.h" #include "utils.h" char * xkb_context_getenv(struct xkb_context *ctx, const char *name) { if (ctx->use_secure_getenv) { return secure_getenv(name); } else { return getenv(name); } } darray_size_t xkb_context_num_failed_include_paths(struct xkb_context *ctx) { return darray_size(ctx->failed_includes); } const char * xkb_context_failed_include_path_get(struct xkb_context *ctx, darray_size_t idx) { if (idx >= xkb_context_num_failed_include_paths(ctx)) return NULL; return darray_item(ctx->failed_includes, idx); } darray_size_t xkb_atom_table_size(struct xkb_context *ctx) { return atom_table_size(ctx->atom_table); } xkb_atom_t xkb_atom_lookup(struct xkb_context *ctx, const char *string) { return atom_intern(ctx->atom_table, string, strlen(string), false); } xkb_atom_t xkb_atom_intern(struct xkb_context *ctx, const char *string, size_t len) { return atom_intern(ctx->atom_table, string, len, true); } const char * xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom) { return atom_text(ctx->atom_table, atom); } void xkb_log(struct xkb_context *ctx, enum xkb_log_level level, int verbosity, const char *fmt, ...) { va_list args; if (ctx->log_level < level || ctx->log_verbosity < verbosity) return; va_start(args, fmt); ctx->log_fn(ctx, level, fmt, args); va_end(args); } char * xkb_context_get_buffer(struct xkb_context *ctx, size_t size) { char *rtrn; if (size >= sizeof(ctx->text_buffer)) return NULL; if (sizeof(ctx->text_buffer) - ctx->text_next <= size) ctx->text_next = 0; rtrn = &ctx->text_buffer[ctx->text_next]; ctx->text_next += size; return rtrn; } static const char * xkb_context_get_default_rules(struct xkb_context *ctx) { const char *env = NULL; if (ctx->use_environment_names) env = xkb_context_getenv(ctx, "XKB_DEFAULT_RULES"); return env ? env : DEFAULT_XKB_RULES; } static const char * xkb_context_get_default_model(struct xkb_context *ctx) { const char *env = NULL; if (ctx->use_environment_names) env = xkb_context_getenv(ctx, "XKB_DEFAULT_MODEL"); return env ? env : DEFAULT_XKB_MODEL; } static const char * xkb_context_get_default_layout(struct xkb_context *ctx) { const char *env = NULL; if (ctx->use_environment_names) env = xkb_context_getenv(ctx, "XKB_DEFAULT_LAYOUT"); return env ? env : DEFAULT_XKB_LAYOUT; } static const char * xkb_context_get_default_variant(struct xkb_context *ctx) { const char *env = NULL; const char *layout = xkb_context_getenv(ctx, "XKB_DEFAULT_LAYOUT"); /* We don't want to inherit the variant if they haven't also set a * layout, since they're so closely paired. */ if (layout && ctx->use_environment_names) env = xkb_context_getenv(ctx, "XKB_DEFAULT_VARIANT"); return env ? env : DEFAULT_XKB_VARIANT; } static const char * xkb_context_get_default_options(struct xkb_context *ctx) { const char *env = NULL; if (ctx->use_environment_names) env = xkb_context_getenv(ctx, "XKB_DEFAULT_OPTIONS"); return env ? env : DEFAULT_XKB_OPTIONS; } enum RMLVO xkb_context_sanitize_rule_names(struct xkb_context *ctx, struct xkb_rule_names *rmlvo) { enum RMLVO modified = 0; if (isempty(rmlvo->rules)) { rmlvo->rules = xkb_context_get_default_rules(ctx); modified |= RMLVO_RULES; } if (isempty(rmlvo->model)) { rmlvo->model = xkb_context_get_default_model(ctx); modified |= RMLVO_MODEL; } /* Layout and variant are tied together, so don't try to use one from * the caller and one from the environment. */ if (isempty(rmlvo->layout)) { rmlvo->layout = xkb_context_get_default_layout(ctx); modified |= RMLVO_LAYOUT; const char * const variant = xkb_context_get_default_variant(ctx); if (!isempty(rmlvo->variant)) { log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "Layout not provided, but variant set to \"%s\": " "ignoring variant and using defaults for both: " "layout=\"%s\", variant=\"%s\".\n", rmlvo->variant, rmlvo->layout, variant ? variant : ""); } rmlvo->variant = variant; modified |= RMLVO_VARIANT; } /* Options can be empty, so respect that if passed in. */ if (rmlvo->options == NULL) { rmlvo->options = xkb_context_get_default_options(ctx); modified |= RMLVO_OPTIONS; } return modified; } xkbcommon-libxkbcommon-54ee7ac/src/context.c000066400000000000000000000235271510033435100213130ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #include "config.h" #include #include #include #include #include "xkbcommon/xkbcommon.h" #include "context.h" #include "messages-codes.h" #include "utils.h" /** * Append one directory to the context's include path. */ int xkb_context_include_path_append(struct xkb_context *ctx, const char *path) { int err = ENOMEM; char *tmp = strdup(path); if (!tmp) goto err; struct stat stat_buf; err = stat(path, &stat_buf); if (err != 0) { err = errno; goto err; } if (!S_ISDIR(stat_buf.st_mode)) { err = ENOTDIR; goto err; } if (!check_eaccess(path, R_OK | X_OK)) { err = EACCES; goto err; } darray_append(ctx->includes, tmp); /* Use “info” log level to facilate bug reporting. */ log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "Include path added: %s\n", tmp); return 1; err: if (tmp) darray_append(ctx->failed_includes, tmp); /* * This error is not fatal because some valid paths may still be defined. * Use “info” log level to facilate bug reporting. */ log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "Include path failed: \"%s\" (%s)\n", path, strerror(err)); return 0; } const char * xkb_context_include_path_get_extra_path(struct xkb_context *ctx) { const char * const extra = xkb_context_getenv(ctx, "XKB_CONFIG_EXTRA_PATH"); /* * Only use default if path is undefined, but accept empty string, which may * be unintentional and should be reported. */ return extra ? extra : DFLT_XKB_CONFIG_EXTRA_PATH; } const char * xkb_context_include_path_get_system_path(struct xkb_context *ctx) { const char * const root = xkb_context_getenv(ctx, "XKB_CONFIG_ROOT"); /* * Only use default if path is undefined, but accept empty string, which may * be unintentional and should be reported. */ return root ? root : DFLT_XKB_CONFIG_ROOT; } /** * Append the default include directories to the context. */ int xkb_context_include_path_append_default(struct xkb_context *ctx) { char *user_path; int ret = 0; const char * const home = xkb_context_getenv(ctx, "HOME"); const char * const xdg = xkb_context_getenv(ctx, "XDG_CONFIG_HOME"); /* Accept empty string, which may be unintentional and should be reported */ if (xdg != NULL) { user_path = asprintf_safe("%s/xkb", xdg); if (user_path) { ret |= xkb_context_include_path_append(ctx, user_path); free(user_path); } } else if (home != NULL) { /* XDG_CONFIG_HOME fallback is $HOME/.config/ */ user_path = asprintf_safe("%s/.config/xkb", home); if (user_path) { ret |= xkb_context_include_path_append(ctx, user_path); free(user_path); } } if (home != NULL) { user_path = asprintf_safe("%s/.xkb", home); if (user_path) { ret |= xkb_context_include_path_append(ctx, user_path); free(user_path); } } const char * const extra = xkb_context_include_path_get_extra_path(ctx); ret |= xkb_context_include_path_append(ctx, extra); /* Canonical XKB root */ const char * const root = xkb_context_include_path_get_system_path(ctx); const bool has_root = xkb_context_include_path_append(ctx, root); ret |= has_root; /* * Fallback for misconfigured setups. * Some setups use the assumption that the canonical XKB root is always the * legacy X11 one, but this is no longer true since xkeyboard-config 2.45, * where the X11 path is now a mere symlink to a dedicated xkeyboard-config * data directory. * This fallback can still be skipped if deliberately using an empty string * for the canonical XKB root hereinabove. */ if (!has_root && root[0] != '\0') { log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "Root include path failed; fallback to \"%s\". " "The setup is probably misconfigured. " "Please ensure that \"%s\" is available in the environment.\n", DFLT_XKB_LEGACY_ROOT, root); ret |= xkb_context_include_path_append(ctx, DFLT_XKB_LEGACY_ROOT); } return ret; } /** * Remove all entries in the context's include path. */ void xkb_context_include_path_clear(struct xkb_context *ctx) { char **path; darray_foreach(path, ctx->includes) free(*path); darray_free(ctx->includes); darray_foreach(path, ctx->failed_includes) free(*path); darray_free(ctx->failed_includes); } /** * xkb_context_include_path_clear() + xkb_context_include_path_append_default() */ int xkb_context_include_path_reset_defaults(struct xkb_context *ctx) { xkb_context_include_path_clear(ctx); return xkb_context_include_path_append_default(ctx); } /** * Returns the number of entries in the context's include path. */ unsigned int xkb_context_num_include_paths(struct xkb_context *ctx) { return darray_size(ctx->includes); } /** * Returns the given entry in the context's include path, or NULL if an * invalid index is passed. */ const char * xkb_context_include_path_get(struct xkb_context *ctx, unsigned int idx) { if (idx >= xkb_context_num_include_paths(ctx)) return NULL; return darray_item(ctx->includes, idx); } /** * Take a new reference on the context. */ struct xkb_context * xkb_context_ref(struct xkb_context *ctx) { assert(ctx->refcnt > 0); ctx->refcnt++; return ctx; } /** * Drop an existing reference on the context, and free it if the refcnt is * now 0. */ void xkb_context_unref(struct xkb_context *ctx) { assert(!ctx || ctx->refcnt > 0); if (!ctx || --ctx->refcnt > 0) return; free(ctx->x11_atom_cache); xkb_context_include_path_clear(ctx); atom_table_free(ctx->atom_table); free(ctx); } static const char * log_level_to_prefix(enum xkb_log_level level) { switch (level) { case XKB_LOG_LEVEL_DEBUG: return "xkbcommon: DEBUG: "; case XKB_LOG_LEVEL_INFO: return "xkbcommon: INFO: "; case XKB_LOG_LEVEL_WARNING: return "xkbcommon: WARNING: "; case XKB_LOG_LEVEL_ERROR: return "xkbcommon: ERROR: "; case XKB_LOG_LEVEL_CRITICAL: return "xkbcommon: CRITICAL: "; default: return NULL; } } ATTR_PRINTF(3, 0) static void default_log_fn(struct xkb_context *ctx, enum xkb_log_level level, const char *fmt, va_list args) { const char *prefix = log_level_to_prefix(level); if (prefix) fprintf(stderr, "%s", prefix); vfprintf(stderr, fmt, args); } static enum xkb_log_level log_level(const char *level) { char *endptr; enum xkb_log_level lvl; errno = 0; lvl = strtol(level, &endptr, 10); if (errno == 0 && (endptr[0] == '\0' || is_space(endptr[0]))) return lvl; if (istreq_prefix("crit", level)) return XKB_LOG_LEVEL_CRITICAL; if (istreq_prefix("err", level)) return XKB_LOG_LEVEL_ERROR; if (istreq_prefix("warn", level)) return XKB_LOG_LEVEL_WARNING; if (istreq_prefix("info", level)) return XKB_LOG_LEVEL_INFO; if (istreq_prefix("debug", level) || istreq_prefix("dbg", level)) return XKB_LOG_LEVEL_DEBUG; return XKB_LOG_LEVEL_ERROR; } static int log_verbosity(const char *verbosity) { errno = 0; const long int v = strtol(verbosity, NULL, 10); if (errno == 0) { /* Truncate */ return (int) v; } return XKB_LOG_VERBOSITY_DEFAULT; } /** * Create a new context. */ struct xkb_context * xkb_context_new(enum xkb_context_flags flags) { const char *env; struct xkb_context *ctx = calloc(1, sizeof(*ctx)); if (!ctx) return NULL; ctx->refcnt = 1; ctx->log_fn = default_log_fn; ctx->log_level = XKB_LOG_LEVEL_ERROR; ctx->log_verbosity = XKB_LOG_VERBOSITY_DEFAULT; ctx->use_environment_names = !(flags & XKB_CONTEXT_NO_ENVIRONMENT_NAMES); ctx->use_secure_getenv = !(flags & XKB_CONTEXT_NO_SECURE_GETENV); /* Environment overwrites defaults. */ env = xkb_context_getenv(ctx, "XKB_LOG_LEVEL"); if (env) xkb_context_set_log_level(ctx, log_level(env)); env = xkb_context_getenv(ctx, "XKB_LOG_VERBOSITY"); if (env) xkb_context_set_log_verbosity(ctx, log_verbosity(env)); if (!(flags & XKB_CONTEXT_NO_DEFAULT_INCLUDES) && !xkb_context_include_path_append_default(ctx)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "failed to add default include path %s\n", DFLT_XKB_CONFIG_ROOT); xkb_context_unref(ctx); return NULL; } ctx->atom_table = atom_table_new(); if (!ctx->atom_table) { xkb_context_unref(ctx); return NULL; } ctx->x11_atom_cache = NULL; return ctx; } void xkb_context_set_log_fn(struct xkb_context *ctx, void (*log_fn)(struct xkb_context *ctx, enum xkb_log_level level, const char *fmt, va_list args)) { ctx->log_fn = (log_fn ? log_fn : default_log_fn); } enum xkb_log_level xkb_context_get_log_level(struct xkb_context *ctx) { return ctx->log_level; } void xkb_context_set_log_level(struct xkb_context *ctx, enum xkb_log_level level) { ctx->log_level = level; } int xkb_context_get_log_verbosity(struct xkb_context *ctx) { return ctx->log_verbosity; } void xkb_context_set_log_verbosity(struct xkb_context *ctx, int verbosity) { ctx->log_verbosity = verbosity; } void * xkb_context_get_user_data(struct xkb_context *ctx) { if (ctx) return ctx->user_data; return NULL; } void xkb_context_set_user_data(struct xkb_context *ctx, void *user_data) { ctx->user_data = user_data; } xkbcommon-libxkbcommon-54ee7ac/src/context.h000066400000000000000000000102021510033435100213020ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #pragma once #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "atom.h" #include "darray.h" #include "messages-codes.h" #include "rmlvo.h" #include "utils.h" struct xkb_context { int refcnt; ATTR_PRINTF(3, 0) void (*log_fn)(struct xkb_context *ctx, enum xkb_log_level level, const char *fmt, va_list args); enum xkb_log_level log_level; int log_verbosity; void *user_data; struct xkb_rule_names names_dflt; darray(char *) includes; darray(char *) failed_includes; struct atom_table *atom_table; /* Used and allocated by xkbcommon-x11, free()d with the context. */ void *x11_atom_cache; /* Buffer for the *Text() functions. */ char text_buffer[2048]; size_t text_next; unsigned int use_environment_names : 1; unsigned int use_secure_getenv : 1; }; char * xkb_context_getenv(struct xkb_context *ctx, const char *name); darray_size_t xkb_context_num_failed_include_paths(struct xkb_context *ctx); const char * xkb_context_failed_include_path_get(struct xkb_context *ctx, darray_size_t idx); const char * xkb_context_include_path_get_extra_path(struct xkb_context *ctx); const char * xkb_context_include_path_get_system_path(struct xkb_context *ctx); XKB_EXPORT_PRIVATE darray_size_t xkb_atom_table_size(struct xkb_context *ctx); /* * Returns XKB_ATOM_NONE if @string was not previously interned, * otherwise returns the atom. */ xkb_atom_t xkb_atom_lookup(struct xkb_context *ctx, const char *string); XKB_EXPORT_PRIVATE xkb_atom_t xkb_atom_intern(struct xkb_context *ctx, const char *string, size_t len); #define xkb_atom_intern_literal(ctx, literal) \ xkb_atom_intern((ctx), (literal), sizeof(literal) - 1) /** * If @string is dynamically allocated, NUL-terminated, free'd immediately * after being interned, and not used afterwards, use this function * instead of xkb_atom_intern to avoid some unnecessary allocations. * The caller should not use or free the passed in string afterwards. */ xkb_atom_t xkb_atom_steal(struct xkb_context *ctx, char *string); XKB_EXPORT_PRIVATE const char * xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom); char * xkb_context_get_buffer(struct xkb_context *ctx, size_t size); XKB_EXPORT_PRIVATE ATTR_PRINTF(4, 5) void xkb_log(struct xkb_context *ctx, enum xkb_log_level level, int verbosity, const char *fmt, ...); enum RMLVO xkb_context_sanitize_rule_names(struct xkb_context *ctx, struct xkb_rule_names *rmlvo); /* * The format is not part of the argument list in order to avoid the * "ISO C99 requires rest arguments to be used" warning when only the * format is supplied without arguments. Not supplying it would still * result in an error, though. */ #define xkb_log_with_code(ctx, level, verbosity, msg_id, fmt, ...) \ xkb_log(ctx, level, verbosity, PREPEND_MESSAGE_ID(msg_id, fmt), ##__VA_ARGS__) #define log_dbg(ctx, id, ...) \ xkb_log_with_code((ctx), XKB_LOG_LEVEL_DEBUG, XKB_LOG_VERBOSITY_MINIMAL, id, __VA_ARGS__) #define log_info(ctx, id, ...) \ xkb_log_with_code((ctx), XKB_LOG_LEVEL_INFO, XKB_LOG_VERBOSITY_MINIMAL, id, __VA_ARGS__) #define log_warn(ctx, id, ...) \ xkb_log_with_code((ctx), XKB_LOG_LEVEL_WARNING, XKB_LOG_VERBOSITY_MINIMAL, id, __VA_ARGS__) #define log_vrb(ctx, vrb, id, ...) \ xkb_log_with_code((ctx), XKB_LOG_LEVEL_WARNING, (vrb), id, __VA_ARGS__) #define log_err(ctx, id, ...) \ xkb_log_with_code((ctx), XKB_LOG_LEVEL_ERROR, XKB_LOG_VERBOSITY_MINIMAL, id, __VA_ARGS__) #define log_wsgo(ctx, id, ...) \ xkb_log_with_code((ctx), XKB_LOG_LEVEL_CRITICAL, XKB_LOG_VERBOSITY_MINIMAL, id, __VA_ARGS__) /* * Variants which are prefixed by the name of the function they're * called from. * Here we must have the silly 1 variant. */ #define log_err_func(ctx, id, fmt, ...) \ log_err(ctx, id, "%s: " fmt, __func__, __VA_ARGS__) #define log_err_func1(ctx, id, fmt) \ log_err(ctx, id, "%s: " fmt, __func__) xkbcommon-libxkbcommon-54ee7ac/src/darray.h000066400000000000000000000166161510033435100211170ustar00rootroot00000000000000/* * Copyright (C) 2011 Joseph Adams * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" /* Originally taken from: https://ccodearchive.net/info/darray.html * But modified for libxkbcommon. */ #include #include #include #include typedef unsigned int darray_size_t; #define DARRAY_SIZE_T_WIDTH (sizeof(darray_size_t) * CHAR_BIT) #define DARRAY_SIZE_MAX UINT_MAX #define darray(type) struct { \ /** Array of items */ \ type *item; \ /** Current size */ \ darray_size_t size; \ /** Count of allocated items */ \ darray_size_t alloc; \ } #define darray_new() { 0, 0, 0 } #define darray_init(arr) do { \ (arr).item = 0; (arr).size = 0; (arr).alloc = 0; \ } while (0) #define darray_free(arr) do { \ free((arr).item); \ darray_init(arr); \ } while (0) #define darray_steal(arr, to, to_size) do { \ *(to) = (arr).item; \ if (to_size) \ *(darray_size_t *) (to_size) = (arr).size; \ darray_init(arr); \ } while (0) /* * Typedefs for darrays of common types. These are useful * when you want to pass a pointer to an darray(T) around. * * The following will produce an incompatible pointer warning: * * void foo(darray(int) *arr); * darray(int) arr = darray_new(); * foo(&arr); * * The workaround: * * void foo(darray_int *arr); * darray_int arr = darray_new(); * foo(&arr); */ typedef darray (char) darray_char; typedef darray (signed char) darray_schar; typedef darray (unsigned char) darray_uchar; typedef darray (short) darray_short; typedef darray (int) darray_int; typedef darray (long) darray_long; typedef darray (unsigned short) darray_ushort; typedef darray (unsigned int) darray_uint; typedef darray (unsigned long) darray_ulong; /*** Access ***/ #define darray_item(arr, i) ((arr).item[i]) #define darray_items(arr) ((arr).item) #define darray_size(arr) ((arr).size) #define darray_empty(arr) ((arr).size == 0) /*** Insertion (single item) ***/ #define darray_append(arr, ...) do { \ darray_resize(arr, (arr).size + 1); \ (arr).item[(arr).size - 1] = (__VA_ARGS__); \ } while (0) #define darray_insert(arr, i, ...) do { \ darray_size_t __index = (i); \ darray_resize(arr, (arr).size+1); \ memmove( \ (arr).item + __index + 1, \ (arr).item + __index, \ ((arr).size - __index - 1) * sizeof(*(arr).item) \ ); \ (arr).item[__index] = (__VA_ARGS__); \ } while(0) /*** Insertion (multiple items) ***/ #define darray_append_items(arr, items, count) do { \ darray_size_t __count = (count), __oldSize = (arr).size; \ darray_resize(arr, __oldSize + __count); \ memcpy((arr).item + __oldSize, items, __count * sizeof(*(arr).item)); \ } while (0) #define darray_from_items(arr, items, count) do { \ darray_size_t __count = (count); \ darray_resize(arr, __count); \ if (__count != 0) \ memcpy((arr).item, items, __count * sizeof(*(arr).item)); \ } while (0) #define darray_copy(arr_to, arr_from) \ darray_from_items((arr_to), (arr_from).item, (arr_from).size) #define darray_concat(arr_to, arr_from) do { \ if ((arr_from).size > 0) \ darray_append_items((arr_to), (arr_from).item, (arr_from).size); \ } while (0) /*** Removal ***/ /* Warning: Do not call darray_remove_last on an empty darray. */ #define darray_remove_last(arr) (--(arr).size) /* Warning, slow: Requires copying all elements after removed item. */ #define darray_remove(arr, i) do { \ darray_size_t __index = (i); \ if (__index < (arr).size-1) \ memmove( \ &(arr).item[__index], \ &(arr).item[__index + 1], \ ((arr).size -1 - __index) * sizeof(*(arr).item) \ ); \ (arr).size--; \ } while(0) /*** String buffer ***/ #define darray_append_string(arr, str) do { \ const char *__str = (str); \ darray_append_items(arr, __str, (darray_size_t) strlen(__str) + 1); \ (arr).size--; \ } while (0) /* Same as `darray_append_string` but do count the final '\0' in the size */ #define darray_append_string0(arr, string) \ darray_append_items((arr), (string), strlen(string) + 1) #define darray_append_lit(arr, stringLiteral) do { \ darray_append_items(arr, stringLiteral, \ (darray_size_t) sizeof(stringLiteral)); \ (arr).size--; \ } while (0) #define darray_appends_nullterminate(arr, items, count) do { \ darray_size_t __count = (count), __oldSize = (arr).size; \ darray_resize(arr, __oldSize + __count + 1); \ memcpy((arr).item + __oldSize, items, __count * sizeof(*(arr).item)); \ (arr).item[--(arr).size] = 0; \ } while (0) #define darray_prepends_nullterminate(arr, items, count) do { \ darray_size_t __count = (count), __oldSize = (arr).size; \ darray_resize(arr, __count + __oldSize + 1); \ memmove((arr).item + __count, (arr).item, \ __oldSize * sizeof(*(arr).item)); \ memcpy((arr).item, items, __count * sizeof(*(arr).item)); \ (arr).item[--(arr).size] = 0; \ } while (0) /*** Size management ***/ #define darray_resize(arr, newSize) \ darray_growalloc(arr, (arr).size = (newSize)) #define darray_resize0(arr, newSize) do { \ darray_size_t __oldSize = (arr).size, __newSize = (newSize); \ (arr).size = __newSize; \ if (__newSize > __oldSize) { \ darray_growalloc(arr, __newSize); \ memset(&(arr).item[__oldSize], 0, \ (__newSize - __oldSize) * sizeof(*(arr).item)); \ } \ } while (0) #define darray_realloc(arr, newAlloc) do { \ (arr).item = realloc((arr).item, \ ((arr).alloc = (newAlloc)) * sizeof(*(arr).item)); \ } while (0) #define darray_growalloc(arr, need) do { \ darray_size_t __need = (need); \ if (__need > (arr).alloc) \ darray_realloc(arr, darray_next_alloc((arr).alloc, __need, \ sizeof(*(arr).item))); \ } while (0) #define darray_shrink(arr) do { \ if ((arr).size > 0) \ (arr).item = realloc((arr).item, \ ((arr).alloc = (arr).size) * sizeof(*(arr).item)); \ } while (0) #define darray_max_alloc(itemSize) (UINT_MAX / (itemSize)) static inline darray_size_t darray_next_alloc(darray_size_t alloc, darray_size_t need, size_t itemSize) { assert(need < darray_max_alloc(itemSize) / 2); /* Overflow. */ if (alloc == 0) alloc = 4; while (alloc < need) alloc *= 2; return alloc; } /*** Traversal ***/ #define darray_foreach(i, arr) \ if ((arr).item) \ for ((i) = &(arr).item[0]; (i) < &(arr).item[(arr).size]; (i)++) #define darray_foreach_from(i, arr, from) \ if ((arr).item) \ for ((i) = &(arr).item[from]; (i) < &(arr).item[(arr).size]; (i)++) /* Iterate on index and value at the same time, like Python's enumerate. */ #define darray_enumerate(idx, val, arr) \ if ((arr).item) \ for ((idx) = 0, (val) = &(arr).item[0]; \ (idx) < (arr).size; \ (idx)++, (val)++) #define darray_enumerate_from(idx, val, arr, from) \ if ((arr).item) \ for ((idx) = (from), (val) = &(arr).item[from]; \ (idx) < (arr).size; \ (idx)++, (val)++) #define darray_foreach_reverse(i, arr) \ if ((arr).item) \ for ((i) = &(arr).item[(arr).size - 1]; (arr).size > 0 && (i) >= &(arr).item[0]; (i)--) xkbcommon-libxkbcommon-54ee7ac/src/keymap-compare.c000066400000000000000000000565231510033435100225430ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "keymap.h" #include "src/messages-codes.h" #include "src/utils.h" #include "xkbcommon/xkbcommon.h" #include "keymap-compare.h" /* * NOTE: these keymap comparison utilities are pretty basic and require that * items have the *same order* in the compared keymaps. */ /* TODO: enable to relax the order on some items, such as: aliases, etc. */ static bool keymap_compare_mods(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2) { bool identical = true; /* Check that the keymaps have the same virtual modifiers */ /* Check common modifiers*/ const xkb_mod_index_t mod_max = MIN(keymap1->mods.num_mods, keymap2->mods.num_mods); for (xkb_mod_index_t mod = 0; mod < mod_max; mod++) { const struct xkb_mod * const mod1 = &keymap1->mods.mods[mod]; const struct xkb_mod * const mod2 = &keymap2->mods.mods[mod]; /* NOTE: cannot compare atoms: keymaps may use different contexts */ const char * const name1 = xkb_atom_text(keymap1->ctx, mod1->name); const char * const name2 = xkb_atom_text(keymap2->ctx, mod2->name); if (!streq_null(name1, name2)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Modifier #%"PRIu32" names do not match: " "\"%s\" != \"%s\"\n", mod, name1, name2); identical = false; } if (mod1->type != mod2->type) { /* Unlikely, only for completeness */ log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Modifier #%"PRIu32" types do not match: " "%d != %d\n", mod, mod1->type, mod2->type); identical = false; } if (mod1->mapping != mod2->mapping) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Modifier #%"PRIu32" mappings do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", mod, mod1->mapping, mod2->mapping); identical = false; } } /* Check non-common modifiers */ if (keymap1->mods.num_mods != keymap2->mods.num_mods) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Modifiers counts do not match: %"PRIu32" != %"PRIu32"\n", keymap1->mods.num_mods, keymap2->mods.num_mods); identical = false; } return identical; } static bool keymap_compare_keycodes(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2) { bool identical = true; /* * Check keycode range */ if (keymap1->num_keys != keymap2->num_keys) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Keycodes counts do not match: %"PRIu32" != %"PRIu32"\n", keymap1->num_keys, keymap2->num_keys); identical = false; } if (keymap1->min_key_code != keymap2->min_key_code) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Min keycodes do not match: %"PRIu32" != %"PRIu32"\n", keymap1->min_key_code, keymap2->min_key_code); identical = false; } if (keymap1->max_key_code != keymap2->max_key_code) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Low keycodes counts do not match: %"PRIu32" != %"PRIu32"\n", keymap1->num_keys_low, keymap2->num_keys_low); identical = false; } if (keymap1->max_key_code != keymap2->max_key_code) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Max keycodes do not match: %"PRIu32" != %"PRIu32"\n", keymap1->min_key_code, keymap2->min_key_code); identical = false; } /* Check common keys */ const xkb_keycode_t k_max = MIN(keymap1->num_keys, keymap2->num_keys); for (xkb_keycode_t k = 0; k < k_max; k++) { const struct xkb_key * const key1 = &keymap1->keys[k]; const struct xkb_key * const key2 = &keymap1->keys[k]; if (key1->keycode != key2->keycode) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key #%"PRIu32" keycodes do not match: " "%"PRIx32" != %"PRIx32"\n", k, key1->keycode, key2->keycode); identical = false; /* It does not make sense to compare further properties */ continue; } const xkb_keycode_t kc = key1->keycode; /* NOTE: cannot compare atoms: keymaps may use different contexts */ const char * const name1 = xkb_atom_text(keymap1->ctx, key1->name); const char * const name2 = xkb_atom_text(keymap2->ctx, key2->name); if (!streq_null(name1, name2)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32" names do not match: " "\"%s\" != \"%s\"\n", kc, name1, name2); identical = false; } } /* Check common aliases */ const darray_size_t a_max = MIN(keymap1->num_key_aliases, keymap2->num_key_aliases); for (darray_size_t a = 0; a < a_max; a++) { const struct xkb_key_alias * const entry1 = &keymap1->key_aliases[a]; const struct xkb_key_alias * const entry2 = &keymap2->key_aliases[a]; /* NOTE: cannot compare atoms: keymaps may use different contexts */ const char * const alias1 = xkb_atom_text(keymap1->ctx, entry1->alias); const char * const alias2 = xkb_atom_text(keymap2->ctx, entry2->alias); if (!streq_null(alias1, alias2)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Alias #%u names do not match: \"%s\" != \"%s\"\n", a, alias1, alias2); identical = false; } const char * const real1 = xkb_atom_text(keymap1->ctx, entry1->real); const char * const real2 = xkb_atom_text(keymap2->ctx, entry2->real); if (!streq_null(real1, real2)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Alias #%u \"%s\" target do not match: \"%s\" != \"%s\"\n", a, alias1, real1, real2); identical = false; } } if (keymap1->num_key_aliases != keymap2->num_key_aliases) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Aliases count do not match: %u != %u\n", keymap1->num_key_aliases, keymap2->num_key_aliases); identical = false; } return identical; } static bool keymap_compare_leds(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2) { bool identical = true; /* Check common LEDs */ xkb_led_index_t led_max = MIN(keymap1->num_leds, keymap2->num_leds); for (xkb_led_index_t led = 0; led < led_max; led++) { const struct xkb_led * const led1 = &keymap1->leds[led]; const struct xkb_led * const led2 = &keymap2->leds[led]; /* NOTE: cannot compare atoms: keymaps may use different contexts */ const char * const name1 = xkb_atom_text(keymap1->ctx, led1->name); const char * const name2 = xkb_atom_text(keymap2->ctx, led2->name); if (!streq_null(name1, name2)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "LED #%"PRIu32" names do not match: \"%s\" != \"%s\"\n", led, name1, name2); identical = false; } if (led1->which_groups != led2->which_groups) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "LED #%"PRIu32" \"%s\" `which_groups` do not match: " "0x%x != 0x%x\n", led, name1, led1->which_groups, led2->which_groups); identical = false; } if (led1->groups != led2->groups) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "LED #%"PRIu32" \"%s\" `groups` do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", led, name1, led1->groups, led2->groups); identical = false; } if (led1->which_mods != led2->which_mods) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "LED #%"PRIu32" \"%s\" `which_mods` do not match: " "0x%x != 0x%x\n", led, name1, led1->which_mods, led2->which_mods); identical = false; } if (led1->mods.mods != led2->mods.mods) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "LED #%"PRIu32" \"%s\" `mods` do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", led, name1, led1->mods.mods, led2->mods.mods); identical = false; } if (led1->ctrls != led2->ctrls) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "LED #%"PRIu32" \"%s\" `ctrls` do not match: " "0x%x != 0x%x\n", led, name1, led1->ctrls, led2->ctrls); identical = false; } } if (keymap1->num_leds != keymap2->num_leds) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "LEDs count do not match: %"PRIu32" != %"PRIu32"\n", keymap1->num_leds, keymap2->num_leds); identical = false; } return identical; } static bool compare_types(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2, const struct xkb_key_type *type1, const struct xkb_key_type *type2) { bool identical = true; /* NOTE: cannot compare atoms: keymaps may use different contexts */ const char * const name1 = xkb_atom_text(keymap1->ctx, type1->name); const char * const name2 = xkb_atom_text(keymap2->ctx, type2->name); if (!streq_null(name1, name2)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type names do not match: \"%s\" != \"%s\"\n", name1, name2); identical = false; } /* From here we will use the name of `type1` as the reference */ if (type1->mods.mods != type2->mods.mods) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type \"%s\" mods do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", name1, type1->mods.mods, type2->mods.mods); /* No point to check further properties */ return false; } if (type1->num_levels != type2->num_levels) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type \"%s\" levels count do not match: " "%"PRIu32" != %"PRIu32"\n", name1, type1->num_levels, type2->num_levels); /* No point to check further properties */ return false; } if (type1->num_level_names != type2->num_level_names) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type \"%s\" level names count do not match: " "%"PRIu32" != %"PRIu32"\n", name1, type1->num_level_names, type2->num_level_names); identical = false; } else { for (xkb_level_index_t l = 0; l < type1->num_level_names; l++) { /* NOTE: cannot compare atoms: keymaps may use different contexts */ const char * const lname1 = xkb_atom_text(keymap1->ctx, type1->level_names[l]); const char * const lname2 = xkb_atom_text(keymap2->ctx, type2->level_names[l]); if (!streq_null(lname1, lname2)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type \"%s\" level #%"PRIu32" names do not match: " "\"%s\" != \"%s\"\n", name1, l, lname1, lname2); identical = false; } } } if (type1->num_entries != type2->num_entries) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type \"%s\" entries count do not match: " "%"PRIu32" != %"PRIu32"\n", name1, type1->num_entries, type2->num_entries); identical = false; } else { for (darray_size_t e = 0; e < type1->num_entries; e++) { const struct xkb_key_type_entry * const entry1 = &type1->entries[e]; const struct xkb_key_type_entry * const entry2 = &type2->entries[e]; if (entry1->level != entry2->level) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type \"%s\" entry #%u levels do not match: " "%"PRIu32" != %"PRIu32"\n", name1, e, entry1->level, entry2->level); identical = false; } if (entry1->mods.mods != entry2->mods.mods) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type \"%s\" entry #%u mods do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", name1, e, entry1->mods.mods, entry2->mods.mods); identical = false; } if (entry1->preserve.mods != entry2->preserve.mods) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key type \"%s\" entry #%u preserve do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", name1, e, entry1->preserve.mods, entry2->preserve.mods); identical = false; } } } return identical; } static bool keymap_compare_types(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2) { bool identical = true; /* Compare common types */ const darray_size_t t_max = MIN(keymap1->num_types, keymap2->num_types); for (darray_size_t t = 0; t < t_max; t++) { identical = compare_types(ctx, keymap1, keymap2, &keymap1->types[t], &keymap2->types[t]) && identical; } if (keymap1->num_types != keymap2->num_types) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key types counts do not match: %u != %u\n", keymap1->num_types, keymap2->num_types); identical = false; } return identical; } static bool compare_groups(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2, xkb_keycode_t kc, xkb_layout_index_t g, const struct xkb_group *group1, const struct xkb_group *group2) { /* TODO: repeatedly compare the same key types is inefficient!! */ if (!compare_types(ctx, keymap1, keymap2, group1->type, group2->type)) { const char * const name1 = xkb_atom_text(keymap1->ctx, group1->type->name); const char * const name2 = xkb_atom_text(keymap2->ctx, group2->type->name); log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32"/group %"PRIu32" types do not match: " "\"%s\" != \"%s\"\n", kc, g, name1, name2); /* No relevant to compare groups with different types */ return false; } assert(group1->type->num_levels == group2->type->num_levels); bool identical = true; for (xkb_level_index_t l = 0; l < group1->type->num_levels; l++) { const struct xkb_level * const level1 = &group1->levels[l]; const struct xkb_level * const level2 = &group2->levels[l]; /* Keysyms */ if (level1->num_syms != level2->num_syms) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32"/group %"PRIu32"/level %"PRIu32" " "keysyms count do not match: %u != %u\n", kc, g, l, level1->num_syms, level2->num_syms); identical = false; } else { if (level1->num_syms > 1) { for (xkb_keysym_count_t k = 0; k < level1->num_syms; k++) { if (level1->s.syms[k] == level2->s.syms[k]) continue; log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32"/group %"PRIu32"/level %"PRIu32" " "keysyms #%u do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", kc, g, l, k, level1->s.syms[k], level2->s.syms[k]); identical = false; } } else if (level1->s.sym != level2->s.sym) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32"/group %"PRIu32"/level %"PRIu32" " "keysyms do not match: 0x%"PRIx32" != 0x%"PRIx32"\n", kc, g, l, level1->s.sym, level2->s.sym); identical = false; } } /* Actions */ if (level1->num_actions != level2->num_actions) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32"/group %"PRIu32"/level %"PRIu32" " "actions count do not match: %u != %u\n", kc, g, l, level1->num_actions, level2->num_actions); identical = false; } else { if (level1->num_actions > 1) { for (xkb_action_count_t a = 0; a < level1->num_actions; a++) { if (action_equal(&level1->a.actions[a], &level2->a.actions[a])) continue; log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32"/group %"PRIu32"/level %"PRIu32" " "actions #%u do not match\n", kc, g, l, a); identical = false; } } else if (level1->num_actions == 1 && !action_equal(&level1->a.action, &level2->a.action)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32"/group %"PRIu32"/level %"PRIu32" " "actions do not match\n", kc, g, l); identical = false; } } } return identical; } static bool keymap_compare_symbols(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2) { bool identical = true; /* * Check groups */ if (keymap1->num_groups != keymap2->num_groups) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Group counts do not match: %"PRIu32" != %"PRIu32"\n", keymap1->num_groups, keymap2->num_groups); identical = false; } if (keymap1->num_group_names != keymap2->num_group_names) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Group name counts do not match: %"PRIu32" != %"PRIu32"\n", keymap1->num_group_names, keymap2->num_group_names); identical = false; } else { for (xkb_layout_index_t g = 0; g < keymap1->num_group_names; g++) { /* NOTE: cannot compare atoms: keymaps may use different contexts */ const char * const name1 = xkb_atom_text(keymap1->ctx, keymap1->group_names[g]); const char * const name2 = xkb_atom_text(keymap2->ctx, keymap2->group_names[g]); if (!streq_null(name1, name2)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Group #%"PRIu32" names do not match: " "\"%s\" != \"%s\"\n", g, name1, name2); identical = false; } } } /* * Check common keycodes */ const xkb_keycode_t k_max = MIN(keymap1->num_keys, keymap2->num_keys); for (xkb_keycode_t k = 0; k < k_max; k++) { const struct xkb_key * const key1 = &keymap1->keys[k]; const struct xkb_key * const key2 = &keymap1->keys[k]; if (key1->keycode != key2->keycode) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key #%"PRIu32" keycodes do not match: " "%"PRIx32" != %"PRIx32"\n", k, key1->keycode, key2->keycode); identical = false; /* It does not make sense to compare further properties */ continue; } const xkb_keycode_t kc = key1->keycode; /* NOTE: key name checked in `compare_keycodes()` */ if (key1->modmap != key2->modmap) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32" modmap do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", kc, key1->modmap, key2->modmap); identical = false; } if (key1->vmodmap != key2->vmodmap) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32" vmodmap do not match: " "0x%"PRIx32" != 0x%"PRIx32"\n", kc, key1->vmodmap, key2->vmodmap); identical = false; } if (key1->repeats != key2->repeats) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32" repeats do not match: " "%d != %d\n", kc, key1->repeats, key2->repeats); identical = false; } if (key1->out_of_range_group_action != key2->out_of_range_group_action || key1->out_of_range_group_number != key2->out_of_range_group_number) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32" out-of-range do not match: " "%d != %d or %"PRIu32" != %"PRIu32"\n", kc, key1->out_of_range_group_action, key2->out_of_range_group_action, key1->out_of_range_group_number, key2->out_of_range_group_number); identical = false; } if (key1->num_groups != key2->num_groups) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Key 0x%"PRIx32" groups counts do not match: " "%"PRIu32" != %"PRIu32"\n", kc, key1->num_groups, key2->num_groups); identical = false; } const xkb_layout_index_t g_max = MIN(key1->num_groups, key2->num_groups); for (xkb_layout_index_t g = 0; g < g_max; g++) { identical = compare_groups(ctx, keymap1, keymap2, kc, g, &key1->groups[g], &key2->groups[g]) && identical; } } return identical; } /** * Compare two keymaps. * * This is primarily aimed for testing if two keymaps compiled from different * sources have the same properties. * * Return `true` if the properties to compare are identical, `false` otherwise. */ bool xkb_keymap_compare(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2, enum xkb_keymap_compare_property properties) { bool identical = true; if (properties & XKB_KEYMAP_CMP_MODS) { identical = keymap_compare_mods(ctx, keymap1, keymap2) && identical; } if (properties & XKB_KEYMAP_CMP_TYPES) { identical = keymap_compare_types(ctx, keymap1, keymap2) && identical; } if (properties & XKB_KEYMAP_CMP_LEDS) { identical = keymap_compare_leds(ctx, keymap1, keymap2) && identical; } if (properties & XKB_KEYMAP_CMP_KEYCODES) { identical = keymap_compare_keycodes(ctx, keymap1, keymap2) && identical; } if (properties & XKB_KEYMAP_CMP_SYMBOLS) { identical = keymap_compare_symbols(ctx, keymap1, keymap2) && identical; } return identical; } xkbcommon-libxkbcommon-54ee7ac/src/keymap-compare.h000066400000000000000000000022011510033435100225300ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "utils.h" /** * Keymap properties to compare in `xkb_keymap_compare()`. * * The level of detail should be adjusted to the need. */ enum xkb_keymap_compare_property { XKB_KEYMAP_CMP_MODS = (1u << 0), XKB_KEYMAP_CMP_LEDS = (1u << 1), XKB_KEYMAP_CMP_TYPES = (1u << 2), /* TODO: compat entries */ XKB_KEYMAP_CMP_KEYCODES = (1u << 3), XKB_KEYMAP_CMP_SYMBOLS = (1u << 4), XKB_KEYMAP_CMP_ALL = XKB_KEYMAP_CMP_MODS | XKB_KEYMAP_CMP_LEDS | XKB_KEYMAP_CMP_TYPES | XKB_KEYMAP_CMP_KEYCODES | XKB_KEYMAP_CMP_SYMBOLS, /* TODO: add interprets to next */ XKB_KEYMAP_CMP_POSSIBLY_DROPPED = XKB_KEYMAP_CMP_TYPES, }; XKB_EXPORT_PRIVATE bool xkb_keymap_compare(struct xkb_context *ctx, const struct xkb_keymap *keymap1, const struct xkb_keymap *keymap2, enum xkb_keymap_compare_property properties); xkbcommon-libxkbcommon-54ee7ac/src/keymap-formats.c000066400000000000000000000037041510033435100225610ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "utils.h" #include "keymap-formats.h" /* [WARNING] Must be in ascending order */ static const enum xkb_keymap_format keymap_formats[] = { XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_FORMAT_TEXT_V2, }; /* * Human-friendly formats labels * * They are aimed to be used in the CLI tools and to be *stable*. While the * current labels are simply “v” + corresponding `xkb_keymap_format` values, it * may change in the future. Indeed, `xkb_keymap_format` encoding may change * (although we avoit it) while the corresponding labels remain unchanged. */ struct format_label { const char* label; enum xkb_keymap_format format; }; static const struct format_label keymap_formats_labels [] = { { "v1", XKB_KEYMAP_FORMAT_TEXT_V1 }, { "v2", XKB_KEYMAP_FORMAT_TEXT_V2 }, }; size_t xkb_keymap_supported_formats(const enum xkb_keymap_format **formats) { *formats = keymap_formats; return ARRAY_SIZE(keymap_formats); } bool xkb_keymap_is_supported_format(enum xkb_keymap_format format) { for (size_t k = 0; k < ARRAY_SIZE(keymap_formats); k++) { if (keymap_formats[k] == format) return true; /* Short-circuit because array is sorted */ if (keymap_formats[k] > format) return false; } return false; } enum xkb_keymap_format xkb_keymap_parse_format(const char *raw) { if (!raw) return 0; if (raw[0] != 'v') { /* Parse numeric format */ const int format = atoi(raw); return (xkb_keymap_is_supported_format(format)) ? format : 0; } else { /* Parse format label: “vXXX” */ for (size_t k = 0; k < ARRAY_SIZE(keymap_formats_labels); k++) { if (strcmp(raw, keymap_formats_labels[k].label) == 0) return keymap_formats_labels[k].format; } return 0; } } xkbcommon-libxkbcommon-54ee7ac/src/keymap-formats.h000066400000000000000000000021101510033435100225540ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include "xkbcommon/xkbcommon.h" #define DEFAULT_INPUT_KEYMAP_FORMAT XKB_KEYMAP_FORMAT_TEXT_V2 #define DEFAULT_OUTPUT_KEYMAP_FORMAT XKB_KEYMAP_USE_ORIGINAL_FORMAT /** * Provide an array of the supported keymap formats, sorted in ascending order * (newest last). * * @param[out] formats An array of the supported keymap formats. * * @returns The size of the array. * * @memberof xkb_keymap */ size_t xkb_keymap_supported_formats(const enum xkb_keymap_format **formats); /** * Check if the given keymap format is supported. * * @param[in] format A keymap format to test. * * @memberof xkb_keymap */ bool xkb_keymap_is_supported_format(enum xkb_keymap_format format); /** * Parse a keymap version. * * @param[in] raw A raw keymap format string. May be the numeric value or the * label of the version, starting with `v`. * * @return The corresponding format or 0 on error. */ enum xkb_keymap_format xkb_keymap_parse_format(const char *raw); xkbcommon-libxkbcommon-54ee7ac/src/keymap-priv.c000066400000000000000000000213331510033435100220640ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon-names.h" #include "keymap.h" static void update_builtin_keymap_fields(struct xkb_keymap *keymap) { /* Predefined (AKA real, core, X11) modifiers. The order is important! */ static const char *const builtin_mods[] = { [XKB_MOD_INDEX_SHIFT] = XKB_MOD_NAME_SHIFT, [XKB_MOD_INDEX_CAPS] = XKB_MOD_NAME_CAPS, [XKB_MOD_INDEX_CTRL] = XKB_MOD_NAME_CTRL, [XKB_MOD_INDEX_MOD1] = XKB_MOD_NAME_MOD1, [XKB_MOD_INDEX_MOD2] = XKB_MOD_NAME_MOD2, [XKB_MOD_INDEX_MOD3] = XKB_MOD_NAME_MOD3, [XKB_MOD_INDEX_MOD4] = XKB_MOD_NAME_MOD4, [XKB_MOD_INDEX_MOD5] = XKB_MOD_NAME_MOD5 }; for (xkb_mod_index_t i = 0; i < ARRAY_SIZE(builtin_mods); i++) { keymap->mods.mods[i].name = xkb_atom_intern(keymap->ctx, builtin_mods[i], strlen(builtin_mods[i])); keymap->mods.mods[i].type = MOD_REAL; /* Real modifiers have a canonical mapping */ keymap->mods.mods[i].mapping = UINT32_C(1) << i; } keymap->mods.num_mods = ARRAY_SIZE(builtin_mods); keymap->canonical_state_mask = MOD_REAL_MASK_ALL; } struct xkb_keymap * xkb_keymap_new(struct xkb_context *ctx, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { struct xkb_keymap *keymap; keymap = calloc(1, sizeof(*keymap)); if (!keymap) return NULL; keymap->refcnt = 1; keymap->ctx = xkb_context_ref(ctx); keymap->format = format; keymap->flags = flags; update_builtin_keymap_fields(keymap); return keymap; } void XkbEscapeMapName(char *name) { /* * All latin-1 alphanumerics, plus parens, slash, minus, underscore and * wildcards. */ static const unsigned char legal[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x83, 0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff }; if (!name) return; while (*name) { unsigned char c = *name; if (!(legal[c / 8] & (1u << (c % 8)))) *name = '_'; name++; } } xkb_mod_index_t XkbModNameToIndex(const struct xkb_mod_set *mods, xkb_atom_t name, enum mod_type type) { xkb_mod_index_t i; const struct xkb_mod *mod; xkb_mods_enumerate(i, mod, mods) if ((mod->type & type) && name == mod->name) return i; return XKB_MOD_INVALID; } bool XkbLevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b) { if (a->num_syms != b->num_syms) return false; if (a->num_syms <= 1) return a->s.sym == b->s.sym; return memcmp(a->s.syms, b->s.syms, sizeof(*a->s.syms) * a->num_syms) == 0; } bool action_equal(const union xkb_action *a, const union xkb_action *b) { if (a->type != b->type) return false; /* Ensure we support all action types */ static_assert(ACTION_TYPE_INTERNAL == 18 && ACTION_TYPE_INTERNAL + 1 == _ACTION_TYPE_NUM_ENTRIES, "Missing action type"); switch (a->type) { case ACTION_TYPE_NONE: case ACTION_TYPE_VOID: return true; case ACTION_TYPE_MOD_SET: case ACTION_TYPE_MOD_LATCH: case ACTION_TYPE_MOD_LOCK: return (a->mods.flags == b->mods.flags && a->mods.mods.mask == b->mods.mods.mask && a->mods.mods.mods == b->mods.mods.mods); case ACTION_TYPE_GROUP_SET: case ACTION_TYPE_GROUP_LATCH: case ACTION_TYPE_GROUP_LOCK: return (a->group.flags == b->group.flags && a->group.group == b->group.group); case ACTION_TYPE_PTR_MOVE: return (a->ptr.flags == b->ptr.flags && a->ptr.x == b->ptr.x && a->ptr.y == b->ptr.y); case ACTION_TYPE_PTR_BUTTON: case ACTION_TYPE_PTR_LOCK: return (a->btn.flags == b->btn.flags && a->btn.button == b->btn.button && a->btn.count == b->btn.count); case ACTION_TYPE_PTR_DEFAULT: return (a->dflt.flags == b->dflt.flags && a->dflt.value == b->dflt.value); case ACTION_TYPE_TERMINATE: return true; case ACTION_TYPE_SWITCH_VT: return (a->screen.flags == b->screen.flags && a->screen.screen == b->screen.screen); case ACTION_TYPE_CTRL_SET: case ACTION_TYPE_CTRL_LOCK: return (a->ctrls.flags == b->ctrls.flags && a->ctrls.ctrls == b->ctrls.ctrls); case ACTION_TYPE_UNSUPPORTED_LEGACY: return true; /* ACTION_TYPE_PRIVATE processed in the default case */ case ACTION_TYPE_INTERNAL: return (a->internal.flags == b->internal.flags) && (a->internal.clear_latched_mods == b->internal.clear_latched_mods); default: {} /* Label followed by declaration requires C23 */ /* Ensure to not miss `xkb_action_type` updates */ static_assert(ACTION_TYPE_INTERNAL == 18 && ACTION_TYPE_INTERNAL + 1 == _ACTION_TYPE_NUM_ENTRIES, "Missing action type"); /* Private/custom action */ return memcmp(a->priv.data, b->priv.data, sizeof(a->priv.data)) == 0; } } bool XkbLevelsSameActions(const struct xkb_level *a, const struct xkb_level *b) { if (a->num_actions != b->num_actions) return false; if (a->num_actions <= 1) return action_equal(&a->a.action, &b->a.action); for (xkb_action_count_t k = 0; k < a->num_actions; k++) { if (!action_equal(&a->a.actions[k], &b->a.actions[k])) return false; } return true; } /* See: XkbAdjustGroup in Xorg xserver */ xkb_layout_index_t XkbWrapGroupIntoRange(int32_t group, xkb_layout_index_t num_groups, enum xkb_range_exceed_type out_of_range_group_action, xkb_layout_index_t out_of_range_group_number) { if (num_groups == 0) return XKB_LAYOUT_INVALID; if (group >= 0 && (xkb_layout_index_t) group < num_groups) return group; switch (out_of_range_group_action) { case RANGE_REDIRECT: if (out_of_range_group_number >= num_groups) return 0; return out_of_range_group_number; case RANGE_SATURATE: if (group < 0) return 0; else return num_groups - 1; case RANGE_WRAP: default: { /* * Ensure conversion xkb_layout_index_t → int32_t is lossless. * * NOTE: C11 requires a compound statement because it does not allow * a declaration after a label (C23 does allow it). */ static_assert(XKB_MAX_GROUPS < INT32_MAX, "Max groups max don't fit"); /* * % returns the *remainder* of the division, not the modulus (see C11 * standard 6.5.5 “Multiplicative operators”: a % b = a - (a/b)*b. While * both operators return the same result for positive operands, they do * not for e.g. a negative dividend: remainder may be negative (in the * open interval ]-num_groups, num_groups[) while the modulus is always * positive. So if the remainder is negative, we must add `num_groups` * to get the modulus. */ const int32_t rem = group % (int32_t) num_groups; return (rem >= 0) ? rem : rem + (int32_t) num_groups; } } } xkb_action_count_t xkb_keymap_key_get_actions_by_level(struct xkb_keymap *keymap, const struct xkb_key *key, xkb_layout_index_t layout, xkb_level_index_t level, const union xkb_action **actions) { if (!key) goto err; layout = XkbWrapGroupIntoRange((int32_t) layout, key->num_groups, key->out_of_range_group_action, key->out_of_range_group_number); if (layout == XKB_LAYOUT_INVALID) goto err; if (level >= XkbKeyNumLevels(key, layout)) goto err; const xkb_action_count_t count = key->groups[layout].levels[level].num_actions; switch (count) { case 0: goto err; case 1: *actions = &key->groups[layout].levels[level].a.action; break; default: *actions = key->groups[layout].levels[level].a.actions; } return count; err: *actions = NULL; return 0; } xkbcommon-libxkbcommon-54ee7ac/src/keymap.c000066400000000000000000000440711510033435100211120ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT * * Author: Daniel Stone */ #include "config.h" #include #include #include "keymap.h" #include "text.h" #include "xkbcommon/xkbcommon.h" struct xkb_keymap * xkb_keymap_ref(struct xkb_keymap *keymap) { assert(keymap->refcnt > 0); keymap->refcnt++; return keymap; } void clear_level(struct xkb_level *leveli) { if (leveli->num_syms > 1) free(leveli->s.syms); if (leveli->num_actions > 1) free(leveli->a.actions); } static void clear_interpret(struct xkb_sym_interpret *interp) { if (interp->num_actions > 1) free(interp->a.actions); } void xkb_keymap_unref(struct xkb_keymap *keymap) { assert(!keymap || keymap->refcnt > 0); if (!keymap || --keymap->refcnt > 0) return; if (keymap->keys) { struct xkb_key *key; xkb_keys_foreach(key, keymap) { if (key->groups) { for (xkb_layout_index_t i = 0; i < key->num_groups; i++) { if (key->groups[i].levels) { for (xkb_level_index_t j = 0; j < XkbKeyNumLevels(key, i); j++) clear_level(&key->groups[i].levels[j]); free(key->groups[i].levels); } } free(key->groups); } } free(keymap->keys); } if (keymap->types) { for (darray_size_t i = 0; i < keymap->num_types; i++) { free(keymap->types[i].entries); free(keymap->types[i].level_names); } free(keymap->types); } for (darray_size_t k = 0; k < keymap->num_sym_interprets; k++) { clear_interpret(&keymap->sym_interprets[k]); } free(keymap->sym_interprets); free(keymap->key_aliases); free(keymap->group_names); free(keymap->keycodes_section_name); free(keymap->symbols_section_name); free(keymap->types_section_name); free(keymap->compat_section_name); xkb_context_unref(keymap->ctx); free(keymap); } static const struct xkb_keymap_format_ops * get_keymap_format_ops(enum xkb_keymap_format format) { static const struct xkb_keymap_format_ops *keymap_format_ops[] = { [XKB_KEYMAP_FORMAT_TEXT_V1] = &text_v1_keymap_format_ops, [XKB_KEYMAP_FORMAT_TEXT_V2] = &text_v1_keymap_format_ops, }; if ((int) format < 0 || (int) format >= (int) ARRAY_SIZE(keymap_format_ops)) return NULL; return keymap_format_ops[(int) format]; } struct xkb_keymap * xkb_keymap_new_from_rmlvo(const struct xkb_rmlvo_builder *rmlvo, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { struct xkb_keymap *keymap; const struct xkb_keymap_format_ops *ops; ops = get_keymap_format_ops(format); if (!ops || !ops->keymap_new_from_rmlvo) { log_err_func(rmlvo->ctx, XKB_LOG_MESSAGE_NO_ID, "unsupported keymap format: %d\n", format); return NULL; } if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { log_err_func(rmlvo->ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized keymap compilation flags: %#x\n", flags); return NULL; } keymap = xkb_keymap_new(rmlvo->ctx, format, flags); if (!keymap) return NULL; if (!ops->keymap_new_from_rmlvo(keymap, rmlvo)) { xkb_keymap_unref(keymap); return NULL; } return keymap; } struct xkb_keymap * xkb_keymap_new_from_names2(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo_in, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { struct xkb_keymap *keymap; struct xkb_rule_names rmlvo; const struct xkb_keymap_format_ops *ops; ops = get_keymap_format_ops(format); if (!ops || !ops->keymap_new_from_names) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unsupported keymap format: %d\n", format); return NULL; } if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized keymap compilation flags: %#x\n", flags); return NULL; } keymap = xkb_keymap_new(ctx, format, flags); if (!keymap) return NULL; if (rmlvo_in) rmlvo = *rmlvo_in; else memset(&rmlvo, 0, sizeof(rmlvo)); xkb_context_sanitize_rule_names(ctx, &rmlvo); if (!ops->keymap_new_from_names(keymap, &rmlvo)) { xkb_keymap_unref(keymap); return NULL; } return keymap; } struct xkb_keymap * xkb_keymap_new_from_names(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo_in, enum xkb_keymap_compile_flags flags) { return xkb_keymap_new_from_names2(ctx, rmlvo_in, XKB_KEYMAP_FORMAT_TEXT_V2, flags); } struct xkb_keymap * xkb_keymap_new_from_string(struct xkb_context *ctx, const char *string, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { return xkb_keymap_new_from_buffer(ctx, string, strlen(string), format, flags); } struct xkb_keymap * xkb_keymap_new_from_buffer(struct xkb_context *ctx, const char *buffer, size_t length, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { struct xkb_keymap *keymap; const struct xkb_keymap_format_ops *ops; ops = get_keymap_format_ops(format); if (!ops || !ops->keymap_new_from_string) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unsupported keymap format: %d\n", format); return NULL; } if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized keymap compilation flags: %#x\n", flags); return NULL; } if (!buffer) { log_err_func1(ctx, XKB_LOG_MESSAGE_NO_ID, "no buffer specified\n"); return NULL; } keymap = xkb_keymap_new(ctx, format, flags); if (!keymap) return NULL; /* Allow a zero-terminated string as a buffer */ if (length > 0 && buffer[length - 1] == '\0') length--; if (!ops->keymap_new_from_string(keymap, buffer, length)) { xkb_keymap_unref(keymap); return NULL; } return keymap; } struct xkb_keymap * xkb_keymap_new_from_file(struct xkb_context *ctx, FILE *file, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags) { struct xkb_keymap *keymap; const struct xkb_keymap_format_ops *ops; ops = get_keymap_format_ops(format); if (!ops || !ops->keymap_new_from_file) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unsupported keymap format: %d\n", format); return NULL; } if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized keymap compilation flags: %#x\n", flags); return NULL; } if (!file) { log_err_func1(ctx, XKB_LOG_MESSAGE_NO_ID, "no file specified\n"); return NULL; } keymap = xkb_keymap_new(ctx, format, flags); if (!keymap) return NULL; if (!ops->keymap_new_from_file(keymap, file)) { xkb_keymap_unref(keymap); return NULL; } return keymap; } char * xkb_keymap_get_as_string2(struct xkb_keymap *keymap, enum xkb_keymap_format format, enum xkb_keymap_serialize_flags flags) { const enum xkb_keymap_serialize_flags valid_flags = XKB_KEYMAP_SERIALIZE_PRETTY | XKB_KEYMAP_SERIALIZE_KEEP_UNUSED; if (flags & ~valid_flags) { log_err_func(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized serialization flags: %#x\n", flags); return NULL; } if (format == XKB_KEYMAP_USE_ORIGINAL_FORMAT) format = keymap->format; const struct xkb_keymap_format_ops * const ops = get_keymap_format_ops(format); if (!ops || !ops->keymap_get_as_string) { log_err_func(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "unsupported keymap format: %d\n", format); return NULL; } return ops->keymap_get_as_string(keymap, format, flags); } char * xkb_keymap_get_as_string(struct xkb_keymap *keymap, enum xkb_keymap_format format) { return xkb_keymap_get_as_string2(keymap, format, XKB_KEYMAP_SERIALIZE_NO_FLAGS); } /** * Returns the total number of modifiers active in the keymap. */ xkb_mod_index_t xkb_keymap_num_mods(struct xkb_keymap *keymap) { return keymap->mods.num_mods; } /** * Return the name for a given modifier. */ const char * xkb_keymap_mod_get_name(struct xkb_keymap *keymap, xkb_mod_index_t idx) { if (idx >= keymap->mods.num_mods) return NULL; return xkb_atom_text(keymap->ctx, keymap->mods.mods[idx].name); } /** * Returns the index for a named modifier. */ xkb_mod_index_t xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name) { const xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name); return (atom == XKB_ATOM_NONE) ? XKB_MOD_INVALID : XkbModNameToIndex(&keymap->mods, atom, MOD_BOTH); } /** * Return the canonical mapping of a named modifier. */ xkb_mod_mask_t xkb_keymap_mod_get_mask(struct xkb_keymap *keymap, const char* name) { const xkb_mod_index_t idx = xkb_keymap_mod_get_index(keymap, name); return (idx >= keymap->mods.num_mods) ? 0 : keymap->mods.mods[idx].mapping; } /** * Return the canonical mapping of a given modifier. */ xkb_mod_mask_t xkb_keymap_mod_get_mask2(struct xkb_keymap *keymap, xkb_mod_index_t idx) { return (idx >= keymap->mods.num_mods) ? 0 : keymap->mods.mods[idx].mapping; } /** * Return the total number of active groups in the keymap. */ xkb_layout_index_t xkb_keymap_num_layouts(struct xkb_keymap *keymap) { return keymap->num_groups; } /** * Returns the name for a given group. */ const char * xkb_keymap_layout_get_name(struct xkb_keymap *keymap, xkb_layout_index_t idx) { if (idx >= keymap->num_group_names) return NULL; return xkb_atom_text(keymap->ctx, keymap->group_names[idx]); } /** * Returns the index for a named layout. */ xkb_layout_index_t xkb_keymap_layout_get_index(struct xkb_keymap *keymap, const char *name) { xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name); xkb_layout_index_t i; if (atom == XKB_ATOM_NONE) return XKB_LAYOUT_INVALID; for (i = 0; i < keymap->num_group_names; i++) if (keymap->group_names[i] == atom) return i; return XKB_LAYOUT_INVALID; } /** * Returns the number of layouts active for a particular key. */ xkb_layout_index_t xkb_keymap_num_layouts_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc) { const struct xkb_key *key = XkbKey(keymap, kc); if (!key) return 0; return key->num_groups; } /** * Returns the number of levels active for a particular key and layout. */ xkb_level_index_t xkb_keymap_num_levels_for_key(struct xkb_keymap *keymap, xkb_keycode_t kc, xkb_layout_index_t layout) { const struct xkb_key *key = XkbKey(keymap, kc); if (!key) return 0; static_assert(XKB_MAX_GROUPS < INT32_MAX, "Max groups don't fit"); layout = XkbWrapGroupIntoRange((int32_t) layout, key->num_groups, key->out_of_range_group_action, key->out_of_range_group_number); if (layout == XKB_LAYOUT_INVALID) return 0; return XkbKeyNumLevels(key, layout); } /** * Return the total number of LEDs in the keymap. */ xkb_led_index_t xkb_keymap_num_leds(struct xkb_keymap *keymap) { return keymap->num_leds; } /** * Returns the name for a given LED. */ const char * xkb_keymap_led_get_name(struct xkb_keymap *keymap, xkb_led_index_t idx) { if (idx >= keymap->num_leds) return NULL; return xkb_atom_text(keymap->ctx, keymap->leds[idx].name); } /** * Returns the index for a named LED. */ xkb_led_index_t xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name) { xkb_atom_t atom = xkb_atom_lookup(keymap->ctx, name); xkb_led_index_t i; const struct xkb_led *led; if (atom == XKB_ATOM_NONE) return XKB_LED_INVALID; xkb_leds_enumerate(i, led, keymap) if (led->name == atom) return i; return XKB_LED_INVALID; } size_t xkb_keymap_key_get_mods_for_level(struct xkb_keymap *keymap, xkb_keycode_t kc, xkb_layout_index_t layout, xkb_level_index_t level, xkb_mod_mask_t *masks_out, size_t masks_size) { const struct xkb_key *key = XkbKey(keymap, kc); if (!key) return 0; static_assert(XKB_MAX_GROUPS < INT32_MAX, "Max groups don't fit"); layout = XkbWrapGroupIntoRange((int32_t) layout, key->num_groups, key->out_of_range_group_action, key->out_of_range_group_number); if (layout == XKB_LAYOUT_INVALID) return 0; if (level >= XkbKeyNumLevels(key, layout)) return 0; const struct xkb_key_type *type = key->groups[layout].type; size_t count = 0; /* * If the active set of modifiers doesn't match any explicit entry of * the key type, the resulting level is 0 (i.e. Level 1). * So, if we are asked to find the modifiers for level==0, we can offer * an ~infinite supply, which is not very workable. * What we do instead, is special case the empty set of modifiers for * this purpose. If the empty set isn't explicit mapped to a level, we * take it to map to Level 1. * This is almost always what we want. If applicable, given it priority * over other ways to generate the level. */ if (level == 0) { bool empty_mapped = false; for (darray_size_t i = 0; i < type->num_entries && count < masks_size; i++) if (entry_is_active(&type->entries[i]) && type->entries[i].mods.mask == 0) { empty_mapped = true; break; } if (!empty_mapped && count < masks_size) { masks_out[count++] = 0; } } /* Now search explicit mappings. */ for (darray_size_t i = 0; i < type->num_entries && count < masks_size; i++) { if (entry_is_active(&type->entries[i]) && type->entries[i].level == level) { masks_out[count++] = type->entries[i].mods.mask; } } return count; } struct xkb_level * xkb_keymap_key_get_level(struct xkb_keymap *keymap, const struct xkb_key *key, xkb_layout_index_t layout, xkb_level_index_t level) { static_assert(XKB_MAX_GROUPS < INT32_MAX, "Max groups don't fit"); layout = XkbWrapGroupIntoRange((int32_t) layout, key->num_groups, key->out_of_range_group_action, key->out_of_range_group_number); if (layout == XKB_LAYOUT_INVALID) return NULL; if (level >= XkbKeyNumLevels(key, layout)) return NULL; return &key->groups[layout].levels[level]; } /** * As below, but takes an explicit layout/level rather than state. */ int xkb_keymap_key_get_syms_by_level(struct xkb_keymap *keymap, xkb_keycode_t kc, xkb_layout_index_t layout, xkb_level_index_t level, const xkb_keysym_t **syms_out) { const struct xkb_key *key = XkbKey(keymap, kc); if (!key) goto err; const struct xkb_level* const leveli = xkb_keymap_key_get_level(keymap, key, layout, level); if (!leveli) goto err; const xkb_keysym_count_t num_syms = leveli->num_syms; if (num_syms == 0) goto err; if (num_syms == 1) *syms_out = &leveli->s.sym; else *syms_out = leveli->s.syms; return (int) num_syms; err: *syms_out = NULL; return 0; } xkb_keycode_t xkb_keymap_min_keycode(struct xkb_keymap *keymap) { return keymap->min_key_code; } xkb_keycode_t xkb_keymap_max_keycode(struct xkb_keymap *keymap) { return keymap->max_key_code; } void xkb_keymap_key_for_each(struct xkb_keymap *keymap, xkb_keymap_key_iter_t iter, void *data) { struct xkb_key *key; xkb_keys_foreach(key, keymap) iter(keymap, key->keycode, data); } const char * xkb_keymap_key_get_name(struct xkb_keymap *keymap, xkb_keycode_t kc) { const struct xkb_key *key = XkbKey(keymap, kc); if (!key) return NULL; return xkb_atom_text(keymap->ctx, key->name); } xkb_keycode_t xkb_keymap_key_by_name(struct xkb_keymap *keymap, const char *name) { struct xkb_key *key; xkb_atom_t atom; atom = xkb_atom_lookup(keymap->ctx, name); if (atom) { for (darray_size_t i = 0; i < keymap->num_key_aliases; i++) if (keymap->key_aliases[i].alias == atom) atom = keymap->key_aliases[i].real; } if (!atom) return XKB_KEYCODE_INVALID; xkb_keys_foreach(key, keymap) { if (key->name == atom) return key->keycode; } return XKB_KEYCODE_INVALID; } /** * Simple boolean specifying whether or not the key should repeat. */ int xkb_keymap_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc) { const struct xkb_key *key = XkbKey(keymap, kc); if (!key) return 0; return key->repeats; } xkbcommon-libxkbcommon-54ee7ac/src/keymap.h000066400000000000000000000532271510033435100211220ustar00rootroot00000000000000/* * For MIT-open-group: * Copyright 1985, 1987, 1990, 1998 The Open Group * * For HPND * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2009 Dan Nicholson * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: MIT-open-group AND HPND AND MIT * * Author: Daniel Stone * Author: Dan Nicholson */ #pragma once /* Don't use compat names in internal code. */ #define _XKBCOMMON_COMPAT_H #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "darray.h" #include "rmlvo.h" #include "context.h" #include "utils.h" /* Note: imposed by the size of the xkb_layout_mask_t type (32). * This is more than enough though. */ #define XKB_MAX_GROUPS 32 #define XKB_ALL_GROUPS ((UINT64_C(1) << XKB_MAX_GROUPS) - UINT64_C(1)) /* Limit imposed by X11 */ #define XKB_MAX_GROUPS_X11 4 static inline xkb_layout_index_t format_max_groups(enum xkb_keymap_format format) { return (format == XKB_KEYMAP_FORMAT_TEXT_V1) ? XKB_MAX_GROUPS_X11 : XKB_MAX_GROUPS; } /* Don't allow more modifiers than we can hold in xkb_mod_mask_t. */ #define XKB_MAX_MODS ((xkb_mod_index_t) (sizeof(xkb_mod_mask_t) * CHAR_BIT)) /* Don't allow more leds than we can hold in xkb_led_mask_t. */ #define XKB_MAX_LEDS ((xkb_led_index_t) (sizeof(xkb_led_mask_t) * CHAR_BIT)) /* Special value to handle modMap None {…} */ #define XKB_MOD_NONE 0xffffffffU enum mod_type { /** X11 core modifier */ MOD_REAL = (1 << 0), /** A non-X11 core modifier */ MOD_VIRT = (1 << 1), /** Any modifier */ MOD_BOTH = (MOD_REAL | MOD_VIRT) }; #define MOD_REAL_MASK_ALL ((xkb_mod_mask_t) 0x000000ff) /** Predefined (AKA real, core, X11) modifiers. The order is important! */ enum real_mod_index { XKB_MOD_INDEX_SHIFT = 0, XKB_MOD_INDEX_CAPS, XKB_MOD_INDEX_CTRL, XKB_MOD_INDEX_MOD1, XKB_MOD_INDEX_MOD2, XKB_MOD_INDEX_MOD3, XKB_MOD_INDEX_MOD4, XKB_MOD_INDEX_MOD5, _XKB_MOD_INDEX_NUM_ENTRIES }; static_assert(_XKB_MOD_INDEX_NUM_ENTRIES == 8, "Invalid X11 core modifiers"); enum xkb_action_type { ACTION_TYPE_NONE = 0, ACTION_TYPE_VOID, /* libxkbcommon extension */ ACTION_TYPE_MOD_SET, ACTION_TYPE_MOD_LATCH, ACTION_TYPE_MOD_LOCK, ACTION_TYPE_GROUP_SET, ACTION_TYPE_GROUP_LATCH, ACTION_TYPE_GROUP_LOCK, ACTION_TYPE_PTR_MOVE, ACTION_TYPE_PTR_BUTTON, ACTION_TYPE_PTR_LOCK, ACTION_TYPE_PTR_DEFAULT, ACTION_TYPE_TERMINATE, ACTION_TYPE_SWITCH_VT, ACTION_TYPE_CTRL_SET, ACTION_TYPE_CTRL_LOCK, ACTION_TYPE_UNSUPPORTED_LEGACY, ACTION_TYPE_PRIVATE, ACTION_TYPE_INTERNAL, /* Action specific and internal to xkbcommon */ _ACTION_TYPE_NUM_ENTRIES }; enum xkb_action_flags { ACTION_LOCK_CLEAR = (1 << 0), ACTION_LATCH_TO_LOCK = (1 << 1), ACTION_LOCK_NO_LOCK = (1 << 2), ACTION_LOCK_NO_UNLOCK = (1 << 3), ACTION_MODS_LOOKUP_MODMAP = (1 << 4), ACTION_ABSOLUTE_SWITCH = (1 << 5), ACTION_ABSOLUTE_X = (1 << 6), ACTION_ABSOLUTE_Y = (1 << 7), ACTION_ACCEL = (1 << 8), ACTION_SAME_SCREEN = (1 << 9), ACTION_LOCK_ON_RELEASE = (1 << 10), ACTION_UNLOCK_ON_PRESS = (1 << 11), ACTION_LATCH_ON_PRESS = (1 << 12), }; enum xkb_action_controls { CONTROL_REPEAT = (1 << 0), CONTROL_SLOW = (1 << 1), CONTROL_DEBOUNCE = (1 << 2), CONTROL_STICKY = (1 << 3), CONTROL_MOUSEKEYS = (1 << 4), CONTROL_MOUSEKEYS_ACCEL = (1 << 5), CONTROL_AX = (1 << 6), CONTROL_AX_TIMEOUT = (1 << 7), CONTROL_AX_FEEDBACK = (1 << 8), CONTROL_BELL = (1 << 9), CONTROL_IGNORE_GROUP_LOCK = (1 << 10), CONTROL_ALL = \ (CONTROL_REPEAT | CONTROL_SLOW | CONTROL_DEBOUNCE | CONTROL_STICKY | \ CONTROL_MOUSEKEYS | CONTROL_MOUSEKEYS_ACCEL | CONTROL_AX | \ CONTROL_AX_TIMEOUT | CONTROL_AX_FEEDBACK | CONTROL_BELL | \ CONTROL_IGNORE_GROUP_LOCK) }; enum xkb_match_operation { MATCH_NONE, MATCH_ANY_OR_NONE, MATCH_ANY, MATCH_ALL, MATCH_EXACTLY, }; struct xkb_mods { xkb_mod_mask_t mods; /* original real+virtual mods in definition */ xkb_mod_mask_t mask; /* computed effective mask */ }; struct xkb_mod_action { enum xkb_action_type type; enum xkb_action_flags flags; struct xkb_mods mods; }; struct xkb_group_action { enum xkb_action_type type; enum xkb_action_flags flags; int32_t group; }; struct xkb_controls_action { enum xkb_action_type type; enum xkb_action_flags flags; enum xkb_action_controls ctrls; }; struct xkb_pointer_default_action { enum xkb_action_type type; enum xkb_action_flags flags; int8_t value; }; struct xkb_switch_screen_action { enum xkb_action_type type; enum xkb_action_flags flags; int8_t screen; }; struct xkb_pointer_action { enum xkb_action_type type; enum xkb_action_flags flags; int16_t x; int16_t y; }; struct xkb_pointer_button_action { enum xkb_action_type type; enum xkb_action_flags flags; uint8_t count; uint8_t button; }; struct xkb_private_action { enum xkb_action_type type; uint8_t data[7]; }; enum xkb_internal_action_flags { INTERNAL_BREAKS_GROUP_LATCH = (1 << 0), INTERNAL_BREAKS_MOD_LATCH = (1 << 1), }; /* Action specific and internal to xkbcommon */ struct xkb_internal_action { enum xkb_action_type type; enum xkb_internal_action_flags flags; union { /* flag == INTERNAL_BREAKS_MOD_LATCH */ xkb_mod_mask_t clear_latched_mods; }; }; union xkb_action { enum xkb_action_type type; struct xkb_mod_action mods; struct xkb_group_action group; struct xkb_controls_action ctrls; struct xkb_pointer_default_action dflt; struct xkb_switch_screen_action screen; struct xkb_pointer_action ptr; struct xkb_pointer_button_action btn; struct xkb_private_action priv; struct xkb_internal_action internal; }; struct xkb_key_type_entry { xkb_level_index_t level; struct xkb_mods mods; struct xkb_mods preserve; }; struct xkb_key_type { xkb_atom_t name; struct xkb_mods mods; bool required; xkb_level_index_t num_levels; xkb_level_index_t num_level_names; xkb_atom_t *level_names; darray_size_t num_entries; struct xkb_key_type_entry *entries; }; typedef uint16_t xkb_action_count_t; #define MAX_ACTIONS_PER_LEVEL UINT16_MAX struct xkb_sym_interpret { xkb_keysym_t sym; enum xkb_match_operation match; xkb_mod_mask_t mods; xkb_mod_index_t virtual_mod; bool level_one_only; bool repeat:1; bool required:1; xkb_action_count_t num_actions; union { /* num_actions <= 1 */ union xkb_action action; /* num_actions > 1 */ union xkb_action *actions; } a; }; struct xkb_led { xkb_atom_t name; enum xkb_state_component which_groups; xkb_layout_mask_t groups; enum xkb_state_component which_mods; struct xkb_mods mods; enum xkb_action_controls ctrls; }; struct xkb_key_alias { xkb_atom_t real; xkb_atom_t alias; }; struct xkb_controls { unsigned char groups_wrap; struct xkb_mods internal; struct xkb_mods ignore_lock; unsigned short repeat_delay; unsigned short repeat_interval; unsigned short slow_keys_delay; unsigned short debounce_delay; unsigned short ax_options; unsigned short ax_timeout; unsigned short axt_opts_mask; unsigned short axt_opts_values; unsigned int axt_ctrls_mask; unsigned int axt_ctrls_values; }; /* Such an awkward name. Oh well. */ enum xkb_range_exceed_type { RANGE_WRAP = 0, RANGE_SATURATE, RANGE_REDIRECT, }; enum xkb_explicit_components { EXPLICIT_SYMBOLS = (1 << 0), EXPLICIT_INTERP = (1 << 1), EXPLICIT_TYPES = (1 << 2), EXPLICIT_VMODMAP = (1 << 3), EXPLICIT_REPEAT = (1 << 4), }; typedef uint16_t xkb_keysym_count_t; #define MAX_KEYSYMS_PER_LEVEL UINT16_MAX /** A key level */ struct xkb_level { /** Count of keysyms */ xkb_keysym_count_t num_syms; /** Count of actions */ xkb_action_count_t num_actions; /** Upper keysym */ union { /** num_syms == 1: Upper keysym */ xkb_keysym_t upper; /** num_syms > 1: Indicate if `syms` contains the upper case keysyms * after the lower ones. */ bool has_upper; }; /** Keysyms */ union { xkb_keysym_t sym; /* num_syms == 1 */ xkb_keysym_t *syms; /* num_syms > 1 */ } s; /** Actions */ union { union xkb_action action; /* num_actions == 1 */ union xkb_action *actions; /* num_actions > 1 */ } a; }; /** * Group in a key */ struct xkb_group { /** * Flag that indicates whether a group has explicit actions. In case it has, * compatibility interpretations will not be used on it. * See also EXPLICIT_INTERP flag at key level. */ bool explicit_actions:1; /** * Flag that indicates whether a group has an explicit key type. In case it * has, type detection will not be used on it. */ bool explicit_type:1; /** * Key type of the group. Points to an entry in keymap->types. */ const struct xkb_key_type *type; /** * Array of group levels. Use `XkbKeyNumLevels` for the number of levels. */ struct xkb_level *levels; }; struct xkb_key { xkb_keycode_t keycode; xkb_atom_t name; enum xkb_explicit_components explicit; xkb_mod_mask_t modmap; xkb_mod_mask_t vmodmap; bool repeats; enum xkb_range_exceed_type out_of_range_group_action; xkb_layout_index_t out_of_range_group_number; xkb_layout_index_t num_groups; struct xkb_group *groups; }; struct xkb_mod { xkb_atom_t name; enum mod_type type; xkb_mod_mask_t mapping; /* vmod -> real mod mapping */ }; struct xkb_mod_set { struct xkb_mod mods[XKB_MAX_MODS]; xkb_mod_index_t num_mods; xkb_mod_mask_t explicit_vmods; }; /* * Implementation with continuous arrays does not allow efficient mapping of * sparse keycodes. Indeed, allowing the API max valid keycode XKB_KEYCODE_MAX * could result in memory exhaustion or memory waste (sparse arrays) with huge * enough valid values. However usual keycodes form a contiguous range with a * that maximum that rarely exceeds 1000. In order to handle the whole keycode * range, we define a threshold for the continuous array storage, above which we * use a more space-efficient storage for sparse arrays. * * The current limit is arbitrary and serves as a minimal security. */ #define XKB_KEYCODE_MAX_CONTIGUOUS 0xfff static_assert(XKB_KEYCODE_MAX_CONTIGUOUS < XKB_KEYCODE_MAX, "Valid keycodes"); static_assert(XKB_KEYCODE_MAX_CONTIGUOUS < darray_max_alloc(sizeof(xkb_atom_t)), "Max keycodes names"); static_assert(XKB_KEYCODE_MAX_CONTIGUOUS < darray_max_alloc(sizeof(struct xkb_key)), "Max keymap keys"); /* * Our current implementation with continuous arrays does not allow efficient * mapping of levels. Allowing the max valid level UINT32_MAX could result in * memory exhaustion or memory waste (sparse arrays) with huge enough valid * values. Let’s be more conservative for now. This value should be big enough * to satisfy automatically generated keymaps. */ #define XKB_LEVEL_MAX_IMPL 2048 static_assert(XKB_LEVEL_MAX_IMPL < XKB_LEVEL_INVALID, "Valid levels"); static_assert(XKB_LEVEL_MAX_IMPL < darray_max_alloc(sizeof(xkb_atom_t)), "Max key types level names"); static_assert(XKB_LEVEL_MAX_IMPL < darray_max_alloc(sizeof(struct xkb_level)), "Max keys levels"); static_assert((1LLU << (DARRAY_SIZE_T_WIDTH - 3)) - 1 >= XKB_KEYCODE_MAX_CONTIGUOUS, "Cannot store low keycodes"); /** Keycode store lookup result */ typedef union { struct { /** If true, the index is valid */ bool found:1; bool:1; /** Whether the corresponding entry is an alias */ bool is_alias:1; darray_size_t:(DARRAY_SIZE_T_WIDTH - 3); }; /* Only if is_alias = false, for better semantics */ struct { bool found:1; /** * Whether the corresponding entry is stored in the low or high table * of the keycode store */ bool low:1; bool is_alias:1; /** * - xkb_keycodes: index of the entry in the keycode store * - xkb_symbols: index of the entry in xkb_keymap::keys array */ darray_size_t index:(DARRAY_SIZE_T_WIDTH - 3); } key; /* Only if is_alias = true, for better semantics */ struct { bool found:1; bool:1; bool is_alias:1; /** Real name of the target key */ xkb_atom_t real:(DARRAY_SIZE_T_WIDTH - 3); } alias; } KeycodeMatch; /* Common keyboard description structure */ struct xkb_keymap { struct xkb_context *ctx; int refcnt; enum xkb_keymap_compile_flags flags; enum xkb_keymap_format format; enum xkb_action_controls enabled_ctrls; xkb_keycode_t min_key_code; xkb_keycode_t max_key_code; xkb_keycode_t num_keys; /* * Keys are divided into 2 ordered (possibly empty) lists: * * Low keycodes (≤ XKB_KEYCODE_MAX_CONTIGUOUS) * Stored contiguously at indexes [0..num_keys_low). * Fast O(1) access. * High keycodes (> XKB_KEYCODE_MAX_CONTIGUOUS) * Stored noncontiguously at indexes [num_keys_low..num_keys). * Slow access via a binary search. */ xkb_keycode_t num_keys_low; struct xkb_key *keys; union { /** * Keycode name atom -> key index lookup table * * ⚠️ Used only *during* compilation * * Given that: * - the number of atoms is usually < 1k; * - the keycode section usually appears first; * then the first atoms will be mostly the keycodes and their aliases, * so we can achieve O(1) lookup of the key names by using a simple array. */ struct { darray_size_t num_key_names; KeycodeMatch *key_names; }; /** * Aliases in no particular order * * ⚠️ Used only *after* compilation */ struct { darray_size_t num_key_aliases; struct xkb_key_alias *key_aliases; }; }; struct xkb_key_type *types; darray_size_t num_types; darray_size_t num_sym_interprets; struct xkb_sym_interpret *sym_interprets; /** * Modifiers configuration. * This is *internal* to the keymap; other implementations may use different * virtual modifiers indices. Ours depends on: * 1. the order of the parsing of the keymap components; * 2. the order of the virtual modifiers declarations; */ struct xkb_mod_set mods; /** * Modifier mask of the *canonical* state, i.e. the mask with the *smallest* * population count that denotes all bits used to encode the modifiers in * the keyboard state. It is equal to the bitwise OR of *real* modifiers and * all *virtual* modifiers mappings. * * [WARNING] The bits that do not correspond to *real* modifiers should * *not* be interpreted as corresponding to indices of virtual modifiers of * the keymap. Indeed, one may use explicit vmod mapping with an arbitrary * value. * * E.g. if M1 is the only vmod and it is defined by: * * virtual_modifiers M1=0x80000000; // 1 << (32 - 1) * * then the 32th bit of a modifier mask input does *not* denote the 32th * virtual modifier of the keymap, but merely the encoding of the mapping of * M1. * * In the API, any input mask should be preprocessed to resolve the bits * that do not match the canonical mask. */ xkb_mod_mask_t canonical_state_mask; /* This field has 2 uses: * • During parsing: Expected layouts count after RMLVO resolution, if any; * • After parsing: Number of groups in the key with the most groups. */ xkb_layout_index_t num_groups; /* Not all groups must have names. */ xkb_layout_index_t num_group_names; xkb_atom_t *group_names; struct xkb_led leds[XKB_MAX_LEDS]; xkb_led_index_t num_leds; char *keycodes_section_name; char *symbols_section_name; char *types_section_name; char *compat_section_name; }; #define xkb_keys_foreach(iter, keymap) \ /* * Start at the first defined low or high keycode: * - if there are some low keycodes, the index is min_key_code, because we * skip the previous undefined keycodes; * - else the first item is the first high keycode. */ \ for ((iter) = (keymap)->keys + \ ((keymap)->num_keys_low == 0 ? 0 : (keymap)->min_key_code); \ (iter) < (keymap)->keys + (keymap)->num_keys; \ (iter)++) #define xkb_mods_foreach(iter, mods_) \ for ((iter) = (mods_)->mods; \ (iter) < (mods_)->mods + (mods_)->num_mods; \ (iter)++) #define xkb_mods_mask_foreach(mask, iter, mods_) \ for ((iter) = (mods_)->mods; \ (mask) && (iter) < (mods_)->mods + (mods_)->num_mods; \ (iter)++, (mask) >>= 1) \ if ((mask) & 0x1) /** Enumerate all modifiers */ #define xkb_mods_enumerate(idx, iter, mods_) \ for ((idx) = 0, (iter) = (mods_)->mods; \ (idx) < (mods_)->num_mods; \ (idx)++, (iter)++) /** Enumerate only real modifiers */ #define xkb_rmods_enumerate(idx, iter, mods_) \ for ((idx) = 0, (iter) = (mods_)->mods; \ (idx) < _XKB_MOD_INDEX_NUM_ENTRIES; \ (idx)++, (iter)++) /** Enumerate only virtual modifiers */ #define xkb_vmods_enumerate(idx, iter, mods_) \ for ((idx) = _XKB_MOD_INDEX_NUM_ENTRIES, \ (iter) = &(mods_)->mods[_XKB_MOD_INDEX_NUM_ENTRIES]; \ (idx) < (mods_)->num_mods; \ (idx)++, (iter)++) #define xkb_leds_foreach(iter, keymap) \ for ((iter) = (keymap)->leds; \ (iter) < (keymap)->leds + (keymap)->num_leds; \ (iter)++) #define xkb_leds_enumerate(idx, iter, keymap) \ for ((idx) = 0, (iter) = (keymap)->leds; \ (idx) < (keymap)->num_leds; \ (idx)++, (iter)++) void clear_level(struct xkb_level *leveli); static inline const struct xkb_key * XkbKey(struct xkb_keymap *keymap, xkb_keycode_t kc) { if (kc < keymap->min_key_code || kc > keymap->max_key_code) { /* Unsupported keycode */ return NULL; } else if (kc < keymap->num_keys_low) { /* Low keycodes */ return &keymap->keys[kc]; } else { /* High keycodes: use binary search */ xkb_keycode_t lower = keymap->num_keys_low; xkb_keycode_t upper = keymap->num_keys; while (lower < upper) { const xkb_keycode_t mid = lower + (upper - 1 - lower) / 2; const struct xkb_key * const key = &keymap->keys[mid]; if (key->keycode < kc) { lower = mid + 1; } else if (key->keycode > kc) { upper = mid; } else { return key; } } return NULL; } } static inline xkb_level_index_t XkbKeyNumLevels(const struct xkb_key *key, xkb_layout_index_t layout) { return key->groups[layout].type->num_levels; } /* * Map entries which specify unbound virtual modifiers are not considered. * See: the XKB protocol, section “Determining the KeySym Associated with a Key * Event” * * xserver does this with cached entry->active field. */ static inline bool entry_is_active(const struct xkb_key_type_entry *entry) { return entry->mods.mods == 0 || entry->mods.mask != 0; } struct xkb_keymap * xkb_keymap_new(struct xkb_context *ctx, enum xkb_keymap_format format, enum xkb_keymap_compile_flags flags); void XkbEscapeMapName(char *name); xkb_mod_index_t XkbModNameToIndex(const struct xkb_mod_set *mods, xkb_atom_t name, enum mod_type type); bool XkbLevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b); bool action_equal(const union xkb_action *a, const union xkb_action *b); bool XkbLevelsSameActions(const struct xkb_level *a, const struct xkb_level *b); xkb_layout_index_t XkbWrapGroupIntoRange(int32_t group, xkb_layout_index_t num_groups, enum xkb_range_exceed_type out_of_range_group_action, xkb_layout_index_t out_of_range_group_number); XKB_EXPORT_PRIVATE xkb_mod_mask_t mod_mask_get_effective(struct xkb_keymap *keymap, xkb_mod_mask_t mods); struct xkb_level * xkb_keymap_key_get_level(struct xkb_keymap *keymap, const struct xkb_key *key, xkb_layout_index_t layout, xkb_level_index_t level); xkb_action_count_t xkb_keymap_key_get_actions_by_level(struct xkb_keymap *keymap, const struct xkb_key *key, xkb_layout_index_t layout, xkb_level_index_t level, const union xkb_action **actions); struct xkb_keymap_format_ops { bool (*keymap_new_from_rmlvo)(struct xkb_keymap *keymap, const struct xkb_rmlvo_builder *rmlvo); bool (*keymap_new_from_names)(struct xkb_keymap *keymap, const struct xkb_rule_names *names); bool (*keymap_new_from_string)(struct xkb_keymap *keymap, const char *string, size_t length); bool (*keymap_new_from_file)(struct xkb_keymap *keymap, FILE *file); char *(*keymap_get_as_string)(struct xkb_keymap *keymap, enum xkb_keymap_format format, enum xkb_keymap_serialize_flags flags); }; extern const struct xkb_keymap_format_ops text_v1_keymap_format_ops; xkbcommon-libxkbcommon-54ee7ac/src/keysym-case-mappings.c000066400000000000000000001207711510033435100236740ustar00rootroot00000000000000// NOTE: This file has been generated automatically by “update-keysyms-case-mappings.py”. // Do not edit manually! /* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ /* Case mappings for Unicode 17.0 * * There are two kinds of keysyms to consider: * • Legacy keysyms: their case mappings is located at `data/keysyms.yaml`. * • Unicode keysyms: their case mappings come from the ICU library. * * These mappings would create huge lookup tables if done naively. Fortunately, * we can observe that if we compute only the *difference* between a keysym and * its corresponding case mapping, there are a lot of repetitions that can be * efficiently compressed. * * The idea for the compression is, for each kind of keysyms: * 1. Compute the deltas between the keysyms and their case mappings. * 2. Split the delta array in chunks of a given size. * 3. Rearrange the order of the chunks in order to optimize consecutive * chunks overlap. * 4. Create a data table with the reordered chunks and an index table that * maps the original chunk index to its offset in the data table. * * Trivial example (chunk size: 4, from step 2): * * [1, 2, 3, 4, 2, 3, 4, 5, 0, 1, 2, 3] # source data * -> [[1, 2, 3, 4], [2, 3, 4, 5], [0, 1, 2, 3]] # make chunks * -> [[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5]] # rearrange to have best overlaps * -> {data: [0, 1, 2, 3, 4, 5], offsets: [1, 2, 0]} # overlap chunks & compute * # their offsets * * Then we can retrieve the data from the original array at index i with the * following formula: * * mask = (1 << chunk_size) - 1; * original[i] = data[offsets[i >> chunk_size] + (i & mask)]; * * Since the index array is itself quite repetitive with the real data, we apply * the compression a second time to the offsets table. * * The complete algorithm optimizes the chunk sizes for both arrays in order to * get the lowest total data size. * * There are 6 resulting arrays, 3 for each kind of keysyms: * 1. The data array. Each item is either: * • 0, if the keysym is not cased. * • A delta to lower case. * • A delta to upper case. * • For some special cases, there are both a lower *and* an upper case * mapping. The delta is identical in both cases. * 2. The 1st offsets array, that provides offsets into the data array. * 3. The 2nd offsets array, that provides offsets into the 1st index array. * * Finally, given the chunks sizes `cs_data` and `cs_offsets`: * 1. We compute the corresponding masks: * • `mask_data = (1 << cs_data) - 1` and * • `mask_offsets = (1 << cs_offsets) - 1`. * 2. We can retrieve the case mapping of a keysyms `ks` with the following * formula: * * data[ * offsets1[ * offsets2[ks >> (cs_data + cs_offsets)] + * ((ks >> cs_data) & mask_offsets) * ] + * (ks & mask_data) * ]; */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "utils.h" #include "keysym.h" struct CaseMappings{ bool lower:1; bool upper:1; int32_t offset:30; }; static const struct CaseMappings legacy_keysym_data[47] = { {0, 1, 0x0000000}, {1, 0, 0x0000010}, {0, 0, 0x0000000}, {0, 0, 0x0000000}, {1, 0, 0x0000020}, {0, 1,-0x1001dbf}, {1, 0, 0x0000020}, {1, 0, 0x0000020}, {0, 0, 0x0000000}, {0, 1,-0x0000717}, {0, 1, 0x0000020}, {0, 0, 0x0000000}, {0, 1, 0x0000020}, {0, 1, 0x0000020}, {0, 1,-0x00012bf}, {0, 1, 0x0000000}, {0, 0, 0x0000000}, {1, 0, 0x0000010}, {1, 0, 0x0000010}, {0, 1,-0x0fff89b}, {0, 0, 0x0000000}, {0, 1, 0x0000010}, {0, 0, 0x0000000}, {0, 1,-0x0000010}, {0, 1,-0x0000010}, {0, 1, 0x0000000}, {0, 1, 0x0000010}, {0, 1, 0x0000010}, {1, 0, 0x0000002}, {0, 0, 0x0000000}, {1, 0,-0x0000010}, {1, 0,-0x0000010}, {1, 0,-0x00012bf}, {1, 0,-0x0000020}, {1, 0,-0x0000020}, {0, 1,-0x0000020}, {0, 1,-0x0000020}, {0, 0, 0x0000000}, {1, 0,-0x0000240}, {0, 0, 0x0000000}, {0, 1, 0x0000002}, {0, 0, 0x0000000}, {0, 1, 0x0000270}, {0, 1, 0x0000020}, {0, 1, 0x0000021}, {1, 0, 0x0000001}, {0, 1, 0x0000001} }; static const uint8_t legacy_keysym_offsets1[540] = { 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0003, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0007, 0x0002, 0x0002, 0x000b, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0010, 0x0011, 0x0011, 0x0010, 0x0011, 0x0010, 0x0002, 0x0002, 0x0014, 0x001a, 0x001a, 0x0019, 0x001a, 0x0019, 0x0002, 0x0002, 0x0003, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0007, 0x0006, 0x0006, 0x0006, 0x0002, 0x0002, 0x0002, 0x000b, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x002b, 0x000c, 0x000c, 0x000c, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0013, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x002d, 0x0020, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0000, 0x0010, 0x0001, 0x0002, 0x0011, 0x0001, 0x0002, 0x0002, 0x0014, 0x0014, 0x0015, 0x0002, 0x001a, 0x001b, 0x0027, 0x0007, 0x0002, 0x0002, 0x0003, 0x0002, 0x0002, 0x0007, 0x0003, 0x0003, 0x0006, 0x0002, 0x0002, 0x0003, 0x0002, 0x0003, 0x0007, 0x000a, 0x0002, 0x0002, 0x000b, 0x0002, 0x0002, 0x000a, 0x000b, 0x000b, 0x000c, 0x0002, 0x0002, 0x000b, 0x0002, 0x000b, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x000f, 0x0002, 0x0002, 0x0002, 0x0002, 0x0008, 0x0002, 0x0002, 0x000f, 0x0002, 0x0002, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0007, 0x0006, 0x0006, 0x0006, 0x0004, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000c, 0x000a, 0x000c, 0x000c, 0x000c, 0x000d, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0010, 0x0002, 0x0002, 0x0001, 0x0025, 0x0010, 0x0001, 0x0002, 0x0014, 0x0002, 0x0002, 0x0015, 0x0029, 0x0014, 0x0015, 0x0002, 0x0002, 0x0002, 0x0003, 0x0007, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0003, 0x0002, 0x0007, 0x0002, 0x0003, 0x0007, 0x0002, 0x0002, 0x000b, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x000b, 0x0002, 0x000a, 0x0002, 0x000b, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0010, 0x0010, 0x0010, 0x0001, 0x0010, 0x0011, 0x0001, 0x0011, 0x0014, 0x0014, 0x0014, 0x0015, 0x0014, 0x001a, 0x0015, 0x001a, 0x0007, 0x0003, 0x0003, 0x0007, 0x0007, 0x0007, 0x0007, 0x0003, 0x0006, 0x0007, 0x0003, 0x0002, 0x0006, 0x0003, 0x0002, 0x0007, 0x000a, 0x000b, 0x000b, 0x000a, 0x000a, 0x000a, 0x000a, 0x000b, 0x000c, 0x000a, 0x000b, 0x0002, 0x000c, 0x000b, 0x0002, 0x000a, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0016, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x0017, 0x001d, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x001e, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0023, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021, 0x0021 }; static const uint16_t legacy_keysym_offsets2[40] = { 0x0000, 0x011c, 0x007b, 0x019c, 0x007b, 0x015c, 0x007b, 0x00dc, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x01dc, 0x007b, 0x003e, 0x007b, 0x0080, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x007b, 0x00bc }; static inline const struct CaseMappings * get_legacy_keysym_entry(xkb_keysym_t ks) { return &legacy_keysym_data[legacy_keysym_offsets1[legacy_keysym_offsets2[ks >> 7] + ((ks >> 1) & 0x3f)] + (ks & 0x01)]; } static const struct CaseMappings unicode_data[1019] = { {0, 1,-0x0080}, {0, 1,-0x0080}, {0, 1,-0x0070}, {0, 1,-0x0070}, {0, 1,-0x007e}, {0, 1,-0x007e}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0xa515}, {0, 1,-0xa512}, {0, 1, 0x0000}, {1, 0, 0x0002}, {1, 1, 0x0001}, {0, 1, 0x0002}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x0061}, {1, 0,-0x0038}, {1, 0, 0x0020}, {1, 0, 0x0020}, {0, 0, 0x0000}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {0, 1,-0x1dbf}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0064}, {1, 0,-0x0064}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x0008}, {0, 0, 0x0000}, {1, 0,-0x0008}, {0, 0, 0x0000}, {1, 0,-0x0008}, {0, 0, 0x0000}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x004a}, {1, 0,-0x004a}, {1, 0,-0x0009}, {0, 0, 0x0000}, {0, 1, 0x1c25}, {0, 0, 0x0000}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1,-0x0079}, {0, 1,-0x2a1f}, {0, 1,-0x2a1c}, {0, 1,-0x2a1e}, {0, 1, 0x00d2}, {0, 1, 0x00ce}, {0, 1, 0x0000}, {0, 1, 0x00cd}, {0, 1, 0x00cd}, {0, 1,-0xa54b}, {0, 1, 0x0000}, {0, 1, 0x00cf}, {0, 1,-0xa567}, {0, 1,-0xa528}, {0, 1,-0xa544}, {0, 1, 0x0000}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1,-0x02e7}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0009}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0007}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x000f}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x20bf}, {1, 0,-0x2046}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a}, {1, 0, 0x001a}, {0, 1,-0x89c2}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0026}, {0, 0, 0x0000}, {1, 0,-0x0080}, {1, 0,-0x0080}, {1, 0,-0x007e}, {1, 0,-0x007e}, {1, 0,-0x0009}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0030}, {1, 0, 0x0030}, {1, 0, 0x0030}, {1, 0, 0x0030}, {1, 0, 0x0030}, {1, 0, 0x0030}, {1, 0, 0x0030}, {1, 0, 0x0030}, {0, 0, 0x0000}, {0, 1, 0x003e}, {0, 1, 0x0039}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x002f}, {0, 1, 0x0036}, {0, 1, 0x0008}, {0, 1, 0x0008}, {0, 1, 0x0008}, {0, 1, 0x0008}, {0, 1, 0x0008}, {0, 1, 0x0008}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0002}, {1, 1, 0x0001}, {0, 1, 0x0002}, {1, 0, 0x0002}, {1, 1, 0x0001}, {0, 1, 0x0002}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x0030}, {1, 0,-0xa543}, {1, 0,-0x8a38}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1,-0x00a3}, {0, 1,-0xa641}, {1, 0, 0x00d3}, {1, 0, 0x00d5}, {0, 1,-0x0082}, {1, 0, 0x00d6}, {1, 0,-0x00c7}, {0, 1, 0x00e8}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00da}, {1, 0, 0x0001}, {1, 0, 0x000f}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x2a1c}, {1, 0,-0x29fd}, {1, 0,-0x2a1f}, {0, 1, 0x0001}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x001c}, {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0001}, {1, 0,-0x0007}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {1, 0,-0x0082}, {1, 0,-0x0082}, {1, 0,-0x0082}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x004f}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0xa544}, {1, 0,-0xa54f}, {1, 0,-0xa54b}, {1, 0,-0xa541}, {1, 0,-0xa544}, {0, 1, 0x0000}, {0, 1, 0x00ca}, {0, 1, 0x0000}, {0, 1, 0x00cb}, {0, 1,-0xa54f}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x03a0}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0,-0x2a3f}, {1, 0,-0x2a3f}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {1, 0, 0x1c60}, {0, 0, 0x0000}, {1, 0, 0x1c60}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0008}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 1, 0x1c60}, {0, 0, 0x0000}, {0, 1, 0x1c60}, {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022}, {1, 0, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 1, 0x0022}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 0, 0x0000}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1,-0x0009}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x00db}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 0, 0x0000}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 1, 0x001a}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1,-0x0054}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040}, {1, 0, 0x0040}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 1, 0x0040}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x1c60}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x001b}, {1, 0, 0x001b}, {1, 0, 0x001b}, {1, 0, 0x001b}, {1, 0, 0x001b}, {1, 0, 0x001b}, {1, 0, 0x001b}, {1, 0, 0x001b}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x001b}, {0, 1, 0x001b}, {0, 1, 0x001b}, {0, 1, 0x001b}, {0, 1, 0x001b}, {0, 1, 0x001b}, {0, 1, 0x001b}, {0, 1, 0x001b}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0xa528}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x001f}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0040}, {0, 1, 0x003f}, {0, 1, 0x003f}, {1, 0, 0x0008}, {1, 0, 0x0008}, {1, 0, 0x0008}, {1, 0, 0x0008}, {1, 0, 0x0008}, {1, 0, 0x0008}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {1, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x003b}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0,-0x1dbf}, {0, 1, 0x0000}, {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0030}, {0, 1, 0x0000}, {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1,-0x0008}, {0, 1,-0x0008}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x8a04}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0ee6}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 1, 0x0020}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x1c60}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0082}, {0, 1,-0x0082}, {0, 1,-0x0082}, {0, 0, 0x0000}, {1, 0, 0x0074}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0xa567}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x001c}, {0, 0, 0x0000}, {1, 0,-0xa512}, {1, 0,-0xa52a}, {1, 0,-0xa515}, {1, 0, 0x03a0}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028}, {1, 0, 0x0028}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 1, 0x0028}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027}, {0, 0, 0x0000}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027}, {1, 0, 0x0027}, {0, 0, 0x0000}, {1, 0, 0x0027}, {1, 0, 0x0027}, {0, 0, 0x0000}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 0, 0x0000}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 0, 0x0000}, {0, 1, 0x0027}, {0, 1, 0x0027}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x2a1e}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {0, 1,-0x0038}, {0, 1, 0x00da}, {0, 1, 0x0045}, {0, 1, 0x00d9}, {0, 1, 0x00d9}, {0, 1, 0x0047}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x29e7}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x8a38}, {0, 1, 0x0000}, {0, 1,-0x29fd}, {0, 1, 0x00d5}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x00d6}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x2a2b}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x00a3}, {1, 0, 0x2a28}, {0, 1,-0x2a3f}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x00c3}, {1, 0, 0x0045}, {1, 0, 0x0047}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0xa641}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x1d5d}, {0, 0, 0x0000}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 0, 0x0000}, {0, 1, 0x0000}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {0, 1,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {1, 0,-0x0bc0}, {0, 1, 0x0001}, {1, 0, 0x00da}, {0, 1, 0x0000}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00da}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1,-0x0030}, {0, 1, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x8a04}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0,-0x29f7}, {1, 0,-0x0ee6}, {1, 0,-0x29e7}, {0, 1, 0x2a2b}, {0, 1, 0x2a28}, {1, 0, 0x0001}, {1, 0,-0x0079}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x012c}, {1, 0,-0x0056}, {1, 0,-0x0056}, {1, 0,-0x0056}, {1, 0,-0x0056}, {1, 0,-0x0009}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {1, 0,-0x0008}, {1, 0,-0x0008}, {1, 0,-0x0070}, {1, 0,-0x0070}, {1, 0,-0x0007}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 0, 0x0000}, {0, 1,-0x00c3}, {1, 0, 0x00d2}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00ce}, {1, 0, 0x0001}, {0, 1,-0x004a}, {0, 1,-0x004a}, {0, 1,-0x0056}, {0, 1,-0x0056}, {0, 1,-0x0056}, {0, 1,-0x0056}, {0, 1,-0x0064}, {0, 1,-0x0064}, {0, 1, 0x0001}, {1, 0, 0x00cd}, {1, 0, 0x00cd}, {1, 0, 0x0001}, {0, 1, 0x0001}, {0, 1, 0x0000}, {1, 0, 0x004f}, {1, 0, 0x00ca}, {0, 1, 0x0001}, {1, 0, 0x00d9}, {1, 0, 0x00d9}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00db}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0010}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0050}, {0, 1, 0x0056}, {0, 1, 0x0050}, {0, 1,-0x0007}, {0, 1, 0x0074}, {1, 0,-0x003c}, {0, 1, 0x0060}, {0, 0, 0x0000}, {1, 0, 0x0001}, {0, 1, 0x00d1}, {0, 1, 0x00d3}, {0, 1,-0xa544}, {0, 1,-0x29f7}, {0, 1,-0xa541}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x00d3}, {0, 1, 0x00da}, {0, 1, 0x0000}, {0, 1,-0xa543}, {0, 1, 0x00da}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1, 0x0000}, {0, 1,-0xa52a}, {0, 1, 0x186e}, {0, 1, 0x186d}, {0, 1, 0x1864}, {0, 1, 0x1862}, {0, 1, 0x1862}, {0, 1, 0x1863}, {0, 1, 0x185c}, {0, 1, 0x1825}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {0, 1, 0x97d0}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0010}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {1, 0, 0x0020}, {0, 1, 0x0026}, {0, 1, 0x0025}, {0, 1, 0x0025}, {0, 1, 0x0025}, {1, 0, 0x0025}, {1, 0, 0x0025}, {1, 0, 0x0025}, {0, 0, 0x0000}, {1, 0, 0x0040}, {0, 0, 0x0000}, {1, 0, 0x003f}, {1, 0, 0x003f}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x0050}, {1, 0, 0x00cb}, {1, 0, 0x0001}, {0, 1, 0x0001}, {1, 0, 0x00cd}, {1, 0, 0x00cf}, {0, 1,-0x0061}, {1, 0, 0x00d3}, {1, 0, 0x00d1}, {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0}, {1, 0, 0x97d0} }; static const uint16_t unicode_offsets1[908] = { 0x00a6, 0x0009, 0x000e, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x00ad, 0x00b3, 0x00b3, 0x00b3, 0x01ca, 0x01ca, 0x01ca, 0x01d0, 0x0009, 0x0009, 0x018e, 0x018e, 0x018e, 0x018e, 0x0190, 0x01f9, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0170, 0x0170, 0x0170, 0x0170, 0x0172, 0x0281, 0x0327, 0x0327, 0x0327, 0x0327, 0x0327, 0x032c, 0x00a5, 0x0165, 0x00a5, 0x00a6, 0x000c, 0x00aa, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0023, 0x0023, 0x0023, 0x0023, 0x0042, 0x0042, 0x0042, 0x0042, 0x0009, 0x0009, 0x0009, 0x0009, 0x0201, 0x0201, 0x0201, 0x0208, 0x020b, 0x020b, 0x020f, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0149, 0x0084, 0x0082, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x00a5, 0x034d, 0x0084, 0x0214, 0x0348, 0x0084, 0x0084, 0x0152, 0x029f, 0x0084, 0x00fd, 0x028f, 0x0084, 0x0316, 0x0009, 0x0009, 0x01c2, 0x00aa, 0x0239, 0x0239, 0x0239, 0x0231, 0x00a5, 0x00a5, 0x0235, 0x0239, 0x0239, 0x024e, 0x0162, 0x00a5, 0x00a5, 0x0239, 0x0239, 0x0239, 0x0231, 0x00a5, 0x00a5, 0x012c, 0x00e4, 0x0241, 0x024e, 0x01be, 0x0163, 0x00a5, 0x0239, 0x0239, 0x0239, 0x0231, 0x00a5, 0x00a5, 0x0162, 0x0235, 0x0239, 0x0239, 0x009f, 0x00a5, 0x00a5, 0x00a6, 0x0233, 0x0239, 0x0239, 0x023a, 0x00a5, 0x00a5, 0x00a5, 0x0166, 0x0239, 0x0239, 0x0239, 0x00a3, 0x00a5, 0x00a5, 0x0164, 0x01e9, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x015e, 0x0164, 0x00a5, 0x00ab, 0x03c3, 0x03c3, 0x03c3, 0x03c3, 0x03c3, 0x03c3, 0x03c3, 0x03c3, 0x03c3, 0x03c3, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a7, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x03bb, 0x00bb, 0x0334, 0x0334, 0x0334, 0x0334, 0x0334, 0x0339, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x01d3, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0145, 0x0287, 0x00be, 0x03db, 0x0059, 0x0023, 0x0020, 0x03d3, 0x0279, 0x0042, 0x021c, 0x0220, 0x00d7, 0x0084, 0x0084, 0x0084, 0x03a3, 0x013a, 0x0198, 0x0198, 0x0198, 0x0198, 0x019e, 0x01a0, 0x01a0, 0x01a0, 0x01a4, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x01ba, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x0166, 0x00aa, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0022, 0x0023, 0x0023, 0x005e, 0x0041, 0x0042, 0x0042, 0x027e, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0006, 0x0061, 0x0006, 0x0023, 0x0023, 0x005a, 0x0024, 0x0042, 0x0042, 0x027a, 0x0043, 0x031c, 0x022d, 0x0074, 0x0246, 0x031f, 0x0093, 0x0132, 0x0099, 0x01e3, 0x0297, 0x0009, 0x0009, 0x03cb, 0x03cb, 0x0393, 0x0393, 0x00ee, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x01db, 0x01db, 0x01db, 0x01db, 0x01db, 0x01db, 0x01e0, 0x0009, 0x01f1, 0x01f1, 0x01f1, 0x01f1, 0x01f1, 0x01f1, 0x01f6, 0x0009, 0x03e3, 0x03e3, 0x0023, 0x0023, 0x0023, 0x0023, 0x0042, 0x0042, 0x0042, 0x0042, 0x039b, 0x039b, 0x0084, 0x0084, 0x0084, 0x0084, 0x00bc, 0x0149, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0116, 0x0085, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x00cd, 0x00ce, 0x00ce, 0x00ce, 0x00cf, 0x0009, 0x025b, 0x025c, 0x025c, 0x025c, 0x025d, 0x0008, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0007, 0x000a, 0x0009, 0x0009, 0x00a5, 0x00a8, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0239, 0x0239, 0x0239, 0x00e9, 0x0239, 0x0239, 0x0239, 0x00e9, 0x0239, 0x0239, 0x0239, 0x0071, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x0272, 0x00a5, 0x02fc, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x00a5, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0143, 0x0009, 0x0009, 0x0084, 0x0084, 0x0084, 0x0293, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0023, 0x0023, 0x005b, 0x0009, 0x0042, 0x0042, 0x027b, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x02c7, 0x02c3, 0x02c7, 0x02c3, 0x02cc, 0x02d6, 0x02d3, 0x02d6, 0x02d3, 0x02dc, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0022, 0x0023, 0x0023, 0x005e, 0x0041, 0x0042, 0x0042, 0x027e, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x03f3, 0x03f3, 0x03f3, 0x03f3, 0x03f3, 0x03f3, 0x03f3, 0x03f3, 0x03f3, 0x03f3, 0x0227, 0x00de, 0x006d, 0x0249, 0x023c, 0x009f, 0x00a5, 0x00a5, 0x00a5, 0x023f, 0x008d, 0x024c, 0x00a3, 0x00a5, 0x00a5, 0x0235, 0x0239, 0x0239, 0x024e, 0x00a5, 0x00a5, 0x00a5, 0x0239, 0x0239, 0x0239, 0x0231, 0x00a5, 0x00a5, 0x0235, 0x0239, 0x0239, 0x024e, 0x00a5, 0x00a5, 0x00a5, 0x0239, 0x0239, 0x0239, 0x0231, 0x00a5, 0x00a5, 0x00a7, 0x0239, 0x0239, 0x0239, 0x00a3, 0x00a5, 0x00a5, 0x0164, 0x0237, 0x0239, 0x0239, 0x00a1, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0126, 0x0254, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x010c, 0x0083, 0x0118, 0x0124, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x035b, 0x0373, 0x0383, 0x03eb, 0x0104, 0x010e, 0x0341, 0x038b, 0x02e9, 0x00f3, 0x00f8, 0x0118, 0x014c, 0x0084, 0x0084, 0x0018, 0x0084, 0x0084, 0x0084, 0x0084, 0x0141, 0x0084, 0x0128, 0x0309, 0x0310, 0x0084, 0x004b, 0x0159, 0x0052, 0x03ab, 0x0303, 0x02f6, 0x03b3, 0x02f1, 0x01b7, 0x0011, 0x00a5, 0x00a5, 0x00a5, 0x0008, 0x00ab, 0x0009, 0x0009, 0x0009, 0x00a8, 0x0009, 0x0009, 0x0009, 0x00ce, 0x00ce, 0x00ce, 0x00ce, 0x00ce, 0x00ce, 0x025c, 0x025c, 0x025c, 0x025c, 0x025c, 0x025c, 0x0353, 0x011c, 0x02e4, 0x0168, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x0084, 0x02a3, 0x01a9, 0x00ef, 0x0009, 0x017a, 0x0184, 0x017c, 0x0186, 0x017a, 0x0184, 0x017a, 0x0184, 0x017c, 0x0186, 0x0264, 0x0033, 0x017a, 0x0184, 0x037b, 0x0000, 0x017a, 0x0184, 0x017a, 0x0184, 0x017a, 0x0184, 0x01b1, 0x003a, 0x0067, 0x0363, 0x026b, 0x002c, 0x007c, 0x036b, 0x0067, 0x00c6, 0x02ab, 0x02ab, 0x02ab, 0x02ab, 0x02ab, 0x02b7, 0x02b7, 0x02b7, 0x02b7, 0x02b7, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x02ab, 0x02ab, 0x02ab, 0x02ab, 0x02af, 0x02b7, 0x02b7, 0x02b7, 0x02b7, 0x02bb }; static const uint16_t unicode_offsets2[498] = { 0x016f, 0x02ed, 0x030c, 0x0127, 0x01c0, 0x01da, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0039, 0x0003, 0x0003, 0x0280, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x010f, 0x0218, 0x02d3, 0x034c, 0x01ec, 0x018f, 0x0003, 0x0003, 0x000d, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x032c, 0x002d, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0230, 0x008d, 0x0003, 0x0003, 0x0003, 0x00e5, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0000, 0x0003, 0x0003, 0x0003, 0x0274, 0x0003, 0x0003, 0x0003, 0x0003, 0x036c, 0x0258, 0x0003, 0x0157, 0x0003, 0x0003, 0x0003, 0x0003, 0x01a0, 0x0246, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0065, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0071, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x00ad, 0x02a0, 0x02b3, 0x00cb, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0059, 0x00ff, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0147, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0206 }; static inline const struct CaseMappings * get_unicode_entry(xkb_keysym_t ks) { return &unicode_data[unicode_offsets1[unicode_offsets2[ks >> 8] + ((ks >> 3) & 0x1f)] + (ks & 0x07)]; } xkb_keysym_t xkb_keysym_to_lower(xkb_keysym_t ks) { if (ks <= 0x13be) { const struct CaseMappings *m = get_legacy_keysym_entry(ks); return (m->lower) ? ks + m->offset : ks; } else if (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= 0x0101f189) { const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET); if (m->lower) { ks = ks + m->offset; return (ks < XKB_KEYSYM_UNICODE_MIN) ? ks - XKB_KEYSYM_UNICODE_OFFSET : ks; } else { return ks; } } else { return ks; } } xkb_keysym_t xkb_keysym_to_upper(xkb_keysym_t ks) { if (ks <= 0x13be) { const struct CaseMappings *m = get_legacy_keysym_entry(ks); return (m->upper) ? ks - m->offset : ks; } else if (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= 0x0101f189) { const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET); if (m->upper) { ks = ks - m->offset; return (ks < XKB_KEYSYM_UNICODE_MIN) ? ks - XKB_KEYSYM_UNICODE_OFFSET : ks; } else { return ks; } } else { return ks; } } bool xkb_keysym_is_lower(xkb_keysym_t ks) { /* This predicate matches keysyms with their corresponding Unicode code point * having the Unicode property “Lowercase”. * * Here: a keysym is lower case if it has an upper case and no lower case. * Note: title case letters may have both. Example for U+01F2: * • U+01F1 DZ: upper case * • U+01F2 Dz: title case * • U+01F3 dz: lower case */ if (ks <= 0x13be) { const struct CaseMappings *m = get_legacy_keysym_entry(ks); return m->upper && !m->lower; } else if (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= 0x0101f189) { const struct CaseMappings *m = get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET); return m->upper && !m->lower; } else { return false; } } bool xkb_keysym_is_upper_or_title(xkb_keysym_t ks) { /* This predicate matches keysyms with their corresponding Unicode code point * having the Unicode properties “Uppercase” or General Category “Lt”. * * Here: a keysym is upper case or title case if it has a lower case. */ if (ks <= 0x13be) { return get_legacy_keysym_entry(ks)->lower; } else if (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= 0x0101f189) { return get_unicode_entry(ks - XKB_KEYSYM_UNICODE_OFFSET)->lower; } else { return false; } } xkbcommon-libxkbcommon-54ee7ac/src/keysym-utf.c000066400000000000000000002275401510033435100217450ustar00rootroot00000000000000/* The table and comments below along with the function xkb_keysym_to_ucs4 * are under the public domain and are derived as described below. */ /* This module converts keysym values into the corresponding ISO 10646 * (UCS, Unicode) values. * * The array keysymtab[] contains pairs of X11 keysym values for graphical * characters and the corresponding Unicode value. The function * keysym2ucs() maps a keysym onto a Unicode value using a binary search, * therefore keysymtab[] must remain SORTED by keysym value. * * The keysym -> UTF-8 conversion will hopefully one day be provided * by Xlib via XmbLookupString() and should ideally not have to be * done in X applications. But we are not there yet. * * We allow to represent any UCS character in the range U-00000000 to * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff. * This admittedly does not cover the entire 31-bit space of UCS, but * it does cover all of the characters up to U-10FFFF, which can be * represented by UTF-16, and more, and it is very unlikely that higher * UCS codes will ever be assigned by ISO. So to get Unicode character * U+ABCD you can directly use keysym 0x0100abcd. * * NOTE: The comments in the table below contain the actual character * encoded in UTF-8, so for viewing and editing best use an editor in * UTF-8 mode. * * Author: Markus G. Kuhn , * University of Cambridge, April 2001 * * Special thanks to Richard Verhoeven for preparing * an initial draft of the mapping table. * * This software is in the public domain. Share and enjoy! * */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "utils.h" #include "utf8.h" #include "keysym.h" #define NO_KEYSYM_UNICODE_CONVERSION 0 /* We don't use the uint32_t types here, to save some space. */ struct codepair { uint16_t keysym:15; bool deprecated:1; uint16_t ucs; }; static const struct codepair keysymtab[] = { { 0x01a1, false, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */ { 0x01a2, false, 0x02d8 }, /* breve ˘ BREVE */ { 0x01a3, false, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */ { 0x01a5, false, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */ { 0x01a6, false, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */ { 0x01a9, false, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */ { 0x01aa, false, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */ { 0x01ab, false, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */ { 0x01ac, false, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */ { 0x01ae, false, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */ { 0x01af, false, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */ { 0x01b1, false, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */ { 0x01b2, false, 0x02db }, /* ogonek ˛ OGONEK */ { 0x01b3, false, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */ { 0x01b5, false, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */ { 0x01b6, false, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */ { 0x01b7, false, 0x02c7 }, /* caron ˇ CARON */ { 0x01b9, false, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */ { 0x01ba, false, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */ { 0x01bb, false, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */ { 0x01bc, false, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */ { 0x01bd, false, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */ { 0x01be, false, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */ { 0x01bf, false, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */ { 0x01c0, false, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */ { 0x01c3, false, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */ { 0x01c5, false, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */ { 0x01c6, false, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */ { 0x01c8, false, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */ { 0x01ca, false, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */ { 0x01cc, false, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */ { 0x01cf, false, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */ { 0x01d0, false, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */ { 0x01d1, false, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */ { 0x01d2, false, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */ { 0x01d5, false, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ { 0x01d8, false, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */ { 0x01d9, false, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */ { 0x01db, false, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ { 0x01de, false, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */ { 0x01e0, false, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */ { 0x01e3, false, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */ { 0x01e5, false, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */ { 0x01e6, false, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */ { 0x01e8, false, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */ { 0x01ea, false, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */ { 0x01ec, false, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */ { 0x01ef, false, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */ { 0x01f0, false, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */ { 0x01f1, false, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */ { 0x01f2, false, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */ { 0x01f5, false, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */ { 0x01f8, false, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */ { 0x01f9, false, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */ { 0x01fb, false, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */ { 0x01fe, false, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */ { 0x01ff, false, 0x02d9 }, /* abovedot ˙ DOT ABOVE */ { 0x02a1, false, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */ { 0x02a6, false, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ { 0x02a9, false, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */ { 0x02ab, false, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */ { 0x02ac, false, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ { 0x02b1, false, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */ { 0x02b6, false, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */ { 0x02b9, false, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */ { 0x02bb, false, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */ { 0x02bc, false, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */ { 0x02c5, false, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */ { 0x02c6, false, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ { 0x02d5, false, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */ { 0x02d8, false, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ { 0x02dd, false, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */ { 0x02de, false, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ { 0x02e5, false, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */ { 0x02e6, false, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */ { 0x02f5, false, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */ { 0x02f8, false, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */ { 0x02fd, false, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */ { 0x02fe, false, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */ { 0x03a2, false, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */ { 0x03a3, false, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */ { 0x03a5, false, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */ { 0x03a6, false, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */ { 0x03aa, false, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */ { 0x03ab, false, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */ { 0x03ac, false, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */ { 0x03b3, false, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */ { 0x03b5, false, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */ { 0x03b6, false, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */ { 0x03ba, false, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */ { 0x03bb, false, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */ { 0x03bc, false, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */ { 0x03bd, false, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */ { 0x03bf, false, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */ { 0x03c0, false, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */ { 0x03c7, false, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */ { 0x03cc, false, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */ { 0x03cf, false, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */ { 0x03d1, false, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */ { 0x03d2, false, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */ { 0x03d3, false, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */ { 0x03d9, false, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */ { 0x03dd, false, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */ { 0x03de, false, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */ { 0x03e0, false, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */ { 0x03e7, false, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */ { 0x03ec, false, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */ { 0x03ef, false, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */ { 0x03f1, false, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */ { 0x03f2, false, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */ { 0x03f3, false, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */ { 0x03f9, false, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */ { 0x03fd, false, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */ { 0x03fe, false, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */ { 0x047e, false, 0x203e }, /* overline ‾ OVERLINE */ { 0x04a1, false, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */ { 0x04a2, false, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */ { 0x04a3, false, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */ { 0x04a4, false, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */ { 0x04a5, false, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */ { 0x04a6, false, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */ { 0x04a7, false, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */ { 0x04a8, false, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */ { 0x04a9, false, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */ { 0x04aa, false, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */ { 0x04ab, false, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */ { 0x04ac, false, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */ { 0x04ad, false, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */ { 0x04ae, false, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */ { 0x04af, false, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */ { 0x04b0, false, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */ { 0x04b1, false, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */ { 0x04b2, false, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */ { 0x04b3, false, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */ { 0x04b4, false, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */ { 0x04b5, false, 0x30aa }, /* kana_O オ KATAKANA LETTER O */ { 0x04b6, false, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */ { 0x04b7, false, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */ { 0x04b8, false, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */ { 0x04b9, false, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */ { 0x04ba, false, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */ { 0x04bb, false, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */ { 0x04bc, false, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */ { 0x04bd, false, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */ { 0x04be, false, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */ { 0x04bf, false, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */ { 0x04c0, false, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */ { 0x04c1, false, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */ { 0x04c2, false, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */ { 0x04c3, false, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */ { 0x04c4, false, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */ { 0x04c5, false, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */ { 0x04c6, false, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */ { 0x04c7, false, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */ { 0x04c8, false, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */ { 0x04c9, false, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */ { 0x04ca, false, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */ { 0x04cb, false, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */ { 0x04cc, false, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */ { 0x04cd, false, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */ { 0x04ce, false, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */ { 0x04cf, false, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */ { 0x04d0, false, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */ { 0x04d1, false, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */ { 0x04d2, false, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */ { 0x04d3, false, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */ { 0x04d4, false, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */ { 0x04d5, false, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */ { 0x04d6, false, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */ { 0x04d7, false, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */ { 0x04d8, false, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */ { 0x04d9, false, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */ { 0x04da, false, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */ { 0x04db, false, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */ { 0x04dc, false, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */ { 0x04dd, false, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */ { 0x04de, false, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */ { 0x04df, false, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */ { 0x05ac, false, 0x060c }, /* Arabic_comma ، ARABIC COMMA */ { 0x05bb, false, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */ { 0x05bf, false, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */ { 0x05c1, false, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */ { 0x05c2, false, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */ { 0x05c3, false, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */ { 0x05c4, false, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */ { 0x05c5, false, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */ { 0x05c6, false, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */ { 0x05c7, false, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */ { 0x05c8, false, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */ { 0x05c9, false, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */ { 0x05ca, false, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */ { 0x05cb, false, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */ { 0x05cc, false, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */ { 0x05cd, false, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */ { 0x05ce, false, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */ { 0x05cf, false, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */ { 0x05d0, false, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */ { 0x05d1, false, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */ { 0x05d2, false, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */ { 0x05d3, false, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */ { 0x05d4, false, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */ { 0x05d5, false, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */ { 0x05d6, false, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */ { 0x05d7, false, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */ { 0x05d8, false, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */ { 0x05d9, false, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */ { 0x05da, false, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */ { 0x05e0, false, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */ { 0x05e1, false, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */ { 0x05e2, false, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */ { 0x05e3, false, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */ { 0x05e4, false, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */ { 0x05e5, false, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */ { 0x05e6, false, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */ { 0x05e7, false, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */ { 0x05e8, false, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */ { 0x05e9, false, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */ { 0x05ea, false, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */ { 0x05eb, false, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */ { 0x05ec, false, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */ { 0x05ed, false, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */ { 0x05ee, false, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */ { 0x05ef, false, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */ { 0x05f0, false, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */ { 0x05f1, false, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */ { 0x05f2, false, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */ { 0x06a1, false, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */ { 0x06a2, false, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */ { 0x06a3, false, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */ { 0x06a4, false, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */ { 0x06a5, false, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */ { 0x06a6, false, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */ { 0x06a7, false, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */ { 0x06a8, false, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */ { 0x06a9, false, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */ { 0x06aa, false, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */ { 0x06ab, false, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */ { 0x06ac, false, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */ { 0x06ad, false, 0x0491 }, /* Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN */ { 0x06ae, false, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */ { 0x06af, false, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */ { 0x06b0, false, 0x2116 }, /* numerosign № NUMERO SIGN */ { 0x06b1, false, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */ { 0x06b2, false, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */ { 0x06b3, false, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */ { 0x06b4, false, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */ { 0x06b5, false, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */ { 0x06b6, false, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ { 0x06b7, false, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */ { 0x06b8, false, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */ { 0x06b9, false, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */ { 0x06ba, false, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */ { 0x06bb, false, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */ { 0x06bc, false, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */ { 0x06bd, false, 0x0490 }, /* Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ { 0x06be, false, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */ { 0x06bf, false, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */ { 0x06c0, false, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */ { 0x06c1, false, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */ { 0x06c2, false, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */ { 0x06c3, false, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */ { 0x06c4, false, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */ { 0x06c5, false, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */ { 0x06c6, false, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */ { 0x06c7, false, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */ { 0x06c8, false, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */ { 0x06c9, false, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */ { 0x06ca, false, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */ { 0x06cb, false, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */ { 0x06cc, false, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */ { 0x06cd, false, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */ { 0x06ce, false, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */ { 0x06cf, false, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */ { 0x06d0, false, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */ { 0x06d1, false, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */ { 0x06d2, false, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */ { 0x06d3, false, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */ { 0x06d4, false, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */ { 0x06d5, false, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */ { 0x06d6, false, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */ { 0x06d7, false, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */ { 0x06d8, false, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */ { 0x06d9, false, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */ { 0x06da, false, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */ { 0x06db, false, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */ { 0x06dc, false, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */ { 0x06dd, false, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */ { 0x06de, false, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */ { 0x06df, false, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */ { 0x06e0, false, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */ { 0x06e1, false, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */ { 0x06e2, false, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */ { 0x06e3, false, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */ { 0x06e4, false, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */ { 0x06e5, false, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */ { 0x06e6, false, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */ { 0x06e7, false, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */ { 0x06e8, false, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */ { 0x06e9, false, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */ { 0x06ea, false, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */ { 0x06eb, false, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */ { 0x06ec, false, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */ { 0x06ed, false, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */ { 0x06ee, false, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */ { 0x06ef, false, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */ { 0x06f0, false, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */ { 0x06f1, false, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */ { 0x06f2, false, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */ { 0x06f3, false, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */ { 0x06f4, false, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */ { 0x06f5, false, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */ { 0x06f6, false, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */ { 0x06f7, false, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */ { 0x06f8, false, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */ { 0x06f9, false, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */ { 0x06fa, false, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */ { 0x06fb, false, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */ { 0x06fc, false, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */ { 0x06fd, false, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */ { 0x06fe, false, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */ { 0x06ff, false, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */ { 0x07a1, false, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */ { 0x07a2, false, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */ { 0x07a3, false, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */ { 0x07a4, false, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */ { 0x07a5, false, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ { 0x07a7, false, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */ { 0x07a8, false, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */ { 0x07a9, false, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ { 0x07ab, false, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */ { 0x07ae, false, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */ { 0x07af, false, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */ { 0x07b1, false, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */ { 0x07b2, false, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */ { 0x07b3, false, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */ { 0x07b4, false, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */ { 0x07b5, false, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */ { 0x07b6, false, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ { 0x07b7, false, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */ { 0x07b8, false, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */ { 0x07b9, false, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */ { 0x07ba, false, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ { 0x07bb, false, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */ { 0x07c1, false, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */ { 0x07c2, false, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */ { 0x07c3, false, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */ { 0x07c4, false, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */ { 0x07c5, false, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */ { 0x07c6, false, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */ { 0x07c7, false, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */ { 0x07c8, false, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */ { 0x07c9, false, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */ { 0x07ca, false, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */ { 0x07cb, false, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */ { 0x07cc, false, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */ { 0x07cd, false, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */ { 0x07ce, false, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */ { 0x07cf, false, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */ { 0x07d0, false, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */ { 0x07d1, false, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */ { 0x07d2, false, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */ { 0x07d4, false, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */ { 0x07d5, false, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */ { 0x07d6, false, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */ { 0x07d7, false, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */ { 0x07d8, false, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */ { 0x07d9, false, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */ { 0x07e1, false, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */ { 0x07e2, false, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */ { 0x07e3, false, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */ { 0x07e4, false, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */ { 0x07e5, false, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */ { 0x07e6, false, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */ { 0x07e7, false, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */ { 0x07e8, false, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */ { 0x07e9, false, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */ { 0x07ea, false, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */ { 0x07eb, false, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */ { 0x07ec, false, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */ { 0x07ed, false, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */ { 0x07ee, false, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */ { 0x07ef, false, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */ { 0x07f0, false, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */ { 0x07f1, false, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */ { 0x07f2, false, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */ { 0x07f3, false, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */ { 0x07f4, false, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */ { 0x07f5, false, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */ { 0x07f6, false, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */ { 0x07f7, false, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */ { 0x07f8, false, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */ { 0x07f9, false, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */ { 0x08a1, false, 0x23b7 }, /* leftradical ⎷ ??? */ { 0x08a2, true, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ { 0x08a3, true, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */ { 0x08a4, false, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */ { 0x08a5, false, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */ { 0x08a6, true, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */ { 0x08a7, false, 0x23a1 }, /* topleftsqbracket ⎡ ??? */ { 0x08a8, false, 0x23a3 }, /* botleftsqbracket ⎣ ??? */ { 0x08a9, false, 0x23a4 }, /* toprightsqbracket ⎤ ??? */ { 0x08aa, false, 0x23a6 }, /* botrightsqbracket ⎦ ??? */ { 0x08ab, false, 0x239b }, /* topleftparens ⎛ ??? */ { 0x08ac, false, 0x239d }, /* botleftparens ⎝ ??? */ { 0x08ad, false, 0x239e }, /* toprightparens ⎞ ??? */ { 0x08ae, false, 0x23a0 }, /* botrightparens ⎠ ??? */ { 0x08af, false, 0x23a8 }, /* leftmiddlecurlybrace ⎨ ??? */ { 0x08b0, false, 0x23ac }, /* rightmiddlecurlybrace ⎬ ??? */ /* 0x08b1 topleftsummation ? ??? */ /* 0x08b2 botleftsummation ? ??? */ /* 0x08b3 topvertsummationconnector ? ??? */ /* 0x08b4 botvertsummationconnector ? ??? */ /* 0x08b5 toprightsummation ? ??? */ /* 0x08b6 botrightsummation ? ??? */ /* 0x08b7 rightmiddlesummation ? ??? */ { 0x08bc, false, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */ { 0x08bd, false, 0x2260 }, /* notequal ≠ NOT EQUAL TO */ { 0x08be, false, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */ { 0x08bf, false, 0x222b }, /* integral ∫ INTEGRAL */ { 0x08c0, false, 0x2234 }, /* therefore ∴ THEREFORE */ { 0x08c1, false, 0x221d }, /* variation ∝ PROPORTIONAL TO */ { 0x08c2, false, 0x221e }, /* infinity ∞ INFINITY */ { 0x08c5, false, 0x2207 }, /* nabla ∇ NABLA */ { 0x08c8, false, 0x223c }, /* approximate ∼ TILDE OPERATOR */ { 0x08c9, false, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */ { 0x08cd, false, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */ { 0x08ce, false, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */ { 0x08cf, false, 0x2261 }, /* identical ≡ IDENTICAL TO */ { 0x08d6, false, 0x221a }, /* radical √ SQUARE ROOT */ { 0x08da, false, 0x2282 }, /* includedin ⊂ SUBSET OF */ { 0x08db, false, 0x2283 }, /* includes ⊃ SUPERSET OF */ { 0x08dc, false, 0x2229 }, /* intersection ∩ INTERSECTION */ { 0x08dd, false, 0x222a }, /* union ∪ UNION */ { 0x08de, false, 0x2227 }, /* logicaland ∧ LOGICAL AND */ { 0x08df, false, 0x2228 }, /* logicalor ∨ LOGICAL OR */ { 0x08ef, false, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */ { 0x08f6, false, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */ { 0x08fb, false, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */ { 0x08fc, false, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */ { 0x08fd, false, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */ { 0x08fe, false, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */ /* 0x09df blank ? ??? */ { 0x09e0, false, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */ { 0x09e1, false, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */ { 0x09e2, false, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */ { 0x09e3, false, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */ { 0x09e4, false, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */ { 0x09e5, false, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */ { 0x09e8, false, 0x2424 }, /* nl ␤ SYMBOL FOR NEWLINE */ { 0x09e9, false, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */ { 0x09ea, false, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */ { 0x09eb, false, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */ { 0x09ec, false, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */ { 0x09ed, false, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */ { 0x09ee, false, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */ { 0x09ef, false, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */ { 0x09f0, false, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */ { 0x09f1, false, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */ { 0x09f2, false, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */ { 0x09f3, false, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */ { 0x09f4, false, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */ { 0x09f5, false, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */ { 0x09f6, false, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */ { 0x09f7, false, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */ { 0x09f8, false, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */ { 0x0aa1, false, 0x2003 }, /* emspace   EM SPACE */ { 0x0aa2, false, 0x2002 }, /* enspace   EN SPACE */ { 0x0aa3, false, 0x2004 }, /* em3space   THREE-PER-EM SPACE */ { 0x0aa4, false, 0x2005 }, /* em4space   FOUR-PER-EM SPACE */ { 0x0aa5, false, 0x2007 }, /* digitspace   FIGURE SPACE */ { 0x0aa6, false, 0x2008 }, /* punctspace   PUNCTUATION SPACE */ { 0x0aa7, false, 0x2009 }, /* thinspace   THIN SPACE */ { 0x0aa8, false, 0x200a }, /* hairspace   HAIR SPACE */ { 0x0aa9, false, 0x2014 }, /* emdash — EM DASH */ { 0x0aaa, false, 0x2013 }, /* endash – EN DASH */ { 0x0aac, true, 0x2423 }, /* signifblank ␣ OPEN BOX */ { 0x0aae, false, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */ { 0x0aaf, false, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */ { 0x0ab0, false, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */ { 0x0ab1, false, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */ { 0x0ab2, false, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */ { 0x0ab3, false, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */ { 0x0ab4, false, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */ { 0x0ab5, false, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */ { 0x0ab6, false, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */ { 0x0ab7, false, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */ { 0x0ab8, false, 0x2105 }, /* careof ℅ CARE OF */ { 0x0abb, false, 0x2012 }, /* figdash ‒ FIGURE DASH */ { 0x0abc, true, 0x27e8 }, /* leftanglebracket ⟨ MATHEMATICAL LEFT ANGLE BRACKET */ { 0x0abd, true, 0x002e }, /* decimalpoint . FULL STOP */ { 0x0abe, true, 0x27e9 }, /* rightanglebracket ⟩ MATHEMATICAL RIGHT ANGLE BRACKET */ /* 0x0abf marker ? ??? */ { 0x0ac3, false, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */ { 0x0ac4, false, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */ { 0x0ac5, false, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */ { 0x0ac6, false, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */ { 0x0ac9, false, 0x2122 }, /* trademark ™ TRADE MARK SIGN */ { 0x0aca, true, 0x2613 }, /* signaturemark ☓ SALTIRE */ /* 0x0acb trademarkincircle ? ??? */ { 0x0acc, true, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */ { 0x0acd, true, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */ { 0x0ace, true, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */ { 0x0acf, true, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */ { 0x0ad0, false, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */ { 0x0ad1, false, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */ { 0x0ad2, false, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */ { 0x0ad3, false, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */ { 0x0ad4, false, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */ { 0x0ad5, false, 0x2030 }, /* permille ‰ PER MILLE SIGN */ { 0x0ad6, false, 0x2032 }, /* minutes ′ PRIME */ { 0x0ad7, false, 0x2033 }, /* seconds ″ DOUBLE PRIME */ { 0x0ad9, false, 0x271d }, /* latincross ✝ LATIN CROSS */ /* 0x0ada hexagram ? ??? */ { 0x0adb, true, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */ { 0x0adc, true, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */ { 0x0add, true, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */ { 0x0ade, true, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */ { 0x0adf, true, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */ { 0x0ae0, true, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */ { 0x0ae1, true, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */ { 0x0ae2, true, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */ { 0x0ae3, true, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */ { 0x0ae4, true, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */ { 0x0ae5, true, 0x2606 }, /* openstar ☆ WHITE STAR */ { 0x0ae6, true, 0x2022 }, /* enfilledcircbullet • BULLET */ { 0x0ae7, true, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */ { 0x0ae8, true, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */ { 0x0ae9, true, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */ { 0x0aea, true, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */ { 0x0aeb, true, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */ { 0x0aec, false, 0x2663 }, /* club ♣ BLACK CLUB SUIT */ { 0x0aed, false, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */ { 0x0aee, false, 0x2665 }, /* heart ♥ BLACK HEART SUIT */ { 0x0af0, false, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */ { 0x0af1, false, 0x2020 }, /* dagger † DAGGER */ { 0x0af2, false, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */ { 0x0af3, false, 0x2713 }, /* checkmark ✓ CHECK MARK */ { 0x0af4, false, 0x2717 }, /* ballotcross ✗ BALLOT X */ { 0x0af5, false, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */ { 0x0af6, false, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */ { 0x0af7, false, 0x2642 }, /* malesymbol ♂ MALE SIGN */ { 0x0af8, false, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */ { 0x0af9, false, 0x260e }, /* telephone ☎ BLACK TELEPHONE */ { 0x0afa, false, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */ { 0x0afb, false, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */ { 0x0afc, false, 0x2038 }, /* caret ‸ CARET */ { 0x0afd, false, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */ { 0x0afe, false, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */ /* 0x0aff cursor ? ??? */ { 0x0ba3, true, 0x003c }, /* leftcaret < LESS-THAN SIGN */ { 0x0ba6, true, 0x003e }, /* rightcaret > GREATER-THAN SIGN */ { 0x0ba8, true, 0x2228 }, /* downcaret ∨ LOGICAL OR */ { 0x0ba9, true, 0x2227 }, /* upcaret ∧ LOGICAL AND */ { 0x0bc0, true, 0x00af }, /* overbar ¯ MACRON */ { 0x0bc2, false, 0x22a4 }, /* downtack ⊤ DOWN TACK */ { 0x0bc3, true, 0x2229 }, /* upshoe ∩ INTERSECTION */ { 0x0bc4, false, 0x230a }, /* downstile ⌊ LEFT FLOOR */ { 0x0bc6, true, 0x005f }, /* underbar _ LOW LINE */ { 0x0bca, false, 0x2218 }, /* jot ∘ RING OPERATOR */ { 0x0bcc, false, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) */ { 0x0bce, false, 0x22a5 }, /* uptack ⊥ UP TACK */ { 0x0bcf, false, 0x25cb }, /* circle ○ WHITE CIRCLE */ { 0x0bd3, false, 0x2308 }, /* upstile ⌈ LEFT CEILING */ { 0x0bd6, true, 0x222a }, /* downshoe ∪ UNION */ { 0x0bd8, true, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */ { 0x0bda, true, 0x2282 }, /* leftshoe ⊂ SUBSET OF */ { 0x0bdc, false, 0x22a3 }, /* lefttack ⊣ LEFT TACK */ { 0x0bfc, false, 0x22a2 }, /* righttack ⊢ RIGHT TACK */ { 0x0cdf, false, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */ { 0x0ce0, false, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */ { 0x0ce1, false, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */ { 0x0ce2, false, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */ { 0x0ce3, false, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */ { 0x0ce4, false, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */ { 0x0ce5, false, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */ { 0x0ce6, false, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */ { 0x0ce7, false, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */ { 0x0ce8, false, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */ { 0x0ce9, false, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */ { 0x0cea, false, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */ { 0x0ceb, false, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */ { 0x0cec, false, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */ { 0x0ced, false, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */ { 0x0cee, false, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */ { 0x0cef, false, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */ { 0x0cf0, false, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */ { 0x0cf1, false, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */ { 0x0cf2, false, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */ { 0x0cf3, false, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */ { 0x0cf4, false, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */ { 0x0cf5, false, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */ { 0x0cf6, false, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */ { 0x0cf7, false, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */ { 0x0cf8, false, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */ { 0x0cf9, false, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */ { 0x0cfa, false, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */ { 0x0da1, false, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */ { 0x0da2, false, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */ { 0x0da3, false, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */ { 0x0da4, false, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */ { 0x0da5, false, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */ { 0x0da6, false, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */ { 0x0da7, false, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */ { 0x0da8, false, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */ { 0x0da9, false, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */ { 0x0daa, false, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */ { 0x0dab, false, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */ { 0x0dac, false, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */ { 0x0dad, false, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */ { 0x0dae, false, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */ { 0x0daf, false, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */ { 0x0db0, false, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */ { 0x0db1, false, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */ { 0x0db2, false, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */ { 0x0db3, false, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */ { 0x0db4, false, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */ { 0x0db5, false, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */ { 0x0db6, false, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */ { 0x0db7, false, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */ { 0x0db8, false, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */ { 0x0db9, false, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */ { 0x0dba, false, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */ { 0x0dbb, false, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */ { 0x0dbc, false, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */ { 0x0dbd, false, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */ { 0x0dbe, false, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */ { 0x0dbf, false, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */ { 0x0dc0, false, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */ { 0x0dc1, false, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */ { 0x0dc2, false, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */ { 0x0dc3, false, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */ { 0x0dc4, false, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */ { 0x0dc5, false, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */ { 0x0dc6, false, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */ { 0x0dc7, false, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */ { 0x0dc8, false, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */ { 0x0dc9, false, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */ { 0x0dca, false, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */ { 0x0dcb, false, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */ { 0x0dcc, false, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */ { 0x0dcd, false, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */ { 0x0dce, false, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */ { 0x0dcf, false, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */ { 0x0dd0, false, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */ { 0x0dd1, false, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */ { 0x0dd2, false, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */ { 0x0dd3, false, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */ { 0x0dd4, false, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */ { 0x0dd5, false, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */ { 0x0dd6, false, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */ { 0x0dd7, false, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */ { 0x0dd8, false, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */ { 0x0dd9, false, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */ { 0x0dda, false, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */ { 0x0dde, true, 0x0e3e }, /* Thai_maihanakat_maitho ฾ ??? */ { 0x0ddf, false, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */ { 0x0de0, false, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */ { 0x0de1, false, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */ { 0x0de2, false, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */ { 0x0de3, false, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */ { 0x0de4, false, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */ { 0x0de5, false, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */ { 0x0de6, false, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */ { 0x0de7, false, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */ { 0x0de8, false, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */ { 0x0de9, false, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */ { 0x0dea, false, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */ { 0x0deb, false, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */ { 0x0dec, false, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */ { 0x0ded, false, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */ { 0x0df0, false, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */ { 0x0df1, false, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */ { 0x0df2, false, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */ { 0x0df3, false, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */ { 0x0df4, false, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */ { 0x0df5, false, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */ { 0x0df6, false, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */ { 0x0df7, false, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */ { 0x0df8, false, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */ { 0x0df9, false, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */ { 0x0ea1, false, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */ { 0x0ea2, false, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */ { 0x0ea3, false, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */ { 0x0ea4, false, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */ { 0x0ea5, false, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */ { 0x0ea6, false, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */ { 0x0ea7, false, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */ { 0x0ea8, false, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */ { 0x0ea9, false, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */ { 0x0eaa, false, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */ { 0x0eab, false, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */ { 0x0eac, false, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */ { 0x0ead, false, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */ { 0x0eae, false, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */ { 0x0eaf, false, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */ { 0x0eb0, false, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */ { 0x0eb1, false, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */ { 0x0eb2, false, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */ { 0x0eb3, false, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */ { 0x0eb4, false, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */ { 0x0eb5, false, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */ { 0x0eb6, false, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */ { 0x0eb7, false, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */ { 0x0eb8, false, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */ { 0x0eb9, false, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */ { 0x0eba, false, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */ { 0x0ebb, false, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */ { 0x0ebc, false, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */ { 0x0ebd, false, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */ { 0x0ebe, false, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */ { 0x0ebf, false, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */ { 0x0ec0, false, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */ { 0x0ec1, false, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */ { 0x0ec2, false, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */ { 0x0ec3, false, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */ { 0x0ec4, false, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */ { 0x0ec5, false, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */ { 0x0ec6, false, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */ { 0x0ec7, false, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */ { 0x0ec8, false, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */ { 0x0ec9, false, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */ { 0x0eca, false, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */ { 0x0ecb, false, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */ { 0x0ecc, false, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */ { 0x0ecd, false, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */ { 0x0ece, false, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */ { 0x0ecf, false, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */ { 0x0ed0, false, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */ { 0x0ed1, false, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */ { 0x0ed2, false, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */ { 0x0ed3, false, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */ { 0x0ed4, false, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */ { 0x0ed5, false, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */ { 0x0ed6, false, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */ { 0x0ed7, false, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */ { 0x0ed8, false, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */ { 0x0ed9, false, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */ { 0x0eda, false, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */ { 0x0edb, false, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */ { 0x0edc, false, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */ { 0x0edd, false, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */ { 0x0ede, false, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */ { 0x0edf, false, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */ { 0x0ee0, false, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */ { 0x0ee1, false, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */ { 0x0ee2, false, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */ { 0x0ee3, false, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */ { 0x0ee4, false, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */ { 0x0ee5, false, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */ { 0x0ee6, false, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */ { 0x0ee7, false, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */ { 0x0ee8, false, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */ { 0x0ee9, false, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */ { 0x0eea, false, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */ { 0x0eeb, false, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */ { 0x0eec, false, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */ { 0x0eed, false, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */ { 0x0eee, false, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */ { 0x0eef, false, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */ { 0x0ef0, false, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */ { 0x0ef1, false, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */ { 0x0ef2, false, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */ { 0x0ef3, false, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */ { 0x0ef4, false, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */ { 0x0ef5, false, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */ { 0x0ef6, false, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */ { 0x0ef7, false, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */ { 0x0ef8, false, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */ { 0x0ef9, false, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */ { 0x0efa, false, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */ { 0x0eff, true, 0x20a9 }, /* Korean_Won ₩ WON SIGN */ { 0x13bc, false, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */ { 0x13bd, false, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */ { 0x13be, false, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */ { 0x20ac, false, 0x20ac }, /* EuroSign € EURO SIGN */ }; /* binary search with range check */ static uint32_t bin_search(const struct codepair *table, size_t length, xkb_keysym_t keysym) { size_t first = 0; size_t last = length; if (keysym < table[0].keysym || keysym > table[length].keysym) return 0; /* binary search in table */ while (last >= first) { size_t mid = (first + last) / 2; if (table[mid].keysym < keysym) first = mid + 1; else if (table[mid].keysym > keysym) last = mid - 1; else /* found it */ return table[mid].ucs; } /* no matching Unicode value found in table */ return NO_KEYSYM_UNICODE_CONVERSION; } uint32_t xkb_keysym_to_utf32(xkb_keysym_t keysym) { /* first check for Latin-1 characters (1:1 mapping) */ if ((keysym >= 0x0020 && keysym <= 0x007e) || (keysym >= 0x00a0 && keysym <= 0x00ff)) return keysym; /* patch encoding botch */ if (keysym == XKB_KEY_KP_Space) return XKB_KEY_space & 0x7f; /* special keysyms */ if ((keysym >= XKB_KEY_BackSpace && keysym <= XKB_KEY_Clear) || (keysym >= XKB_KEY_KP_Multiply && keysym <= XKB_KEY_KP_9) || keysym == XKB_KEY_Return || keysym == XKB_KEY_Escape || keysym == XKB_KEY_Delete || keysym == XKB_KEY_KP_Tab || keysym == XKB_KEY_KP_Enter || keysym == XKB_KEY_KP_Equal) return keysym & 0x7f; /* also check for directly encoded Unicode codepoints */ /* Exclude surrogates: they are invalid in UTF-32. * See https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G28875 * for further details. */ if (keysym >= XKB_KEYSYM_UNICODE_SURROGATE_MIN && keysym <= XKB_KEYSYM_UNICODE_SURROGATE_MAX) return NO_KEYSYM_UNICODE_CONVERSION; /* * In theory, this is supposed to start from 0x100100, such that the ASCII * range, which is already covered by 0x00-0xff, can't be encoded in two * ways. However, changing this after a couple of decades probably won't * go well, so it stays as it is. */ if (XKB_KEYSYM_UNICODE_OFFSET <= keysym && keysym <= XKB_KEYSYM_UNICODE_MAX) return keysym - XKB_KEYSYM_UNICODE_OFFSET; /* search main table */ return bin_search(keysymtab, ARRAY_SIZE(keysymtab) - 1, keysym); } xkb_keysym_t xkb_utf32_to_keysym(uint32_t ucs) { /* first check for Latin-1 characters (1:1 mapping) */ if ((ucs >= 0x0020 && ucs <= 0x007e) || (ucs >= 0x00a0 && ucs <= 0x00ff)) return ucs; /* special keysyms */ if ((ucs >= (XKB_KEY_BackSpace & 0x7f) && ucs <= (XKB_KEY_Clear & 0x7f)) || ucs == (XKB_KEY_Return & 0x7f) || ucs == (XKB_KEY_Escape & 0x7f)) return ucs | 0xff00; if (ucs == (XKB_KEY_Delete & 0x7f)) return XKB_KEY_Delete; /* * U+0000 NULL and invalid Unicode code points. * Surrogates are invalid in UTF-32. * See https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G28875 * for further details. */ if (unlikely(ucs == 0 || is_surrogate(ucs) || ucs > 0x10ffff)) return XKB_KEY_NoSymbol; /* search main table */ for (size_t i = 0; i < ARRAY_SIZE(keysymtab); i++) { /* Do not use deprecated keysyms */ if (keysymtab[i].ucs == ucs && !keysymtab[i].deprecated) return keysymtab[i].keysym; } /* Use direct encoding if everything else failed */ return ucs | XKB_KEYSYM_UNICODE_OFFSET; } /* * SPDX-SnippetBegin * Copyright © 2012 Intel Corporation * SPDX-License-Identifier: MIT * * Author: Rob Bradford */ int xkb_keysym_to_utf8(xkb_keysym_t keysym, char *buffer, size_t size) { uint32_t codepoint; /* Unicode code point takes up to 4 bytes in UTF-8, plus the * NULL-terminating byte. */ if (size < XKB_KEYSYM_UTF8_MAX_SIZE) return -1; codepoint = xkb_keysym_to_utf32(keysym); if (codepoint == NO_KEYSYM_UNICODE_CONVERSION) return 0; return utf32_to_utf8(codepoint, buffer); } /* SPDX-SnippetEnd */ xkbcommon-libxkbcommon-54ee7ac/src/keysym.c000066400000000000000000000351441510033435100211460ustar00rootroot00000000000000/* * For MIT-open-group: * Copyright 1985, 1987, 1990, 1998 The Open Group * * For MIT: * Copyright © 2009 Dan Nicholson * * SPDX-License-Identifier: MIT-open-group AND MIT */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon-keysyms.h" #include "xkbcommon/xkbcommon.h" #include "utils.h" #include "utils-numbers.h" #include "keysym.h" #include "ks_tables.h" static ssize_t find_keysym_index(xkb_keysym_t ks) { /* Lower bound: * keysym_to_name[0].keysym * == XKB_KEYSYM_MIN_EXPLICIT == XKB_KEYSYM_MIN == 0 * No need to check: xkb_keysym_t is unsigned. * * Upper bound: * keysym_to_name[ARRAY_SIZE(keysym_to_name) - 1].keysym * == XKB_KEYSYM_MAX_EXPLICIT <= XKB_KEYSYM_MAX */ if (ks > XKB_KEYSYM_MAX_EXPLICIT) return -1; ssize_t lo = 0, hi = ARRAY_SIZE(keysym_to_name) - 1; while (hi >= lo) { ssize_t mid = (lo + hi) / 2; if (ks > keysym_to_name[mid].keysym) { lo = mid + 1; } else if (ks < keysym_to_name[mid].keysym) { hi = mid - 1; } else { return mid; } } return -1; } #define get_name_by_index(index) (keysym_names + (index)) static inline const char * get_name(const struct name_keysym *entry) { return get_name_by_index(entry->offset); } /* Unnamed Unicode codepoint. */ static inline int get_unicode_name(xkb_keysym_t ks, char *buffer, size_t size) { return snprintf(buffer, size, "U%04"PRIX32, ks & UINT32_C(0xffffff)); } int xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size) { if (ks > XKB_KEYSYM_MAX) { snprintf(buffer, size, "Invalid"); return -1; } ssize_t index = find_keysym_index(ks); if (index != -1) return snprintf(buffer, size, "%s", get_name(&keysym_to_name[index])); /* * Unnamed Unicode codepoint. * • Keysyms in the range [XKB_KEYSYM_UNICODE_OFFSET, XKB_KEYSYM_UNICODE_MIN [ * do not use the Unicode notation for backward compatibility. * • Keysyms are not normalized: e.g. given a Unicode keysym, calling * `xkb_utf32_to_keysym` with the corresponding code point may return a * different keysym or fail (e.g. surrogates are invalid in UTF-32). */ if (ks >= XKB_KEYSYM_UNICODE_MIN && ks <= XKB_KEYSYM_UNICODE_MAX) return get_unicode_name(ks, buffer, size); /* Unnamed, non-Unicode, symbol (shouldn't generally happen). */ return snprintf(buffer, size, "0x%08x", ks); } bool xkb_keysym_is_assigned(xkb_keysym_t ks) { return (XKB_KEYSYM_UNICODE_MIN <= ks && ks <= XKB_KEYSYM_UNICODE_MAX) || find_keysym_index(ks) != -1; } int xkb_keysym_get_explicit_names(xkb_keysym_t ks, const char **buffer, size_t size) { if (ks > XKB_KEYSYM_MAX) return -1; const ssize_t index = find_keysym_index(ks); if (index < 0) return 0; const uint16_t canonical = keysym_to_name[index].offset; if (size > 0) buffer[0] = get_name(&keysym_to_name[index]); int count = 1; for (size_t pos = 0; pos < ARRAY_SIZE(name_to_keysym); pos++) { if (name_to_keysym[pos].keysym == ks && name_to_keysym[pos].offset != canonical) { if ((size_t) count < size) { buffer[count] = get_name(&name_to_keysym[pos]); } count++; } } return count; } struct xkb_keysym_iterator { bool explicit; /* If true, traverse only explicitly named keysyms */ int32_t index; /* Current index in `keysym_to_name` */ xkb_keysym_t keysym; /* Current keysym */ }; struct xkb_keysym_iterator* xkb_keysym_iterator_new(bool iterate_only_explicit_keysyms) { struct xkb_keysym_iterator* iter = calloc(1, sizeof(*iter)); iter->explicit = iterate_only_explicit_keysyms; iter->index = -1; iter->keysym = XKB_KEYSYM_UNICODE_MAX; return iter; } struct xkb_keysym_iterator* xkb_keysym_iterator_unref(struct xkb_keysym_iterator *iter) { /* * [NOTE] If we ever make this API public, add: * - an `refcnt` member, * - `xkb_keysym_iterator_ref()`, * - `assert(!iter || iter->refcnt > 0)`. */ if (iter) free(iter); return NULL; } xkb_keysym_t xkb_keysym_iterator_get_keysym(struct xkb_keysym_iterator *iter) { return iter->keysym; } bool xkb_keysym_iterator_is_explicitly_named(struct xkb_keysym_iterator *iter) { return iter->index >= 0 && iter->index < (int32_t)ARRAY_SIZE(keysym_to_name) && (iter->explicit || iter->keysym == keysym_to_name[iter->index].keysym); } int xkb_keysym_iterator_get_name(struct xkb_keysym_iterator *iter, char *buffer, size_t size) { if (iter->index < 0 || iter->index >= (int32_t)ARRAY_SIZE(keysym_to_name)) return -1; if (iter->explicit || iter->keysym == keysym_to_name[iter->index].keysym) return snprintf(buffer, size, "%s", get_name(&keysym_to_name[iter->index])); return get_unicode_name(iter->keysym, buffer, size); } /* Iterate over the *assigned* keysyms. * * Use: * * ```c * struct xkb_keysym_iterator *iter = xkb_keysym_iterator_new(true); * while (xkb_keysym_iterator_next(iter)) { * ... * } * iter = xkb_keysym_iterator_unref(iter); * ``` */ bool xkb_keysym_iterator_next(struct xkb_keysym_iterator *iter) { if (iter->index >= (int32_t)ARRAY_SIZE(keysym_to_name) - 1) return false; /* Next keysym */ if (iter->explicit || iter->keysym >= XKB_KEYSYM_UNICODE_MAX || keysym_to_name[iter->index + 1].keysym < XKB_KEYSYM_UNICODE_MIN) { /* Explicitly named keysyms only */ iter->keysym = keysym_to_name[++iter->index].keysym; assert(iter->explicit || iter->keysym <= XKB_KEYSYM_UNICODE_MIN || iter->keysym >= XKB_KEYSYM_UNICODE_MAX); } else { /* Unicode keysyms * NOTE: Unicode keysyms are within keysym_to_name keysyms range. */ if (iter->keysym >= keysym_to_name[iter->index].keysym) iter->index++; if (iter->keysym >= XKB_KEYSYM_UNICODE_MIN) { /* Continue Unicode keysyms */ iter->keysym++; } else { /* Start Unicode keysyms */ iter->keysym = XKB_KEYSYM_UNICODE_MIN; } } return true; } /* Parse the numeric part of a 0xXXXX and UXXXX keysym. */ static bool parse_keysym_hex(const char *s, uint32_t *out) { /* We expect a NULL-terminated string of length up to 8 */ const int count = parse_hex_to_uint32_t(s, 8, out); /* Check that some value was parsed and we reached the end of the string */ return (count > 0 && s[count] == '\0'); } xkb_keysym_t xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags) { const struct name_keysym *entry = NULL; char *tmp; uint32_t val; bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE); if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE) return XKB_KEY_NoSymbol; /* * We need to !icase case to be fast, for e.g. Compose file parsing. * So do it in a fast path. */ if (!icase) { size_t pos = keysym_name_perfect_hash(name); if (pos < ARRAY_SIZE(name_to_keysym)) { const char *s = get_name(&name_to_keysym[pos]); if (strcmp(name, s) == 0) return name_to_keysym[pos].keysym; } } /* * Find the correct keysym for case-insensitive match. * * The name_to_keysym table is sorted by istrcmp(). So the binary * search may return _any_ of all possible case-insensitive duplicates. The * duplicates are sorted so that the "best" case-insensitive match comes * last. So the code searches the entry and all next entries that match by * case-insensitive comparison and returns the "best" case-insensitive match. * * The "best" case-insensitive match is the lower-case keysym name. Most * keysyms names that only differ by letter-case are keysyms that are * available as “small” and “big” variants. For example: * * - Bicameral scripts: Lower-case and upper-case variants, * e.g. KEY_a and KEY_A. * - Non-bicameral scripts: e.g. KEY_kana_a and KEY_kana_A. * * There are some exceptions, e.g. `XF86Screensaver` and `XF86ScreenSaver`. */ else { int32_t lo = 0, hi = ARRAY_SIZE(name_to_keysym) - 1; while (hi >= lo) { int32_t mid = (lo + hi) / 2; int cmp = istrcmp(name, get_name(&name_to_keysym[mid])); if (cmp > 0) { lo = mid + 1; } else if (cmp < 0) { hi = mid - 1; } else { entry = &name_to_keysym[mid]; break; } } if (entry) { const struct name_keysym *last; last = name_to_keysym + ARRAY_SIZE(name_to_keysym) - 1; /* Keep going until we reach end of array * or non case-insensitve match */ while (entry < last && istrcmp(get_name(entry + 1), get_name(entry)) == 0) { entry++; } return entry->keysym; } } if (*name == 'U' || (icase && *name == 'u')) { /* Parse Unicode notation */ if (!parse_keysym_hex(&name[1], &val)) return XKB_KEY_NoSymbol; return (val > 0xff && val <= 0x10ffff) /* * No normalization. * * NOTE: It allows surrogates, as we are dealing with Unicode * *code points* here, not Unicode *scalars*. */ ? XKB_KEYSYM_UNICODE_OFFSET + val /* * Normalize ISO-8859-1 (Latin-1 + C0 and C1 control code) * * These code points require special processing to ensure * backward compatibility with legacy keysyms. */ : xkb_utf32_to_keysym(val); } else if (name[0] == '0' && (name[1] == 'x' || (icase && name[1] == 'X'))) { /* * Parse numeric hexadecimal notation without any normalization, in * in order to be consistent with the keymap files parsing. */ if (!parse_keysym_hex(&name[2], &val) || val > XKB_KEYSYM_MAX) return XKB_KEY_NoSymbol; return (xkb_keysym_t) val; } /* Stupid inconsistency between the headers and XKeysymDB: the former has * no separating underscore, while some XF86* syms in the latter did. * As a last ditch effort, try without. */ if (strncmp(name, "XF86_", 5) == 0 || (icase && istrncmp(name, "XF86_", 5) == 0)) { xkb_keysym_t ret; tmp = strdup(name); if (!tmp) return XKB_KEY_NoSymbol; memmove(&tmp[4], &tmp[5], strlen(name) - 5 + 1); ret = xkb_keysym_from_name(tmp, flags); free(tmp); return ret; } return XKB_KEY_NoSymbol; } /* * Check whether a keysym with code "keysym" and name "name" is deprecated. * • If the keysym is not deprecated itself and has no deprecated names, * then return false and write NULL in "reference_name". * • If there is a non-deprecated name for the given keysym, then write this * name in "reference_name", else write NULL and return true. * • If "name" is NULL, then returns false: the keysym itself is not deprecated. * • If "name" is not NULL, then check if "name" is deprecated. * * WARNING: this function is unsafe because it does not test if "name" is * actually a correct name for "keysym". It is intended to be used just after * keysym resolution. */ bool xkb_keysym_is_deprecated(xkb_keysym_t keysym, const char *name, const char **reference_name) { if (keysym > XKB_KEYSYM_MAX) { /* Invalid keysym */ *reference_name = NULL; return false; } /* [WARNING] We do not check that name, if defined, is a valid for keysym */ int32_t lo = 0, hi = ARRAY_SIZE(deprecated_keysyms) - 1; while (hi >= lo) { int32_t mid = (lo + hi) / 2; if (keysym > deprecated_keysyms[mid].keysym) { lo = mid + 1; } else if (keysym < deprecated_keysyms[mid].keysym) { hi = mid - 1; } else { /* Keysym have some deprecated names */ if (deprecated_keysyms[mid].offset == DEPRECATED_KEYSYM) { /* All names are deprecated */ *reference_name = NULL; return true; } else if (deprecated_keysyms[mid].offset == UNICODE_KEYSYM) { /* All names are deprecated, but Unicode notation is valid */ *reference_name = NULL; if (name == NULL) return false; if (name[0] != 'U') return true; /* Since the current function is internal, assume the name * corresponds to the keysym value and just check its syntax. */ const char *start = name + 1; while (is_xdigit(*start)) start++; return *start != '\0' && start > name + 1; } /* There is a reference name that is not deprecated */ *reference_name = get_name_by_index(deprecated_keysyms[mid].offset); if (name == NULL) /* No name to check: indicate not deprecated */ return false; if (deprecated_keysyms[mid].explicit_count) { /* Only some explicit names are deprecated */ uint8_t k = deprecated_keysyms[mid].explicit_index; const uint8_t k_max = deprecated_keysyms[mid].explicit_index + deprecated_keysyms[mid].explicit_count; /* Check every deprecated alias */ for (; k < k_max; k++) { const char *alias = get_name_by_index(explicit_deprecated_aliases[k]); if (strcmp(name, alias) == 0) return true; } return false; } else { /* All names but the reference one are deprecated */ return strcmp(name, *reference_name) != 0; } } } /* Keysym has no deprecated names */ *reference_name = NULL; return false; } bool xkb_keysym_is_keypad(xkb_keysym_t keysym) { return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal; } bool xkb_keysym_is_modifier(xkb_keysym_t keysym) { return (keysym >= XKB_KEY_Shift_L && keysym <= XKB_KEY_Hyper_R) || (keysym >= XKB_KEY_ISO_Lock && keysym <= XKB_KEY_ISO_Level5_Lock) || keysym == XKB_KEY_Mode_switch || keysym == XKB_KEY_Num_Lock; } xkbcommon-libxkbcommon-54ee7ac/src/keysym.h000066400000000000000000000115171510033435100211510ustar00rootroot00000000000000/* * NOTE: This file has been generated automatically by “scripts/update-keysyms-derived-headers.py”. * Do not edit manually! */ /* * For MIT-open-group: * Copyright 1985, 1987, 1990, 1998 The Open Group * * For MIT: * Copyright © 2009 Dan Nicholson * * SPDX-License-Identifier: MIT-open-group AND MIT */ #pragma once #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "utils.h" /* * NOTE: this is not defined in xkbcommon.h, because if we did, it may add * overhead for library user: when handling keysyms they would also need to * check min keysym when previously there was no reason to. */ /** Minimum keysym value */ #define XKB_KEYSYM_MIN 0x00000000 /** Minimum keysym value assigned */ #define XKB_KEYSYM_MIN_ASSIGNED ((xkb_keysym_t)0x00000000) /** Maximum keysym value assigned */ #define XKB_KEYSYM_MAX_ASSIGNED 0x1008ffb8 /** Minimum keysym value with explicit name */ #define XKB_KEYSYM_MIN_EXPLICIT 0x00000000 /** Maximum keysym value with explicit name */ #define XKB_KEYSYM_MAX_EXPLICIT 0x1008ffb8 /** Count of keysym value with explicit name */ #define XKB_KEYSYM_COUNT_EXPLICIT 2493 /** Offset to use when converting a Unicode code point to a keysym */ #define XKB_KEYSYM_UNICODE_OFFSET 0x01000000 /** Minimum Unicode keysym. NOTE: code points in 0..0xff cannot be converted. */ #define XKB_KEYSYM_UNICODE_MIN 0x01000100 /** Minimum Unicode surrogate keysym */ #define XKB_KEYSYM_UNICODE_SURROGATE_MIN 0x0100d800 /** Maximum Unicode surrogate keysym */ #define XKB_KEYSYM_UNICODE_SURROGATE_MAX 0x0100dfff /** Maximum Unicode keysym, corresponding to the maximum Unicode code point */ #define XKB_KEYSYM_UNICODE_MAX 0x0110ffff /** Unicode version used for case mappings */ #define XKB_KEYSYM_UNICODE_VERSION { 17, 0, 0, 0 } /** Maximum keysym canonical name length, plus terminating NULL byte */ #define XKB_KEYSYM_NAME_MAX_SIZE 28 /** Longest keysym canonical name */ #define XKB_KEYSYM_LONGEST_CANONICAL_NAME ISO_Discontinuous_Underline /** Longest keysym name */ #define XKB_KEYSYM_LONGEST_NAME ISO_Discontinuous_Underline /** Maximum of distinct explicit names for a keysym */ #define XKB_KEYSYM_EXPLICIT_ALIASES_MAX 9 /** Maximum bytes to encode the Unicode representation of a keysym in UTF-8: * 4 bytes + NULL-terminating byte */ #define XKB_KEYSYM_UTF8_MAX_SIZE 5 XKB_EXPORT_PRIVATE bool xkb_keysym_is_assigned(xkb_keysym_t ks); XKB_EXPORT_PRIVATE int xkb_keysym_get_explicit_names(xkb_keysym_t ks, const char **buffer, size_t size); struct xkb_keysym_iterator; XKB_EXPORT_PRIVATE struct xkb_keysym_iterator* xkb_keysym_iterator_new(bool explicit); XKB_EXPORT_PRIVATE struct xkb_keysym_iterator* xkb_keysym_iterator_unref(struct xkb_keysym_iterator *iter); XKB_EXPORT_PRIVATE bool xkb_keysym_iterator_next(struct xkb_keysym_iterator *iter); XKB_EXPORT_PRIVATE xkb_keysym_t xkb_keysym_iterator_get_keysym(struct xkb_keysym_iterator *iter); XKB_EXPORT_PRIVATE int xkb_keysym_iterator_get_name(struct xkb_keysym_iterator *iter, char *buffer, size_t size); XKB_EXPORT_PRIVATE bool xkb_keysym_iterator_is_explicitly_named(struct xkb_keysym_iterator *iter); XKB_EXPORT_PRIVATE bool xkb_keysym_is_deprecated(xkb_keysym_t keysym, const char *name, const char **reference_name); #define XKB_MIN_VERBOSITY_DEPRECATED_KEYSYM 2 #define check_deprecated_keysyms(log_func, log_param, ctx, keysym, name, token, format, end) \ if (unlikely((ctx)->log_verbosity >= XKB_MIN_VERBOSITY_DEPRECATED_KEYSYM)) { \ const char *ref_name = NULL; \ if (xkb_keysym_is_deprecated(keysym, name, &ref_name)) { \ if (ref_name == NULL) \ log_func(log_param, XKB_WARNING_DEPRECATED_KEYSYM, \ "deprecated keysym \"" format "\"." end, token); \ else \ log_func(log_param, XKB_WARNING_DEPRECATED_KEYSYM_NAME, \ "deprecated keysym name \"" format "\"; " \ "please use \"%s\" instead." end, \ token, ref_name); \ } \ } XKB_EXPORT_PRIVATE bool xkb_keysym_is_lower(xkb_keysym_t keysym); XKB_EXPORT_PRIVATE bool xkb_keysym_is_upper_or_title(xkb_keysym_t keysym); XKB_EXPORT_PRIVATE bool xkb_keysym_is_keypad(xkb_keysym_t keysym); XKB_EXPORT_PRIVATE bool xkb_keysym_is_modifier(xkb_keysym_t keysym); xkbcommon-libxkbcommon-54ee7ac/src/keysym.h.jinja000066400000000000000000000120111510033435100222310ustar00rootroot00000000000000/* * NOTE: This file has been generated automatically by “{{script}}”. * Do not edit manually! */ /* * For MIT-open-group: * Copyright 1985, 1987, 1990, 1998 The Open Group * * For MIT: * Copyright © 2009 Dan Nicholson * * SPDX-License-Identifier: MIT-open-group AND MIT */ #pragma once #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "utils.h" /* * NOTE: this is not defined in xkbcommon.h, because if we did, it may add * overhead for library user: when handling keysyms they would also need to * check min keysym when previously there was no reason to. */ /** Minimum keysym value */ #define XKB_KEYSYM_MIN 0x00000000 /** Minimum keysym value assigned */ #define XKB_KEYSYM_MIN_ASSIGNED ((xkb_keysym_t){{ XKB_KEYSYM_MIN_ASSIGNED | keysym }}) /** Maximum keysym value assigned */ #define XKB_KEYSYM_MAX_ASSIGNED {{ XKB_KEYSYM_MAX_ASSIGNED | keysym }} /** Minimum keysym value with explicit name */ #define XKB_KEYSYM_MIN_EXPLICIT {{ XKB_KEYSYM_MIN_EXPLICIT | keysym }} /** Maximum keysym value with explicit name */ #define XKB_KEYSYM_MAX_EXPLICIT {{ XKB_KEYSYM_MAX_EXPLICIT | keysym }} /** Count of keysym value with explicit name */ #define XKB_KEYSYM_COUNT_EXPLICIT {{ XKB_KEYSYM_COUNT_EXPLICIT }} /** Offset to use when converting a Unicode code point to a keysym */ #define XKB_KEYSYM_UNICODE_OFFSET 0x01000000 /** Minimum Unicode keysym. NOTE: code points in 0..0xff cannot be converted. */ #define XKB_KEYSYM_UNICODE_MIN 0x01000100 /** Minimum Unicode surrogate keysym */ #define XKB_KEYSYM_UNICODE_SURROGATE_MIN 0x0100d800 /** Maximum Unicode surrogate keysym */ #define XKB_KEYSYM_UNICODE_SURROGATE_MAX 0x0100dfff /** Maximum Unicode keysym, corresponding to the maximum Unicode code point */ #define XKB_KEYSYM_UNICODE_MAX 0x0110ffff /** Unicode version used for case mappings */ #define XKB_KEYSYM_UNICODE_VERSION { 17, 0, 0, 0 } /** Maximum keysym canonical name length, plus terminating NULL byte */ #define XKB_KEYSYM_NAME_MAX_SIZE {{ XKB_KEYSYM_NAME_MAX_SIZE }} /** Longest keysym canonical name */ #define XKB_KEYSYM_LONGEST_CANONICAL_NAME {{ XKB_KEYSYM_LONGEST_CANONICAL_NAME }} /** Longest keysym name */ #define XKB_KEYSYM_LONGEST_NAME {{ XKB_KEYSYM_LONGEST_NAME }} /** Maximum of distinct explicit names for a keysym */ #define XKB_KEYSYM_EXPLICIT_ALIASES_MAX {{ XKB_KEYSYM_EXPLICIT_ALIASES_MAX }} /** Maximum bytes to encode the Unicode representation of a keysym in UTF-8: * 4 bytes + NULL-terminating byte */ #define XKB_KEYSYM_UTF8_MAX_SIZE 5 XKB_EXPORT_PRIVATE bool xkb_keysym_is_assigned(xkb_keysym_t ks); XKB_EXPORT_PRIVATE int xkb_keysym_get_explicit_names(xkb_keysym_t ks, const char **buffer, size_t size); struct xkb_keysym_iterator; XKB_EXPORT_PRIVATE struct xkb_keysym_iterator* xkb_keysym_iterator_new(bool explicit); XKB_EXPORT_PRIVATE struct xkb_keysym_iterator* xkb_keysym_iterator_unref(struct xkb_keysym_iterator *iter); XKB_EXPORT_PRIVATE bool xkb_keysym_iterator_next(struct xkb_keysym_iterator *iter); XKB_EXPORT_PRIVATE xkb_keysym_t xkb_keysym_iterator_get_keysym(struct xkb_keysym_iterator *iter); XKB_EXPORT_PRIVATE int xkb_keysym_iterator_get_name(struct xkb_keysym_iterator *iter, char *buffer, size_t size); XKB_EXPORT_PRIVATE bool xkb_keysym_iterator_is_explicitly_named(struct xkb_keysym_iterator *iter); XKB_EXPORT_PRIVATE bool xkb_keysym_is_deprecated(xkb_keysym_t keysym, const char *name, const char **reference_name); #define XKB_MIN_VERBOSITY_DEPRECATED_KEYSYM 2 #define check_deprecated_keysyms(log_func, log_param, ctx, keysym, name, token, format, end) \ if (unlikely((ctx)->log_verbosity >= XKB_MIN_VERBOSITY_DEPRECATED_KEYSYM)) { \ const char *ref_name = NULL; \ if (xkb_keysym_is_deprecated(keysym, name, &ref_name)) { \ if (ref_name == NULL) \ log_func(log_param, XKB_WARNING_DEPRECATED_KEYSYM, \ "deprecated keysym \"" format "\"." end, token); \ else \ log_func(log_param, XKB_WARNING_DEPRECATED_KEYSYM_NAME, \ "deprecated keysym name \"" format "\"; " \ "please use \"%s\" instead." end, \ token, ref_name); \ } \ } XKB_EXPORT_PRIVATE bool xkb_keysym_is_lower(xkb_keysym_t keysym); XKB_EXPORT_PRIVATE bool xkb_keysym_is_upper_or_title(xkb_keysym_t keysym); XKB_EXPORT_PRIVATE bool xkb_keysym_is_keypad(xkb_keysym_t keysym); XKB_EXPORT_PRIVATE bool xkb_keysym_is_modifier(xkb_keysym_t keysym); xkbcommon-libxkbcommon-54ee7ac/src/ks_tables.h000066400000000000000000011705331510033435100216040ustar00rootroot00000000000000 /** * This file comes from libxkbcommon and was generated by update-keysyms-names-handling.py * You can always fetch the latest version from: * https://raw.github.com/xkbcommon/libxkbcommon/master/src/ks_tables.h */ #pragma once #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Woverlength-strings" #endif static const char *keysym_names = "0\0" "1\0" "2\0" "3\0" "3270_AltCursor\0" "3270_Attn\0" "3270_BackTab\0" "3270_ChangeScreen\0" "3270_Copy\0" "3270_CursorBlink\0" "3270_CursorSelect\0" "3270_DeleteWord\0" "3270_Duplicate\0" "3270_Enter\0" "3270_EraseEOF\0" "3270_EraseInput\0" "3270_ExSelect\0" "3270_FieldMark\0" "3270_Ident\0" "3270_Jump\0" "3270_KeyClick\0" "3270_Left2\0" "3270_PA1\0" "3270_PA2\0" "3270_PA3\0" "3270_Play\0" "3270_PrintScreen\0" "3270_Quit\0" "3270_Record\0" "3270_Reset\0" "3270_Right2\0" "3270_Rule\0" "3270_Setup\0" "3270_Test\0" "4\0" "5\0" "6\0" "7\0" "8\0" "9\0" "A\0" "a\0" "Aacute\0" "aacute\0" "Abelowdot\0" "abelowdot\0" "abovedot\0" "Abreve\0" "abreve\0" "Abreveacute\0" "abreveacute\0" "Abrevebelowdot\0" "abrevebelowdot\0" "Abrevegrave\0" "abrevegrave\0" "Abrevehook\0" "abrevehook\0" "Abrevetilde\0" "abrevetilde\0" "AccessX_Enable\0" "AccessX_Feedback_Enable\0" "Acircumflex\0" "acircumflex\0" "Acircumflexacute\0" "acircumflexacute\0" "Acircumflexbelowdot\0" "acircumflexbelowdot\0" "Acircumflexgrave\0" "acircumflexgrave\0" "Acircumflexhook\0" "acircumflexhook\0" "Acircumflextilde\0" "acircumflextilde\0" "acute\0" "Adiaeresis\0" "adiaeresis\0" "AE\0" "ae\0" "Agrave\0" "agrave\0" "Ahook\0" "ahook\0" "Alt_L\0" "Alt_R\0" "Amacron\0" "amacron\0" "ampersand\0" "Aogonek\0" "aogonek\0" "apostrophe\0" "approxeq\0" "approximate\0" "Arabic_0\0" "Arabic_1\0" "Arabic_2\0" "Arabic_3\0" "Arabic_4\0" "Arabic_5\0" "Arabic_6\0" "Arabic_7\0" "Arabic_8\0" "Arabic_9\0" "Arabic_ain\0" "Arabic_alef\0" "Arabic_alefmaksura\0" "Arabic_beh\0" "Arabic_comma\0" "Arabic_dad\0" "Arabic_dal\0" "Arabic_damma\0" "Arabic_dammatan\0" "Arabic_ddal\0" "Arabic_farsi_yeh\0" "Arabic_fatha\0" "Arabic_fathatan\0" "Arabic_feh\0" "Arabic_fullstop\0" "Arabic_gaf\0" "Arabic_ghain\0" "Arabic_ha\0" "Arabic_hah\0" "Arabic_hamza\0" "Arabic_hamza_above\0" "Arabic_hamza_below\0" "Arabic_hamzaonalef\0" "Arabic_hamzaonwaw\0" "Arabic_hamzaonyeh\0" "Arabic_hamzaunderalef\0" "Arabic_heh\0" "Arabic_heh_doachashmee\0" "Arabic_heh_goal\0" "Arabic_jeem\0" "Arabic_jeh\0" "Arabic_kaf\0" "Arabic_kasra\0" "Arabic_kasratan\0" "Arabic_keheh\0" "Arabic_khah\0" "Arabic_lam\0" "Arabic_madda_above\0" "Arabic_maddaonalef\0" "Arabic_meem\0" "Arabic_noon\0" "Arabic_noon_ghunna\0" "Arabic_peh\0" "Arabic_percent\0" "Arabic_qaf\0" "Arabic_question_mark\0" "Arabic_ra\0" "Arabic_rreh\0" "Arabic_sad\0" "Arabic_seen\0" "Arabic_semicolon\0" "Arabic_shadda\0" "Arabic_sheen\0" "Arabic_sukun\0" "Arabic_superscript_alef\0" "Arabic_switch\0" "Arabic_tah\0" "Arabic_tatweel\0" "Arabic_tcheh\0" "Arabic_teh\0" "Arabic_tehmarbuta\0" "Arabic_thal\0" "Arabic_theh\0" "Arabic_tteh\0" "Arabic_veh\0" "Arabic_waw\0" "Arabic_yeh\0" "Arabic_yeh_baree\0" "Arabic_zah\0" "Arabic_zain\0" "Aring\0" "aring\0" "Armenian_accent\0" "Armenian_amanak\0" "Armenian_apostrophe\0" "Armenian_AT\0" "Armenian_at\0" "Armenian_AYB\0" "Armenian_ayb\0" "Armenian_BEN\0" "Armenian_ben\0" "Armenian_but\0" "Armenian_CHA\0" "Armenian_cha\0" "Armenian_DA\0" "Armenian_da\0" "Armenian_DZA\0" "Armenian_dza\0" "Armenian_E\0" "Armenian_e\0" "Armenian_exclam\0" "Armenian_FE\0" "Armenian_fe\0" "Armenian_full_stop\0" "Armenian_GHAT\0" "Armenian_ghat\0" "Armenian_GIM\0" "Armenian_gim\0" "Armenian_HI\0" "Armenian_hi\0" "Armenian_HO\0" "Armenian_ho\0" "Armenian_hyphen\0" "Armenian_INI\0" "Armenian_ini\0" "Armenian_JE\0" "Armenian_je\0" "Armenian_KE\0" "Armenian_ke\0" "Armenian_KEN\0" "Armenian_ken\0" "Armenian_KHE\0" "Armenian_khe\0" "Armenian_ligature_ew\0" "Armenian_LYUN\0" "Armenian_lyun\0" "Armenian_MEN\0" "Armenian_men\0" "Armenian_NU\0" "Armenian_nu\0" "Armenian_O\0" "Armenian_o\0" "Armenian_paruyk\0" "Armenian_PE\0" "Armenian_pe\0" "Armenian_PYUR\0" "Armenian_pyur\0" "Armenian_question\0" "Armenian_RA\0" "Armenian_ra\0" "Armenian_RE\0" "Armenian_re\0" "Armenian_SE\0" "Armenian_se\0" "Armenian_separation_mark\0" "Armenian_SHA\0" "Armenian_sha\0" "Armenian_shesht\0" "Armenian_TCHE\0" "Armenian_tche\0" "Armenian_TO\0" "Armenian_to\0" "Armenian_TSA\0" "Armenian_tsa\0" "Armenian_TSO\0" "Armenian_tso\0" "Armenian_TYUN\0" "Armenian_tyun\0" "Armenian_verjaket\0" "Armenian_VEV\0" "Armenian_vev\0" "Armenian_VO\0" "Armenian_vo\0" "Armenian_VYUN\0" "Armenian_vyun\0" "Armenian_YECH\0" "Armenian_yech\0" "Armenian_yentamna\0" "Armenian_ZA\0" "Armenian_za\0" "Armenian_ZHE\0" "Armenian_zhe\0" "asciicircum\0" "asciitilde\0" "asterisk\0" "at\0" "Atilde\0" "atilde\0" "AudibleBell_Enable\0" "B\0" "b\0" "Babovedot\0" "babovedot\0" "backslash\0" "BackSpace\0" "BackTab\0" "ballotcross\0" "bar\0" "because\0" "Begin\0" "blank\0" "block\0" "botintegral\0" "botleftparens\0" "botleftsqbracket\0" "botleftsummation\0" "botrightparens\0" "botrightsqbracket\0" "botrightsummation\0" "bott\0" "botvertsummationconnector\0" "BounceKeys_Enable\0" "braceleft\0" "braceright\0" "bracketleft\0" "bracketright\0" "braille_blank\0" "braille_dot_1\0" "braille_dot_10\0" "braille_dot_2\0" "braille_dot_3\0" "braille_dot_4\0" "braille_dot_5\0" "braille_dot_6\0" "braille_dot_7\0" "braille_dot_8\0" "braille_dot_9\0" "braille_dots_1\0" "braille_dots_12\0" "braille_dots_123\0" "braille_dots_1234\0" "braille_dots_12345\0" "braille_dots_123456\0" "braille_dots_1234567\0" "braille_dots_12345678\0" "braille_dots_1234568\0" "braille_dots_123457\0" "braille_dots_1234578\0" "braille_dots_123458\0" "braille_dots_12346\0" "braille_dots_123467\0" "braille_dots_1234678\0" "braille_dots_123468\0" "braille_dots_12347\0" "braille_dots_123478\0" "braille_dots_12348\0" "braille_dots_1235\0" "braille_dots_12356\0" "braille_dots_123567\0" "braille_dots_1235678\0" "braille_dots_123568\0" "braille_dots_12357\0" "braille_dots_123578\0" "braille_dots_12358\0" "braille_dots_1236\0" "braille_dots_12367\0" "braille_dots_123678\0" "braille_dots_12368\0" "braille_dots_1237\0" "braille_dots_12378\0" "braille_dots_1238\0" "braille_dots_124\0" "braille_dots_1245\0" "braille_dots_12456\0" "braille_dots_124567\0" "braille_dots_1245678\0" "braille_dots_124568\0" "braille_dots_12457\0" "braille_dots_124578\0" "braille_dots_12458\0" "braille_dots_1246\0" "braille_dots_12467\0" "braille_dots_124678\0" "braille_dots_12468\0" "braille_dots_1247\0" "braille_dots_12478\0" "braille_dots_1248\0" "braille_dots_125\0" "braille_dots_1256\0" "braille_dots_12567\0" "braille_dots_125678\0" "braille_dots_12568\0" "braille_dots_1257\0" "braille_dots_12578\0" "braille_dots_1258\0" "braille_dots_126\0" "braille_dots_1267\0" "braille_dots_12678\0" "braille_dots_1268\0" "braille_dots_127\0" "braille_dots_1278\0" "braille_dots_128\0" "braille_dots_13\0" "braille_dots_134\0" "braille_dots_1345\0" "braille_dots_13456\0" "braille_dots_134567\0" "braille_dots_1345678\0" "braille_dots_134568\0" "braille_dots_13457\0" "braille_dots_134578\0" "braille_dots_13458\0" "braille_dots_1346\0" "braille_dots_13467\0" "braille_dots_134678\0" "braille_dots_13468\0" "braille_dots_1347\0" "braille_dots_13478\0" "braille_dots_1348\0" "braille_dots_135\0" "braille_dots_1356\0" "braille_dots_13567\0" "braille_dots_135678\0" "braille_dots_13568\0" "braille_dots_1357\0" "braille_dots_13578\0" "braille_dots_1358\0" "braille_dots_136\0" "braille_dots_1367\0" "braille_dots_13678\0" "braille_dots_1368\0" "braille_dots_137\0" "braille_dots_1378\0" "braille_dots_138\0" "braille_dots_14\0" "braille_dots_145\0" "braille_dots_1456\0" "braille_dots_14567\0" "braille_dots_145678\0" "braille_dots_14568\0" "braille_dots_1457\0" "braille_dots_14578\0" "braille_dots_1458\0" "braille_dots_146\0" "braille_dots_1467\0" "braille_dots_14678\0" "braille_dots_1468\0" "braille_dots_147\0" "braille_dots_1478\0" "braille_dots_148\0" "braille_dots_15\0" "braille_dots_156\0" "braille_dots_1567\0" "braille_dots_15678\0" "braille_dots_1568\0" "braille_dots_157\0" "braille_dots_1578\0" "braille_dots_158\0" "braille_dots_16\0" "braille_dots_167\0" "braille_dots_1678\0" "braille_dots_168\0" "braille_dots_17\0" "braille_dots_178\0" "braille_dots_18\0" "braille_dots_2\0" "braille_dots_23\0" "braille_dots_234\0" "braille_dots_2345\0" "braille_dots_23456\0" "braille_dots_234567\0" "braille_dots_2345678\0" "braille_dots_234568\0" "braille_dots_23457\0" "braille_dots_234578\0" "braille_dots_23458\0" "braille_dots_2346\0" "braille_dots_23467\0" "braille_dots_234678\0" "braille_dots_23468\0" "braille_dots_2347\0" "braille_dots_23478\0" "braille_dots_2348\0" "braille_dots_235\0" "braille_dots_2356\0" "braille_dots_23567\0" "braille_dots_235678\0" "braille_dots_23568\0" "braille_dots_2357\0" "braille_dots_23578\0" "braille_dots_2358\0" "braille_dots_236\0" "braille_dots_2367\0" "braille_dots_23678\0" "braille_dots_2368\0" "braille_dots_237\0" "braille_dots_2378\0" "braille_dots_238\0" "braille_dots_24\0" "braille_dots_245\0" "braille_dots_2456\0" "braille_dots_24567\0" "braille_dots_245678\0" "braille_dots_24568\0" "braille_dots_2457\0" "braille_dots_24578\0" "braille_dots_2458\0" "braille_dots_246\0" "braille_dots_2467\0" "braille_dots_24678\0" "braille_dots_2468\0" "braille_dots_247\0" "braille_dots_2478\0" "braille_dots_248\0" "braille_dots_25\0" "braille_dots_256\0" "braille_dots_2567\0" "braille_dots_25678\0" "braille_dots_2568\0" "braille_dots_257\0" "braille_dots_2578\0" "braille_dots_258\0" "braille_dots_26\0" "braille_dots_267\0" "braille_dots_2678\0" "braille_dots_268\0" "braille_dots_27\0" "braille_dots_278\0" "braille_dots_28\0" "braille_dots_3\0" "braille_dots_34\0" "braille_dots_345\0" "braille_dots_3456\0" "braille_dots_34567\0" "braille_dots_345678\0" "braille_dots_34568\0" "braille_dots_3457\0" "braille_dots_34578\0" "braille_dots_3458\0" "braille_dots_346\0" "braille_dots_3467\0" "braille_dots_34678\0" "braille_dots_3468\0" "braille_dots_347\0" "braille_dots_3478\0" "braille_dots_348\0" "braille_dots_35\0" "braille_dots_356\0" "braille_dots_3567\0" "braille_dots_35678\0" "braille_dots_3568\0" "braille_dots_357\0" "braille_dots_3578\0" "braille_dots_358\0" "braille_dots_36\0" "braille_dots_367\0" "braille_dots_3678\0" "braille_dots_368\0" "braille_dots_37\0" "braille_dots_378\0" "braille_dots_38\0" "braille_dots_4\0" "braille_dots_45\0" "braille_dots_456\0" "braille_dots_4567\0" "braille_dots_45678\0" "braille_dots_4568\0" "braille_dots_457\0" "braille_dots_4578\0" "braille_dots_458\0" "braille_dots_46\0" "braille_dots_467\0" "braille_dots_4678\0" "braille_dots_468\0" "braille_dots_47\0" "braille_dots_478\0" "braille_dots_48\0" "braille_dots_5\0" "braille_dots_56\0" "braille_dots_567\0" "braille_dots_5678\0" "braille_dots_568\0" "braille_dots_57\0" "braille_dots_578\0" "braille_dots_58\0" "braille_dots_6\0" "braille_dots_67\0" "braille_dots_678\0" "braille_dots_68\0" "braille_dots_7\0" "braille_dots_78\0" "braille_dots_8\0" "Break\0" "breve\0" "brokenbar\0" "Byelorussian_SHORTU\0" "Byelorussian_shortu\0" "C\0" "c\0" "C_H\0" "C_h\0" "c_h\0" "Cabovedot\0" "cabovedot\0" "Cacute\0" "cacute\0" "Cancel\0" "Caps_Lock\0" "careof\0" "caret\0" "caron\0" "Ccaron\0" "ccaron\0" "Ccedilla\0" "ccedilla\0" "Ccircumflex\0" "ccircumflex\0" "cedilla\0" "cent\0" "CH\0" "Ch\0" "ch\0" "checkerboard\0" "checkmark\0" "circle\0" "Clear\0" "ClearLine\0" "club\0" "Codeinput\0" "colon\0" "ColonSign\0" "combining_acute\0" "combining_belowdot\0" "combining_grave\0" "combining_hook\0" "combining_tilde\0" "comma\0" "containsas\0" "Control_L\0" "Control_R\0" "copyright\0" "cr\0" "crossinglines\0" "CruzeiroSign\0" "cuberoot\0" "currency\0" "cursor\0" "Cyrillic_A\0" "Cyrillic_a\0" "Cyrillic_BE\0" "Cyrillic_be\0" "Cyrillic_CHE\0" "Cyrillic_che\0" "Cyrillic_CHE_descender\0" "Cyrillic_che_descender\0" "Cyrillic_CHE_vertstroke\0" "Cyrillic_che_vertstroke\0" "Cyrillic_DE\0" "Cyrillic_de\0" "Cyrillic_DZHE\0" "Cyrillic_dzhe\0" "Cyrillic_E\0" "Cyrillic_e\0" "Cyrillic_EF\0" "Cyrillic_ef\0" "Cyrillic_EL\0" "Cyrillic_el\0" "Cyrillic_EM\0" "Cyrillic_em\0" "Cyrillic_EN\0" "Cyrillic_en\0" "Cyrillic_EN_descender\0" "Cyrillic_en_descender\0" "Cyrillic_ER\0" "Cyrillic_er\0" "Cyrillic_ES\0" "Cyrillic_es\0" "Cyrillic_GHE\0" "Cyrillic_ghe\0" "Cyrillic_GHE_bar\0" "Cyrillic_ghe_bar\0" "Cyrillic_HA\0" "Cyrillic_ha\0" "Cyrillic_HA_descender\0" "Cyrillic_ha_descender\0" "Cyrillic_HARDSIGN\0" "Cyrillic_hardsign\0" "Cyrillic_I\0" "Cyrillic_i\0" "Cyrillic_I_macron\0" "Cyrillic_i_macron\0" "Cyrillic_IE\0" "Cyrillic_ie\0" "Cyrillic_IO\0" "Cyrillic_io\0" "Cyrillic_JE\0" "Cyrillic_je\0" "Cyrillic_KA\0" "Cyrillic_ka\0" "Cyrillic_KA_descender\0" "Cyrillic_ka_descender\0" "Cyrillic_KA_vertstroke\0" "Cyrillic_ka_vertstroke\0" "Cyrillic_LJE\0" "Cyrillic_lje\0" "Cyrillic_NJE\0" "Cyrillic_nje\0" "Cyrillic_O\0" "Cyrillic_o\0" "Cyrillic_O_bar\0" "Cyrillic_o_bar\0" "Cyrillic_PE\0" "Cyrillic_pe\0" "Cyrillic_SCHWA\0" "Cyrillic_schwa\0" "Cyrillic_SHA\0" "Cyrillic_sha\0" "Cyrillic_SHCHA\0" "Cyrillic_shcha\0" "Cyrillic_SHHA\0" "Cyrillic_shha\0" "Cyrillic_SHORTI\0" "Cyrillic_shorti\0" "Cyrillic_SOFTSIGN\0" "Cyrillic_softsign\0" "Cyrillic_TE\0" "Cyrillic_te\0" "Cyrillic_TSE\0" "Cyrillic_tse\0" "Cyrillic_U\0" "Cyrillic_u\0" "Cyrillic_U_macron\0" "Cyrillic_u_macron\0" "Cyrillic_U_straight\0" "Cyrillic_u_straight\0" "Cyrillic_U_straight_bar\0" "Cyrillic_u_straight_bar\0" "Cyrillic_VE\0" "Cyrillic_ve\0" "Cyrillic_YA\0" "Cyrillic_ya\0" "Cyrillic_YERU\0" "Cyrillic_yeru\0" "Cyrillic_YU\0" "Cyrillic_yu\0" "Cyrillic_ZE\0" "Cyrillic_ze\0" "Cyrillic_ZHE\0" "Cyrillic_zhe\0" "Cyrillic_ZHE_descender\0" "Cyrillic_zhe_descender\0" "D\0" "d\0" "Dabovedot\0" "dabovedot\0" "Dacute_accent\0" "dagger\0" "Dcaron\0" "dcaron\0" "Dcedilla_accent\0" "Dcircumflex_accent\0" "Ddiaeresis\0" "dead_A\0" "dead_a\0" "dead_abovecomma\0" "dead_abovedot\0" "dead_abovereversedcomma\0" "dead_abovering\0" "dead_aboveverticalline\0" "dead_acute\0" "dead_belowbreve\0" "dead_belowcircumflex\0" "dead_belowcomma\0" "dead_belowdiaeresis\0" "dead_belowdot\0" "dead_belowmacron\0" "dead_belowring\0" "dead_belowtilde\0" "dead_belowverticalline\0" "dead_breve\0" "dead_capital_schwa\0" "dead_caron\0" "dead_cedilla\0" "dead_circumflex\0" "dead_currency\0" "dead_dasia\0" "dead_diaeresis\0" "dead_doubleacute\0" "dead_doublegrave\0" "dead_E\0" "dead_e\0" "dead_grave\0" "dead_greek\0" "dead_hamza\0" "dead_hook\0" "dead_horn\0" "dead_I\0" "dead_i\0" "dead_invertedbreve\0" "dead_iota\0" "dead_longsolidusoverlay\0" "dead_lowline\0" "dead_macron\0" "dead_O\0" "dead_o\0" "dead_ogonek\0" "dead_perispomeni\0" "dead_psili\0" "dead_SCHWA\0" "dead_schwa\0" "dead_semivoiced_sound\0" "dead_small_schwa\0" "dead_stroke\0" "dead_tilde\0" "dead_U\0" "dead_u\0" "dead_voiced_sound\0" "decimalpoint\0" "degree\0" "Delete\0" "DeleteChar\0" "DeleteLine\0" "Dgrave_accent\0" "diaeresis\0" "diamond\0" "digitspace\0" "dintegral\0" "division\0" "dollar\0" "DongSign\0" "doubbaselinedot\0" "doubleacute\0" "doubledagger\0" "doublelowquotemark\0" "Down\0" "downarrow\0" "downcaret\0" "downshoe\0" "downstile\0" "downtack\0" "DRemove\0" "Dring_accent\0" "Dstroke\0" "dstroke\0" "Dtilde\0" "E\0" "e\0" "Eabovedot\0" "eabovedot\0" "Eacute\0" "eacute\0" "Ebelowdot\0" "ebelowdot\0" "Ecaron\0" "ecaron\0" "Ecircumflex\0" "ecircumflex\0" "Ecircumflexacute\0" "ecircumflexacute\0" "Ecircumflexbelowdot\0" "ecircumflexbelowdot\0" "Ecircumflexgrave\0" "ecircumflexgrave\0" "Ecircumflexhook\0" "ecircumflexhook\0" "Ecircumflextilde\0" "ecircumflextilde\0" "EcuSign\0" "Ediaeresis\0" "ediaeresis\0" "Egrave\0" "egrave\0" "Ehook\0" "ehook\0" "eightsubscript\0" "eightsuperior\0" "Eisu_Shift\0" "Eisu_toggle\0" "elementof\0" "ellipsis\0" "em3space\0" "em4space\0" "Emacron\0" "emacron\0" "emdash\0" "emfilledcircle\0" "emfilledrect\0" "emopencircle\0" "emopenrectangle\0" "emptyset\0" "emspace\0" "End\0" "endash\0" "enfilledcircbullet\0" "enfilledsqbullet\0" "ENG\0" "eng\0" "enopencircbullet\0" "enopensquarebullet\0" "enspace\0" "Eogonek\0" "eogonek\0" "equal\0" "Escape\0" "ETH\0" "Eth\0" "eth\0" "Etilde\0" "etilde\0" "EuroSign\0" "exclam\0" "exclamdown\0" "Execute\0" "Ext16bit_L\0" "Ext16bit_R\0" "EZH\0" "ezh\0" "F\0" "f\0" "F1\0" "F10\0" "F11\0" "F12\0" "F13\0" "F14\0" "F15\0" "F16\0" "F17\0" "F18\0" "F19\0" "F2\0" "F20\0" "F21\0" "F22\0" "F23\0" "F24\0" "F25\0" "F26\0" "F27\0" "F28\0" "F29\0" "F3\0" "F30\0" "F31\0" "F32\0" "F33\0" "F34\0" "F35\0" "F4\0" "F5\0" "F6\0" "F7\0" "F8\0" "F9\0" "Fabovedot\0" "fabovedot\0" "Farsi_0\0" "Farsi_1\0" "Farsi_2\0" "Farsi_3\0" "Farsi_4\0" "Farsi_5\0" "Farsi_6\0" "Farsi_7\0" "Farsi_8\0" "Farsi_9\0" "Farsi_yeh\0" "femalesymbol\0" "ff\0" "FFrancSign\0" "figdash\0" "filledlefttribullet\0" "filledrectbullet\0" "filledrighttribullet\0" "filledtribulletdown\0" "filledtribulletup\0" "Find\0" "First_Virtual_Screen\0" "fiveeighths\0" "fivesixths\0" "fivesubscript\0" "fivesuperior\0" "fourfifths\0" "foursubscript\0" "foursuperior\0" "fourthroot\0" "function\0" "G\0" "g\0" "Gabovedot\0" "gabovedot\0" "Gbreve\0" "gbreve\0" "Gcaron\0" "gcaron\0" "Gcedilla\0" "gcedilla\0" "Gcircumflex\0" "gcircumflex\0" "Georgian_an\0" "Georgian_ban\0" "Georgian_can\0" "Georgian_char\0" "Georgian_chin\0" "Georgian_cil\0" "Georgian_don\0" "Georgian_en\0" "Georgian_fi\0" "Georgian_gan\0" "Georgian_ghan\0" "Georgian_hae\0" "Georgian_har\0" "Georgian_he\0" "Georgian_hie\0" "Georgian_hoe\0" "Georgian_in\0" "Georgian_jhan\0" "Georgian_jil\0" "Georgian_kan\0" "Georgian_khar\0" "Georgian_las\0" "Georgian_man\0" "Georgian_nar\0" "Georgian_on\0" "Georgian_par\0" "Georgian_phar\0" "Georgian_qar\0" "Georgian_rae\0" "Georgian_san\0" "Georgian_shin\0" "Georgian_tan\0" "Georgian_tar\0" "Georgian_un\0" "Georgian_vin\0" "Georgian_we\0" "Georgian_xan\0" "Georgian_zen\0" "Georgian_zhar\0" "grave\0" "greater\0" "greaterthanequal\0" "Greek_accentdieresis\0" "Greek_ALPHA\0" "Greek_alpha\0" "Greek_ALPHAaccent\0" "Greek_alphaaccent\0" "Greek_BETA\0" "Greek_beta\0" "Greek_CHI\0" "Greek_chi\0" "Greek_DELTA\0" "Greek_delta\0" "Greek_EPSILON\0" "Greek_epsilon\0" "Greek_EPSILONaccent\0" "Greek_epsilonaccent\0" "Greek_ETA\0" "Greek_eta\0" "Greek_ETAaccent\0" "Greek_etaaccent\0" "Greek_finalsmallsigma\0" "Greek_GAMMA\0" "Greek_gamma\0" "Greek_horizbar\0" "Greek_IOTA\0" "Greek_iota\0" "Greek_IOTAaccent\0" "Greek_iotaaccent\0" "Greek_iotaaccentdieresis\0" "Greek_IOTAdiaeresis\0" "Greek_IOTAdieresis\0" "Greek_iotadieresis\0" "Greek_KAPPA\0" "Greek_kappa\0" "Greek_LAMBDA\0" "Greek_lambda\0" "Greek_LAMDA\0" "Greek_lamda\0" "Greek_MU\0" "Greek_mu\0" "Greek_NU\0" "Greek_nu\0" "Greek_OMEGA\0" "Greek_omega\0" "Greek_OMEGAaccent\0" "Greek_omegaaccent\0" "Greek_OMICRON\0" "Greek_omicron\0" "Greek_OMICRONaccent\0" "Greek_omicronaccent\0" "Greek_PHI\0" "Greek_phi\0" "Greek_PI\0" "Greek_pi\0" "Greek_PSI\0" "Greek_psi\0" "Greek_RHO\0" "Greek_rho\0" "Greek_SIGMA\0" "Greek_sigma\0" "Greek_switch\0" "Greek_TAU\0" "Greek_tau\0" "Greek_THETA\0" "Greek_theta\0" "Greek_UPSILON\0" "Greek_upsilon\0" "Greek_UPSILONaccent\0" "Greek_upsilonaccent\0" "Greek_upsilonaccentdieresis\0" "Greek_UPSILONdieresis\0" "Greek_upsilondieresis\0" "Greek_XI\0" "Greek_xi\0" "Greek_ZETA\0" "Greek_zeta\0" "guilder\0" "guillemetleft\0" "guillemetright\0" "guillemotleft\0" "guillemotright\0" "H\0" "h\0" "hairspace\0" "Hangul\0" "Hangul_A\0" "Hangul_AE\0" "Hangul_AraeA\0" "Hangul_AraeAE\0" "Hangul_Banja\0" "Hangul_Cieuc\0" "Hangul_Codeinput\0" "Hangul_Dikeud\0" "Hangul_E\0" "Hangul_End\0" "Hangul_EO\0" "Hangul_EU\0" "Hangul_Hanja\0" "Hangul_Hieuh\0" "Hangul_I\0" "Hangul_Ieung\0" "Hangul_J_Cieuc\0" "Hangul_J_Dikeud\0" "Hangul_J_Hieuh\0" "Hangul_J_Ieung\0" "Hangul_J_Jieuj\0" "Hangul_J_Khieuq\0" "Hangul_J_Kiyeog\0" "Hangul_J_KiyeogSios\0" "Hangul_J_KkogjiDalrinIeung\0" "Hangul_J_Mieum\0" "Hangul_J_Nieun\0" "Hangul_J_NieunHieuh\0" "Hangul_J_NieunJieuj\0" "Hangul_J_PanSios\0" "Hangul_J_Phieuf\0" "Hangul_J_Pieub\0" "Hangul_J_PieubSios\0" "Hangul_J_Rieul\0" "Hangul_J_RieulHieuh\0" "Hangul_J_RieulKiyeog\0" "Hangul_J_RieulMieum\0" "Hangul_J_RieulPhieuf\0" "Hangul_J_RieulPieub\0" "Hangul_J_RieulSios\0" "Hangul_J_RieulTieut\0" "Hangul_J_Sios\0" "Hangul_J_SsangKiyeog\0" "Hangul_J_SsangSios\0" "Hangul_J_Tieut\0" "Hangul_J_YeorinHieuh\0" "Hangul_Jamo\0" "Hangul_Jeonja\0" "Hangul_Jieuj\0" "Hangul_Khieuq\0" "Hangul_Kiyeog\0" "Hangul_KiyeogSios\0" "Hangul_KkogjiDalrinIeung\0" "Hangul_Mieum\0" "Hangul_MultipleCandidate\0" "Hangul_Nieun\0" "Hangul_NieunHieuh\0" "Hangul_NieunJieuj\0" "Hangul_O\0" "Hangul_OE\0" "Hangul_PanSios\0" "Hangul_Phieuf\0" "Hangul_Pieub\0" "Hangul_PieubSios\0" "Hangul_PostHanja\0" "Hangul_PreHanja\0" "Hangul_PreviousCandidate\0" "Hangul_Rieul\0" "Hangul_RieulHieuh\0" "Hangul_RieulKiyeog\0" "Hangul_RieulMieum\0" "Hangul_RieulPhieuf\0" "Hangul_RieulPieub\0" "Hangul_RieulSios\0" "Hangul_RieulTieut\0" "Hangul_RieulYeorinHieuh\0" "Hangul_Romaja\0" "Hangul_SingleCandidate\0" "Hangul_Sios\0" "Hangul_Special\0" "Hangul_SsangDikeud\0" "Hangul_SsangJieuj\0" "Hangul_SsangKiyeog\0" "Hangul_SsangPieub\0" "Hangul_SsangSios\0" "Hangul_Start\0" "Hangul_SunkyeongeumMieum\0" "Hangul_SunkyeongeumPhieuf\0" "Hangul_SunkyeongeumPieub\0" "Hangul_switch\0" "Hangul_Tieut\0" "Hangul_U\0" "Hangul_WA\0" "Hangul_WAE\0" "Hangul_WE\0" "Hangul_WEO\0" "Hangul_WI\0" "Hangul_YA\0" "Hangul_YAE\0" "Hangul_YE\0" "Hangul_YEO\0" "Hangul_YeorinHieuh\0" "Hangul_YI\0" "Hangul_YO\0" "Hangul_YU\0" "Hankaku\0" "Hcircumflex\0" "hcircumflex\0" "heart\0" "hebrew_aleph\0" "hebrew_ayin\0" "hebrew_bet\0" "hebrew_beth\0" "hebrew_chet\0" "hebrew_dalet\0" "hebrew_daleth\0" "hebrew_doublelowline\0" "hebrew_finalkaph\0" "hebrew_finalmem\0" "hebrew_finalnun\0" "hebrew_finalpe\0" "hebrew_finalzade\0" "hebrew_finalzadi\0" "hebrew_gimel\0" "hebrew_gimmel\0" "hebrew_he\0" "hebrew_het\0" "hebrew_kaph\0" "hebrew_kuf\0" "hebrew_lamed\0" "hebrew_mem\0" "hebrew_nun\0" "hebrew_pe\0" "hebrew_qoph\0" "hebrew_resh\0" "hebrew_samech\0" "hebrew_samekh\0" "hebrew_shin\0" "Hebrew_switch\0" "hebrew_taf\0" "hebrew_taw\0" "hebrew_tet\0" "hebrew_teth\0" "hebrew_waw\0" "hebrew_yod\0" "hebrew_zade\0" "hebrew_zadi\0" "hebrew_zain\0" "hebrew_zayin\0" "Help\0" "Henkan\0" "Henkan_Mode\0" "hexagram\0" "Hiragana\0" "Hiragana_Katakana\0" "Home\0" "horizconnector\0" "horizlinescan1\0" "horizlinescan3\0" "horizlinescan5\0" "horizlinescan7\0" "horizlinescan9\0" "hpBackTab\0" "hpblock\0" "hpClearLine\0" "hpDeleteChar\0" "hpDeleteLine\0" "hpguilder\0" "hpInsertChar\0" "hpInsertLine\0" "hpIO\0" "hpKP_BackTab\0" "hplira\0" "hplongminus\0" "hpModelock1\0" "hpModelock2\0" "hpmute_acute\0" "hpmute_asciicircum\0" "hpmute_asciitilde\0" "hpmute_diaeresis\0" "hpmute_grave\0" "hpReset\0" "hpSystem\0" "hpUser\0" "hpYdiaeresis\0" "Hstroke\0" "hstroke\0" "ht\0" "Hyper_L\0" "Hyper_R\0" "hyphen\0" "I\0" "i\0" "Iabovedot\0" "Iacute\0" "iacute\0" "Ibelowdot\0" "ibelowdot\0" "Ibreve\0" "ibreve\0" "Icircumflex\0" "icircumflex\0" "identical\0" "Idiaeresis\0" "idiaeresis\0" "idotless\0" "ifonlyif\0" "Igrave\0" "igrave\0" "Ihook\0" "ihook\0" "Imacron\0" "imacron\0" "implies\0" "includedin\0" "includes\0" "infinity\0" "Insert\0" "InsertChar\0" "InsertLine\0" "integral\0" "intersection\0" "IO\0" "Iogonek\0" "iogonek\0" "ISO_Center_Object\0" "ISO_Continuous_Underline\0" "ISO_Discontinuous_Underline\0" "ISO_Emphasize\0" "ISO_Enter\0" "ISO_Fast_Cursor_Down\0" "ISO_Fast_Cursor_Left\0" "ISO_Fast_Cursor_Right\0" "ISO_Fast_Cursor_Up\0" "ISO_First_Group\0" "ISO_First_Group_Lock\0" "ISO_Group_Latch\0" "ISO_Group_Lock\0" "ISO_Group_Shift\0" "ISO_Last_Group\0" "ISO_Last_Group_Lock\0" "ISO_Left_Tab\0" "ISO_Level2_Latch\0" "ISO_Level3_Latch\0" "ISO_Level3_Lock\0" "ISO_Level3_Shift\0" "ISO_Level5_Latch\0" "ISO_Level5_Lock\0" "ISO_Level5_Shift\0" "ISO_Lock\0" "ISO_Move_Line_Down\0" "ISO_Move_Line_Up\0" "ISO_Next_Group\0" "ISO_Next_Group_Lock\0" "ISO_Partial_Line_Down\0" "ISO_Partial_Line_Up\0" "ISO_Partial_Space_Left\0" "ISO_Partial_Space_Right\0" "ISO_Prev_Group\0" "ISO_Prev_Group_Lock\0" "ISO_Release_Both_Margins\0" "ISO_Release_Margin_Left\0" "ISO_Release_Margin_Right\0" "ISO_Set_Margin_Left\0" "ISO_Set_Margin_Right\0" "Itilde\0" "itilde\0" "J\0" "j\0" "Jcircumflex\0" "jcircumflex\0" "jot\0" "K\0" "k\0" "kana_A\0" "kana_a\0" "kana_CHI\0" "kana_closingbracket\0" "kana_comma\0" "kana_conjunctive\0" "kana_E\0" "kana_e\0" "kana_FU\0" "kana_fullstop\0" "kana_HA\0" "kana_HE\0" "kana_HI\0" "kana_HO\0" "kana_HU\0" "kana_I\0" "kana_i\0" "kana_KA\0" "kana_KE\0" "kana_KI\0" "kana_KO\0" "kana_KU\0" "Kana_Lock\0" "kana_MA\0" "kana_ME\0" "kana_MI\0" "kana_middledot\0" "kana_MO\0" "kana_MU\0" "kana_N\0" "kana_NA\0" "kana_NE\0" "kana_NI\0" "kana_NO\0" "kana_NU\0" "kana_O\0" "kana_o\0" "kana_openingbracket\0" "kana_RA\0" "kana_RE\0" "kana_RI\0" "kana_RO\0" "kana_RU\0" "kana_SA\0" "kana_SE\0" "kana_SHI\0" "Kana_Shift\0" "kana_SO\0" "kana_SU\0" "kana_switch\0" "kana_TA\0" "kana_TE\0" "kana_TI\0" "kana_TO\0" "kana_TSU\0" "kana_tsu\0" "kana_TU\0" "kana_tu\0" "kana_U\0" "kana_u\0" "kana_WA\0" "kana_WO\0" "kana_YA\0" "kana_ya\0" "kana_YO\0" "kana_yo\0" "kana_YU\0" "kana_yu\0" "Kanji\0" "Kanji_Bangou\0" "kappa\0" "Katakana\0" "Kcedilla\0" "kcedilla\0" "Korean_Won\0" "KP_0\0" "KP_1\0" "KP_2\0" "KP_3\0" "KP_4\0" "KP_5\0" "KP_6\0" "KP_7\0" "KP_8\0" "KP_9\0" "KP_Add\0" "KP_BackTab\0" "KP_Begin\0" "KP_Decimal\0" "KP_Delete\0" "KP_Divide\0" "KP_Down\0" "KP_End\0" "KP_Enter\0" "KP_Equal\0" "KP_F1\0" "KP_F2\0" "KP_F3\0" "KP_F4\0" "KP_Home\0" "KP_Insert\0" "KP_Left\0" "KP_Multiply\0" "KP_Next\0" "KP_Page_Down\0" "KP_Page_Up\0" "KP_Prior\0" "KP_Right\0" "KP_Separator\0" "KP_Space\0" "KP_Subtract\0" "KP_Tab\0" "KP_Up\0" "kra\0" "L\0" "l\0" "L1\0" "L10\0" "L2\0" "L3\0" "L4\0" "L5\0" "L6\0" "L7\0" "L8\0" "L9\0" "Lacute\0" "lacute\0" "Last_Virtual_Screen\0" "latincross\0" "Lbelowdot\0" "lbelowdot\0" "Lcaron\0" "lcaron\0" "Lcedilla\0" "lcedilla\0" "Left\0" "leftanglebracket\0" "leftarrow\0" "leftcaret\0" "leftdoublequotemark\0" "leftmiddlecurlybrace\0" "leftopentriangle\0" "leftpointer\0" "leftradical\0" "leftshoe\0" "leftsinglequotemark\0" "leftt\0" "lefttack\0" "less\0" "lessthanequal\0" "lf\0" "Linefeed\0" "lira\0" "LiraSign\0" "logicaland\0" "logicalor\0" "longminus\0" "lowleftcorner\0" "lowrightcorner\0" "Lstroke\0" "lstroke\0" "M\0" "m\0" "Mabovedot\0" "mabovedot\0" "Macedonia_DSE\0" "Macedonia_dse\0" "Macedonia_GJE\0" "Macedonia_gje\0" "Macedonia_KJE\0" "Macedonia_kje\0" "macron\0" "Mae_Koho\0" "malesymbol\0" "maltesecross\0" "marker\0" "masculine\0" "Massyo\0" "Menu\0" "Meta_L\0" "Meta_R\0" "MillSign\0" "minus\0" "minutes\0" "Mode_switch\0" "MouseKeys_Accel_Enable\0" "MouseKeys_Enable\0" "mu\0" "Muhenkan\0" "Multi_key\0" "MultipleCandidate\0" "multiply\0" "musicalflat\0" "musicalsharp\0" "mute_acute\0" "mute_asciicircum\0" "mute_asciitilde\0" "mute_diaeresis\0" "mute_grave\0" "N\0" "n\0" "nabla\0" "Nacute\0" "nacute\0" "NairaSign\0" "Ncaron\0" "ncaron\0" "Ncedilla\0" "ncedilla\0" "NewSheqelSign\0" "Next\0" "Next_Virtual_Screen\0" "ninesubscript\0" "ninesuperior\0" "nl\0" "nobreakspace\0" "NoSymbol\0" "notapproxeq\0" "notelementof\0" "notequal\0" "notidentical\0" "notsign\0" "Ntilde\0" "ntilde\0" "Num_Lock\0" "numbersign\0" "numerosign\0" "O\0" "o\0" "Oacute\0" "oacute\0" "Obarred\0" "obarred\0" "Obelowdot\0" "obelowdot\0" "Ocaron\0" "ocaron\0" "Ocircumflex\0" "ocircumflex\0" "Ocircumflexacute\0" "ocircumflexacute\0" "Ocircumflexbelowdot\0" "ocircumflexbelowdot\0" "Ocircumflexgrave\0" "ocircumflexgrave\0" "Ocircumflexhook\0" "ocircumflexhook\0" "Ocircumflextilde\0" "ocircumflextilde\0" "Odiaeresis\0" "odiaeresis\0" "Odoubleacute\0" "odoubleacute\0" "OE\0" "oe\0" "ogonek\0" "Ograve\0" "ograve\0" "Ohook\0" "ohook\0" "Ohorn\0" "ohorn\0" "Ohornacute\0" "ohornacute\0" "Ohornbelowdot\0" "ohornbelowdot\0" "Ohorngrave\0" "ohorngrave\0" "Ohornhook\0" "ohornhook\0" "Ohorntilde\0" "ohorntilde\0" "Omacron\0" "omacron\0" "oneeighth\0" "onefifth\0" "onehalf\0" "onequarter\0" "onesixth\0" "onesubscript\0" "onesuperior\0" "onethird\0" "Ooblique\0" "ooblique\0" "openrectbullet\0" "openstar\0" "opentribulletdown\0" "opentribulletup\0" "ordfeminine\0" "ordmasculine\0" "osfActivate\0" "osfAddMode\0" "osfBackSpace\0" "osfBackTab\0" "osfBeginData\0" "osfBeginLine\0" "osfCancel\0" "osfClear\0" "osfCopy\0" "osfCut\0" "osfDelete\0" "osfDeselectAll\0" "osfDown\0" "osfEndData\0" "osfEndLine\0" "osfEscape\0" "osfExtend\0" "osfHelp\0" "osfInsert\0" "osfLeft\0" "osfMenu\0" "osfMenuBar\0" "osfNextField\0" "osfNextMenu\0" "osfPageDown\0" "osfPageLeft\0" "osfPageRight\0" "osfPageUp\0" "osfPaste\0" "osfPrevField\0" "osfPrevMenu\0" "osfPrimaryPaste\0" "osfQuickPaste\0" "osfReselect\0" "osfRestore\0" "osfRight\0" "osfSelect\0" "osfSelectAll\0" "osfUndo\0" "osfUp\0" "Oslash\0" "oslash\0" "Otilde\0" "otilde\0" "overbar\0" "Overlay1_Enable\0" "Overlay2_Enable\0" "overline\0" "P\0" "p\0" "Pabovedot\0" "pabovedot\0" "Page_Down\0" "Page_Up\0" "paragraph\0" "parenleft\0" "parenright\0" "partdifferential\0" "partialderivative\0" "Pause\0" "percent\0" "period\0" "periodcentered\0" "permille\0" "PesetaSign\0" "phonographcopyright\0" "plus\0" "plusminus\0" "Pointer_Accelerate\0" "Pointer_Button1\0" "Pointer_Button2\0" "Pointer_Button3\0" "Pointer_Button4\0" "Pointer_Button5\0" "Pointer_Button_Dflt\0" "Pointer_DblClick1\0" "Pointer_DblClick2\0" "Pointer_DblClick3\0" "Pointer_DblClick4\0" "Pointer_DblClick5\0" "Pointer_DblClick_Dflt\0" "Pointer_DfltBtnNext\0" "Pointer_DfltBtnPrev\0" "Pointer_Down\0" "Pointer_DownLeft\0" "Pointer_DownRight\0" "Pointer_Drag1\0" "Pointer_Drag2\0" "Pointer_Drag3\0" "Pointer_Drag4\0" "Pointer_Drag5\0" "Pointer_Drag_Dflt\0" "Pointer_EnableKeys\0" "Pointer_Left\0" "Pointer_Right\0" "Pointer_Up\0" "Pointer_UpLeft\0" "Pointer_UpRight\0" "prescription\0" "Prev_Virtual_Screen\0" "PreviousCandidate\0" "Print\0" "Prior\0" "prolongedsound\0" "punctspace\0" "Q\0" "q\0" "quad\0" "question\0" "questiondown\0" "quotedbl\0" "quoteleft\0" "quoteright\0" "R\0" "r\0" "R1\0" "R10\0" "R11\0" "R12\0" "R13\0" "R14\0" "R15\0" "R2\0" "R3\0" "R4\0" "R5\0" "R6\0" "R7\0" "R8\0" "R9\0" "Racute\0" "racute\0" "radical\0" "Rcaron\0" "rcaron\0" "Rcedilla\0" "rcedilla\0" "Redo\0" "registered\0" "RepeatKeys_Enable\0" "Reset\0" "Return\0" "Right\0" "rightanglebracket\0" "rightarrow\0" "rightcaret\0" "rightdoublequotemark\0" "rightmiddlecurlybrace\0" "rightmiddlesummation\0" "rightopentriangle\0" "rightpointer\0" "rightshoe\0" "rightsinglequotemark\0" "rightt\0" "righttack\0" "Romaji\0" "RupeeSign\0" "S\0" "s\0" "Sabovedot\0" "sabovedot\0" "Sacute\0" "sacute\0" "Scaron\0" "scaron\0" "Scedilla\0" "scedilla\0" "SCHWA\0" "schwa\0" "Scircumflex\0" "scircumflex\0" "script_switch\0" "Scroll_Lock\0" "seconds\0" "section\0" "Select\0" "semicolon\0" "semivoicedsound\0" "Serbian_DJE\0" "Serbian_dje\0" "Serbian_DZE\0" "Serbian_dze\0" "Serbian_JE\0" "Serbian_je\0" "Serbian_LJE\0" "Serbian_lje\0" "Serbian_NJE\0" "Serbian_nje\0" "Serbian_TSHE\0" "Serbian_tshe\0" "seveneighths\0" "sevensubscript\0" "sevensuperior\0" "Shift_L\0" "Shift_Lock\0" "Shift_R\0" "signaturemark\0" "signifblank\0" "similarequal\0" "SingleCandidate\0" "singlelowquotemark\0" "Sinh_a\0" "Sinh_aa\0" "Sinh_aa2\0" "Sinh_ae\0" "Sinh_ae2\0" "Sinh_aee\0" "Sinh_aee2\0" "Sinh_ai\0" "Sinh_ai2\0" "Sinh_al\0" "Sinh_au\0" "Sinh_au2\0" "Sinh_ba\0" "Sinh_bha\0" "Sinh_ca\0" "Sinh_cha\0" "Sinh_dda\0" "Sinh_ddha\0" "Sinh_dha\0" "Sinh_dhha\0" "Sinh_e\0" "Sinh_e2\0" "Sinh_ee\0" "Sinh_ee2\0" "Sinh_fa\0" "Sinh_ga\0" "Sinh_gha\0" "Sinh_h2\0" "Sinh_ha\0" "Sinh_i\0" "Sinh_i2\0" "Sinh_ii\0" "Sinh_ii2\0" "Sinh_ja\0" "Sinh_jha\0" "Sinh_jnya\0" "Sinh_ka\0" "Sinh_kha\0" "Sinh_kunddaliya\0" "Sinh_la\0" "Sinh_lla\0" "Sinh_lu\0" "Sinh_lu2\0" "Sinh_luu\0" "Sinh_luu2\0" "Sinh_ma\0" "Sinh_mba\0" "Sinh_na\0" "Sinh_ndda\0" "Sinh_ndha\0" "Sinh_ng\0" "Sinh_ng2\0" "Sinh_nga\0" "Sinh_nja\0" "Sinh_nna\0" "Sinh_nya\0" "Sinh_o\0" "Sinh_o2\0" "Sinh_oo\0" "Sinh_oo2\0" "Sinh_pa\0" "Sinh_pha\0" "Sinh_ra\0" "Sinh_ri\0" "Sinh_rii\0" "Sinh_ru2\0" "Sinh_ruu2\0" "Sinh_sa\0" "Sinh_sha\0" "Sinh_ssha\0" "Sinh_tha\0" "Sinh_thha\0" "Sinh_tta\0" "Sinh_ttha\0" "Sinh_u\0" "Sinh_u2\0" "Sinh_uu\0" "Sinh_uu2\0" "Sinh_va\0" "Sinh_ya\0" "sixsubscript\0" "sixsuperior\0" "slash\0" "SlowKeys_Enable\0" "soliddiamond\0" "space\0" "squareroot\0" "ssharp\0" "sterling\0" "StickyKeys_Enable\0" "stricteq\0" "SunAgain\0" "SunAltGraph\0" "SunAudioLowerVolume\0" "SunAudioMute\0" "SunAudioRaiseVolume\0" "SunCompose\0" "SunCopy\0" "SunCut\0" "SunF36\0" "SunF37\0" "SunFA_Acute\0" "SunFA_Cedilla\0" "SunFA_Circum\0" "SunFA_Diaeresis\0" "SunFA_Grave\0" "SunFA_Tilde\0" "SunFind\0" "SunFront\0" "SunOpen\0" "SunPageDown\0" "SunPageUp\0" "SunPaste\0" "SunPowerSwitch\0" "SunPowerSwitchShift\0" "SunPrint_Screen\0" "SunProps\0" "SunStop\0" "SunSys_Req\0" "SunUndo\0" "SunVideoDegauss\0" "SunVideoLowerBrightness\0" "SunVideoRaiseBrightness\0" "Super_L\0" "Super_R\0" "Sys_Req\0" "System\0" "T\0" "t\0" "Tab\0" "Tabovedot\0" "tabovedot\0" "Tcaron\0" "tcaron\0" "Tcedilla\0" "tcedilla\0" "telephone\0" "telephonerecorder\0" "Terminate_Server\0" "Thai_baht\0" "Thai_bobaimai\0" "Thai_chochan\0" "Thai_chochang\0" "Thai_choching\0" "Thai_chochoe\0" "Thai_dochada\0" "Thai_dodek\0" "Thai_fofa\0" "Thai_fofan\0" "Thai_hohip\0" "Thai_honokhuk\0" "Thai_khokhai\0" "Thai_khokhon\0" "Thai_khokhuat\0" "Thai_khokhwai\0" "Thai_khorakhang\0" "Thai_kokai\0" "Thai_lakkhangyao\0" "Thai_lekchet\0" "Thai_lekha\0" "Thai_lekhok\0" "Thai_lekkao\0" "Thai_leknung\0" "Thai_lekpaet\0" "Thai_leksam\0" "Thai_leksi\0" "Thai_leksong\0" "Thai_leksun\0" "Thai_lochula\0" "Thai_loling\0" "Thai_lu\0" "Thai_maichattawa\0" "Thai_maiek\0" "Thai_maihanakat\0" "Thai_maihanakat_maitho\0" "Thai_maitaikhu\0" "Thai_maitho\0" "Thai_maitri\0" "Thai_maiyamok\0" "Thai_moma\0" "Thai_ngongu\0" "Thai_nikhahit\0" "Thai_nonen\0" "Thai_nonu\0" "Thai_oang\0" "Thai_paiyannoi\0" "Thai_phinthu\0" "Thai_phophan\0" "Thai_phophung\0" "Thai_phosamphao\0" "Thai_popla\0" "Thai_rorua\0" "Thai_ru\0" "Thai_saraa\0" "Thai_saraaa\0" "Thai_saraae\0" "Thai_saraaimaimalai\0" "Thai_saraaimaimuan\0" "Thai_saraam\0" "Thai_sarae\0" "Thai_sarai\0" "Thai_saraii\0" "Thai_sarao\0" "Thai_sarau\0" "Thai_saraue\0" "Thai_sarauee\0" "Thai_sarauu\0" "Thai_sorusi\0" "Thai_sosala\0" "Thai_soso\0" "Thai_sosua\0" "Thai_thanthakhat\0" "Thai_thonangmontho\0" "Thai_thophuthao\0" "Thai_thothahan\0" "Thai_thothan\0" "Thai_thothong\0" "Thai_thothung\0" "Thai_topatak\0" "Thai_totao\0" "Thai_wowaen\0" "Thai_yoyak\0" "Thai_yoying\0" "therefore\0" "thinspace\0" "THORN\0" "Thorn\0" "thorn\0" "threeeighths\0" "threefifths\0" "threequarters\0" "threesubscript\0" "threesuperior\0" "tintegral\0" "topintegral\0" "topleftparens\0" "topleftradical\0" "topleftsqbracket\0" "topleftsummation\0" "toprightparens\0" "toprightsqbracket\0" "toprightsummation\0" "topt\0" "topvertsummationconnector\0" "Touroku\0" "trademark\0" "trademarkincircle\0" "Tslash\0" "tslash\0" "twofifths\0" "twosubscript\0" "twosuperior\0" "twothirds\0" "U\0" "u\0" "Uacute\0" "uacute\0" "Ubelowdot\0" "ubelowdot\0" "Ubreve\0" "ubreve\0" "Ucircumflex\0" "ucircumflex\0" "Udiaeresis\0" "udiaeresis\0" "Udoubleacute\0" "udoubleacute\0" "Ugrave\0" "ugrave\0" "Uhook\0" "uhook\0" "Uhorn\0" "uhorn\0" "Uhornacute\0" "uhornacute\0" "Uhornbelowdot\0" "uhornbelowdot\0" "Uhorngrave\0" "uhorngrave\0" "Uhornhook\0" "uhornhook\0" "Uhorntilde\0" "uhorntilde\0" "Ukrainian_GHE_WITH_UPTURN\0" "Ukrainian_ghe_with_upturn\0" "Ukrainian_I\0" "Ukrainian_i\0" "Ukrainian_IE\0" "Ukrainian_ie\0" "Ukrainian_YI\0" "Ukrainian_yi\0" "Ukranian_I\0" "Ukranian_i\0" "Ukranian_JE\0" "Ukranian_je\0" "Ukranian_YI\0" "Ukranian_yi\0" "Umacron\0" "umacron\0" "underbar\0" "underscore\0" "Undo\0" "union\0" "Uogonek\0" "uogonek\0" "Up\0" "uparrow\0" "upcaret\0" "upleftcorner\0" "uprightcorner\0" "upshoe\0" "upstile\0" "uptack\0" "Uring\0" "uring\0" "User\0" "Utilde\0" "utilde\0" "V\0" "v\0" "variation\0" "vertbar\0" "vertconnector\0" "voicedsound\0" "VoidSymbol\0" "vt\0" "W\0" "w\0" "Wacute\0" "wacute\0" "Wcircumflex\0" "wcircumflex\0" "Wdiaeresis\0" "wdiaeresis\0" "Wgrave\0" "wgrave\0" "WonSign\0" "X\0" "x\0" "Xabovedot\0" "xabovedot\0" "XF8610ChannelsDown\0" "XF8610ChannelsUp\0" "XF863DMode\0" "XF86Accessibility\0" "XF86AddFavorite\0" "XF86Addressbook\0" "XF86ALSToggle\0" "XF86ApplicationLeft\0" "XF86ApplicationRight\0" "XF86AppSelect\0" "XF86AspectRatio\0" "XF86Assistant\0" "XF86AttendantOff\0" "XF86AttendantOn\0" "XF86AttendantToggle\0" "XF86Audio\0" "XF86AudioChannelMode\0" "XF86AudioCycleTrack\0" "XF86AudioDesc\0" "XF86AudioForward\0" "XF86AudioLowerVolume\0" "XF86AudioMedia\0" "XF86AudioMicMute\0" "XF86AudioMute\0" "XF86AudioNext\0" "XF86AudioPause\0" "XF86AudioPlay\0" "XF86AudioPreset\0" "XF86AudioPrev\0" "XF86AudioRaiseVolume\0" "XF86AudioRandomPlay\0" "XF86AudioRecord\0" "XF86AudioRepeat\0" "XF86AudioRewind\0" "XF86AudioStop\0" "XF86AutopilotEngageToggle\0" "XF86Away\0" "XF86Back\0" "XF86BackForward\0" "XF86Battery\0" "XF86Blue\0" "XF86Bluetooth\0" "XF86Book\0" "XF86Break\0" "XF86BrightnessAdjust\0" "XF86BrightnessAuto\0" "XF86BrightnessMax\0" "XF86BrightnessMin\0" "XF86Buttonconfig\0" "XF86Calculater\0" "XF86Calculator\0" "XF86Calendar\0" "XF86CameraAccessDisable\0" "XF86CameraAccessEnable\0" "XF86CameraAccessToggle\0" "XF86CameraDown\0" "XF86CameraFocus\0" "XF86CameraLeft\0" "XF86CameraRight\0" "XF86CameraUp\0" "XF86CameraZoomIn\0" "XF86CameraZoomOut\0" "XF86CD\0" "XF86ChannelDown\0" "XF86ChannelUp\0" "XF86Clear\0" "XF86ClearGrab\0" "XF86ClearvuSonar\0" "XF86Close\0" "XF86Community\0" "XF86ContextMenu\0" "XF86ContrastAdjust\0" "XF86ControlPanel\0" "XF86Copy\0" "XF86Cut\0" "XF86CycleAngle\0" "XF86Data\0" "XF86Database\0" "XF86Dictate\0" "XF86Display\0" "XF86DisplayOff\0" "XF86DisplayToggle\0" "XF86Documents\0" "XF86DoNotDisturb\0" "XF86DOS\0" "XF86DualRangeRadar\0" "XF86DVD\0" "XF86Editor\0" "XF86Eject\0" "XF86EmojiPicker\0" "XF86Excel\0" "XF86Explorer\0" "XF86FastReverse\0" "XF86Favorites\0" "XF86Finance\0" "XF86FishingChart\0" "XF86Fn\0" "XF86Fn_1\0" "XF86Fn_2\0" "XF86Fn_B\0" "XF86Fn_D\0" "XF86Fn_E\0" "XF86Fn_Esc\0" "XF86Fn_F\0" "XF86Fn_F1\0" "XF86Fn_F10\0" "XF86Fn_F11\0" "XF86Fn_F12\0" "XF86Fn_F2\0" "XF86Fn_F3\0" "XF86Fn_F4\0" "XF86Fn_F5\0" "XF86Fn_F6\0" "XF86Fn_F7\0" "XF86Fn_F8\0" "XF86Fn_F9\0" "XF86Fn_S\0" "XF86FnRightShift\0" "XF86Forward\0" "XF86FrameBack\0" "XF86FrameForward\0" "XF86FullScreen\0" "XF86Game\0" "XF86Go\0" "XF86GoTo\0" "XF86GraphicsEditor\0" "XF86Green\0" "XF86HangupPhone\0" "XF86Hibernate\0" "XF86History\0" "XF86HomePage\0" "XF86HotLinks\0" "XF86Images\0" "XF86Info\0" "XF86iTouch\0" "XF86Journal\0" "XF86KbdBrightnessDown\0" "XF86KbdBrightnessUp\0" "XF86KbdInputAssistAccept\0" "XF86KbdInputAssistCancel\0" "XF86KbdInputAssistNext\0" "XF86KbdInputAssistNextgroup\0" "XF86KbdInputAssistPrev\0" "XF86KbdInputAssistPrevgroup\0" "XF86KbdLcdMenu1\0" "XF86KbdLcdMenu2\0" "XF86KbdLcdMenu3\0" "XF86KbdLcdMenu4\0" "XF86KbdLcdMenu5\0" "XF86KbdLightOnOff\0" "XF86Keyboard\0" "XF86Launch0\0" "XF86Launch1\0" "XF86Launch2\0" "XF86Launch3\0" "XF86Launch4\0" "XF86Launch5\0" "XF86Launch6\0" "XF86Launch7\0" "XF86Launch8\0" "XF86Launch9\0" "XF86LaunchA\0" "XF86LaunchB\0" "XF86LaunchC\0" "XF86LaunchD\0" "XF86LaunchE\0" "XF86LaunchF\0" "XF86LeftDown\0" "XF86LeftUp\0" "XF86LightBulb\0" "XF86LightsToggle\0" "XF86LinkPhone\0" "XF86LogGrabInfo\0" "XF86LogOff\0" "XF86LogWindowTree\0" "XF86Macro1\0" "XF86Macro10\0" "XF86Macro11\0" "XF86Macro12\0" "XF86Macro13\0" "XF86Macro14\0" "XF86Macro15\0" "XF86Macro16\0" "XF86Macro17\0" "XF86Macro18\0" "XF86Macro19\0" "XF86Macro2\0" "XF86Macro20\0" "XF86Macro21\0" "XF86Macro22\0" "XF86Macro23\0" "XF86Macro24\0" "XF86Macro25\0" "XF86Macro26\0" "XF86Macro27\0" "XF86Macro28\0" "XF86Macro29\0" "XF86Macro3\0" "XF86Macro30\0" "XF86Macro4\0" "XF86Macro5\0" "XF86Macro6\0" "XF86Macro7\0" "XF86Macro8\0" "XF86Macro9\0" "XF86MacroPreset1\0" "XF86MacroPreset2\0" "XF86MacroPreset3\0" "XF86MacroPresetCycle\0" "XF86MacroRecordStart\0" "XF86MacroRecordStop\0" "XF86Mail\0" "XF86MailForward\0" "XF86Market\0" "XF86MarkWaypoint\0" "XF86MediaLanguageMenu\0" "XF86MediaPlayer\0" "XF86MediaPlaySlow\0" "XF86MediaRepeat\0" "XF86MediaSelectAuxiliary\0" "XF86MediaSelectCable\0" "XF86MediaSelectCD\0" "XF86MediaSelectDVD\0" "XF86MediaSelectHome\0" "XF86MediaSelectPC\0" "XF86MediaSelectProgramGuide\0" "XF86MediaSelectRadio\0" "XF86MediaSelectSatellite\0" "XF86MediaSelectTape\0" "XF86MediaSelectTeletext\0" "XF86MediaSelectTuner\0" "XF86MediaSelectTV\0" "XF86MediaSelectVCR\0" "XF86MediaSelectVCRPlus\0" "XF86MediaTitleMenu\0" "XF86MediaTopMenu\0" "XF86Meeting\0" "XF86Memo\0" "XF86MenuKB\0" "XF86MenuPB\0" "XF86Messenger\0" "XF86ModeLock\0" "XF86MonBrightnessAuto\0" "XF86MonBrightnessCycle\0" "XF86MonBrightnessDown\0" "XF86MonBrightnessUp\0" "XF86Music\0" "XF86MyComputer\0" "XF86MySites\0" "XF86NavChart\0" "XF86NavInfo\0" "XF86New\0" "XF86News\0" "XF86Next_VMode\0" "XF86NextElement\0" "XF86NextFavorite\0" "XF86NotificationCenter\0" "XF86NumberEntryMode\0" "XF86Numeric0\0" "XF86Numeric1\0" "XF86Numeric11\0" "XF86Numeric12\0" "XF86Numeric2\0" "XF86Numeric3\0" "XF86Numeric4\0" "XF86Numeric5\0" "XF86Numeric6\0" "XF86Numeric7\0" "XF86Numeric8\0" "XF86Numeric9\0" "XF86NumericA\0" "XF86NumericB\0" "XF86NumericC\0" "XF86NumericD\0" "XF86NumericPound\0" "XF86NumericStar\0" "XF86OfficeHome\0" "XF86OK\0" "XF86OnScreenKeyboard\0" "XF86Open\0" "XF86OpenURL\0" "XF86Option\0" "XF86Paste\0" "XF86PauseRecord\0" "XF86PerformanceMode\0" "XF86Phone\0" "XF86PickupPhone\0" "XF86Pictures\0" "XF86PowerDown\0" "XF86PowerOff\0" "XF86Presentation\0" "XF86Prev_VMode\0" "XF86PreviousElement\0" "XF86PrivacyScreenToggle\0" "XF86Q\0" "XF86RadarOverlay\0" "XF86Red\0" "XF86Refresh\0" "XF86RefreshRateToggle\0" "XF86Reload\0" "XF86Reply\0" "XF86RFKill\0" "XF86RightDown\0" "XF86RightUp\0" "XF86RockerDown\0" "XF86RockerEnter\0" "XF86RockerUp\0" "XF86RootMenu\0" "XF86RotateWindows\0" "XF86RotationKB\0" "XF86RotationLockToggle\0" "XF86RotationPB\0" "XF86Save\0" "XF86ScreenSaver\0" "XF86Screensaver\0" "XF86ScrollClick\0" "XF86ScrollDown\0" "XF86ScrollUp\0" "XF86Search\0" "XF86Select\0" "XF86SelectiveScreenshot\0" "XF86Send\0" "XF86Shop\0" "XF86SidevuSonar\0" "XF86SingleRangeRadar\0" "XF86Sleep\0" "XF86SlowReverse\0" "XF86Sos\0" "XF86Spell\0" "XF86SpellCheck\0" "XF86SplitScreen\0" "XF86Sport\0" "XF86Standby\0" "XF86Start\0" "XF86Stop\0" "XF86StopRecord\0" "XF86Subtitle\0" "XF86Support\0" "XF86Suspend\0" "XF86Switch_VT_1\0" "XF86Switch_VT_10\0" "XF86Switch_VT_11\0" "XF86Switch_VT_12\0" "XF86Switch_VT_2\0" "XF86Switch_VT_3\0" "XF86Switch_VT_4\0" "XF86Switch_VT_5\0" "XF86Switch_VT_6\0" "XF86Switch_VT_7\0" "XF86Switch_VT_8\0" "XF86Switch_VT_9\0" "XF86Taskmanager\0" "XF86TaskPane\0" "XF86Terminal\0" "XF86Time\0" "XF86ToDoList\0" "XF86Tools\0" "XF86TopMenu\0" "XF86TouchpadOff\0" "XF86TouchpadOn\0" "XF86TouchpadToggle\0" "XF86TraditionalSonar\0" "XF86Travel\0" "XF86Ungrab\0" "XF86Unmute\0" "XF86User1KB\0" "XF86User2KB\0" "XF86UserPB\0" "XF86UWB\0" "XF86VendorHome\0" "XF86VendorLogo\0" "XF86Video\0" "XF86VideoPhone\0" "XF86View\0" "XF86VOD\0" "XF86VoiceCommand\0" "XF86Voicemail\0" "XF86WakeUp\0" "XF86WebCam\0" "XF86WheelButton\0" "XF86WLAN\0" "XF86Word\0" "XF86WPSButton\0" "XF86WWAN\0" "XF86WWW\0" "XF86Xfer\0" "XF86Yellow\0" "XF86ZoomIn\0" "XF86ZoomOut\0" "XF86ZoomReset\0" "Y\0" "y\0" "Yacute\0" "yacute\0" "Ybelowdot\0" "ybelowdot\0" "Ycircumflex\0" "ycircumflex\0" "Ydiaeresis\0" "ydiaeresis\0" "yen\0" "Ygrave\0" "ygrave\0" "Yhook\0" "yhook\0" "Ytilde\0" "ytilde\0" "Z\0" "z\0" "Zabovedot\0" "zabovedot\0" "Zacute\0" "zacute\0" "Zcaron\0" "zcaron\0" "Zen_Koho\0" "Zenkaku\0" "Zenkaku_Hankaku\0" "zerosubscript\0" "zerosuperior\0" "Zstroke\0" "zstroke\0" ; #ifdef __GNUC__ #pragma GCC diagnostic pop #endif static const uint16_t keysym_name_G[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3887, 0, 0, 0, 0, 452, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1768, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 669, 3644, 0, 0, 0, 3745, 0, 0, 2211, 0, 0, 1563, 0, 0, 1978, 0, 2558, 0, 0, 2746, 0, 0, 0, 0, 0, 0, 4648, 0, 0, 0, 0, 0, 0, 0, 1082, 0, 0, 1675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2344, 0, 0, 2318, 301, 0, 0, 44, 0, 0, 0, 0, 0, 0, 274, 0, 0, 0, 0, 0, 0, 3130, 2809, 1610, 0, 3211, 0, 0, 0, 749, 3092, 0, 21, 1240, 669, 2032, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, 1696, 1000, 0, 669, 0, 0, 0, 0, 0, 1173, 0, 3283, 0, 35, 28, 259, 0, 0, 0, 0, 0, 0, 1643, 2611, 0, 0, 0, 704, 0, 0, 0, 0, 0, 0, 0, 1515, 4045, 0, 2529, 0, 0, 0, 0, 1378, 1991, 4889, 0, 138, 0, 0, 4878, 0, 0, 0, 0, 0, 0, 3930, 0, 1527, 0, 146, 4500, 0, 0, 4278, 0, 0, 86, 0, 0, 3955, 0, 0, 3531, 0, 3358, 0, 4310, 303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3287, 0, 0, 3175, 0, 0, 0, 0, 0, 0, 0, 0, 0, 150, 1161, 1567, 0, 0, 0, 2929, 0, 3297, 591, 2364, 2527, 0, 2214, 0, 0, 0, 2975, 0, 2729, 0, 1233, 992, 3042, 0, 0, 0, 0, 0, 0, 0, 0, 3343, 1131, 2486, 0, 0, 0, 0, 304, 0, 4148, 0, 0, 0, 2781, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2642, 0, 0, 860, 688, 0, 0, 0, 1887, 0, 0, 380, 0, 300, 325, 0, 0, 0, 0, 0, 0, 4875, 0, 726, 0, 0, 0, 0, 2611, 0, 4062, 0, 558, 0, 0, 0, 504, 0, 0, 0, 4791, 0, 0, 0, 2413, 1711, 2038, 1914, 0, 3537, 0, 0, 0, 0, 0, 0, 0, 2287, 0, 1518, 0, 3477, 0, 4555, 0, 3145, 3998, 0, 0, 1828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1867, 0, 1080, 0, 0, 0, 1590, 0, 0, 0, 0, 2157, 0, 3922, 0, 1897, 0, 0, 557, 0, 0, 0, 3247, 0, 0, 2375, 0, 0, 0, 2734, 1480, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 306, 0, 267, 0, 0, 0, 0, 0, 820, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3896, 0, 0, 2430, 2694, 1212, 0, 0, 2003, 0, 0, 0, 0, 4712, 0, 2865, 0, 0, 436, 0, 0, 0, 498, 2808, 0, 0, 526, 0, 0, 0, 534, 4411, 2907, 0, 0, 1147, 4490, 4901, 0, 0, 0, 0, 0, 571, 3682, 0, 4560, 1847, 0, 0, 585, 1437, 0, 4126, 4859, 0, 4153, 0, 0, 158, 0, 839, 0, 643, 0, 4674, 4817, 0, 1374, 1729, 0, 0, 0, 2357, 4604, 0, 2068, 0, 0, 0, 676, 0, 2189, 3860, 0, 0, 0, 0, 0, 0, 2553, 0, 0, 0, 0, 0, 0, 0, 0, 927, 0, 91, 0, 0, 0, 643, 0, 51, 4561, 2265, 0, 0, 150, 0, 0, 205, 0, 0, 1627, 0, 416, 0, 0, 0, 0, 4835, 0, 500, 3447, 0, 0, 486, 0, 2666, 2327, 2355, 4458, 3128, 0, 0, 0, 1508, 0, 308, 0, 0, 4570, 0, 0, 2773, 2997, 0, 0, 0, 0, 2039, 0, 563, 0, 0, 320, 0, 0, 589, 0, 0, 86, 0, 0, 0, 1395, 0, 3402, 0, 0, 0, 0, 0, 0, 4355, 0, 3480, 314, 757, 0, 4661, 0, 0, 0, 0, 3955, 3841, 0, 0, 0, 0, 0, 0, 696, 0, 4815, 1719, 1360, 0, 0, 0, 0, 2534, 0, 0, 0, 4913, 0, 176, 429, 0, 0, 706, 0, 0, 0, 0, 2695, 0, 0, 2087, 0, 0, 0, 0, 0, 2090, 4903, 0, 449, 0, 532, 2772, 2689, 2553, 546, 0, 0, 3667, 550, 2040, 1078, 0, 4783, 0, 2816, 0, 2187, 445, 0, 2211, 4122, 0, 3225, 2988, 11, 0, 4156, 415, 0, 0, 1087, 0, 904, 0, 0, 0, 0, 0, 1665, 3555, 86, 0, 0, 0, 294, 0, 0, 0, 0, 1582, 0, 4894, 4792, 0, 0, 0, 4837, 0, 0, 0, 0, 4463, 4169, 0, 0, 0, 0, 0, 0, 0, 3724, 1838, 0, 0, 3504, 0, 2639, 0, 496, 0, 471, 0, 0, 0, 0, 4362, 0, 0, 0, 0, 0, 4574, 0, 469, 1590, 0, 2125, 0, 0, 0, 0, 0, 0, 0, 0, 2097, 0, 0, 0, 1343, 0, 3862, 0, 2855, 62, 192, 0, 0, 0, 0, 3425, 0, 2583, 0, 2740, 2418, 0, 2920, 0, 1325, 1666, 0, 0, 0, 4584, 1795, 1040, 0, 0, 0, 0, 2636, 0, 0, 0, 4358, 3269, 2077, 0, 0, 2071, 0, 496, 0, 3, 0, 1434, 0, 0, 4591, 0, 0, 0, 0, 2561, 0, 0, 0, 0, 1458, 0, 4581, 4351, 1986, 0, 0, 0, 0, 3338, 0, 3720, 2562, 0, 4216, 0, 0, 0, 482, 2481, 0, 0, 4467, 4579, 4812, 0, 1773, 0, 4277, 2263, 0, 4651, 0, 4655, 0, 0, 0, 4588, 0, 0, 406, 0, 0, 237, 857, 795, 0, 0, 0, 3342, 0, 0, 0, 3126, 223, 2255, 740, 0, 1314, 0, 804, 2266, 0, 0, 2273, 1440, 0, 4449, 0, 4165, 1826, 0, 0, 3292, 0, 742, 0, 0, 1794, 1295, 0, 0, 0, 0, 0, 1014, 0, 3361, 0, 0, 0, 1893, 0, 4430, 1507, 4253, 2384, 3184, 0, 0, 3240, 0, 4032, 401, 0, 0, 779, 0, 0, 1796, 0, 0, 2630, 3896, 2394, 0, 2832, 2149, 2102, 1296, 0, 161, 0, 0, 0, 0, 0, 0, 287, 4804, 0, 0, 0, 0, 1034, 0, 4646, 0, 0, 0, 4338, 0, 0, 0, 0, 2755, 2244, 4619, 358, 710, 0, 1660, 0, 0, 4492, 4607, 4909, 0, 943, 0, 4341, 1619, 0, 0, 0, 0, 0, 2395, 0, 0, 2120, 2896, 0, 0, 1192, 0, 0, 0, 1802, 1683, 0, 0, 0, 0, 0, 0, 0, 0, 2485, 0, 3759, 0, 0, 0, 0, 0, 0, 0, 0, 3753, 4672, 0, 2386, 0, 4066, 0, 272, 292, 0, 0, 844, 0, 0, 0, 0, 0, 2814, 0, 0, 0, 2396, 2050, 0, 1469, 0, 2280, 0, 0, 1479, 0, 0, 1682, 4018, 0, 0, 2718, 0, 0, 77, 0, 3146, 0, 0, 0, 0, 2799, 0, 0, 1816, 0, 0, 0, 2512, 2277, 3526, 2387, 0, 0, 0, 0, 3122, 1912, 1270, 0, 4207, 0, 0, 2508, 2354, 0, 3100, 610, 0, 2397, 1162, 0, 0, 1157, 1819, 3292, 0, 0, 0, 3788, 0, 163, 0, 170, 0, 0, 0, 0, 1946, 0, 2927, 1002, 4861, 1985, 0, 1922, 1586, 0, 1483, 0, 0, 2357, 3033, 0, 4289, 0, 133, 0, 0, 0, 1262, 2637, 0, 4716, 2705, 136, 745, 0, 0, 4146, 1142, 1312, 4412, 866, 0, 0, 3726, 0, 0, 568, 0, 2349, 1146, 0, 1365, 166, 2594, 0, 0, 0, 4689, 3723, 1008, 4470, 2333, 0, 1469, 0, 0, 1527, 0, 0, 0, 1718, 0, 0, 0, 2389, 0, 1117, 3023, 3477, 6, 1674, 2404, 1151, 0, 2245, 3237, 0, 3655, 2601, 4787, 0, 0, 2399, 2519, 3478, 0, 0, 2089, 0, 3753, 0, 2637, 0, 3388, 0, 0, 4908, 49, 0, 1715, 0, 0, 0, 0, 0, 0, 0, 0, 1678, 0, 0, 342, 0, 0, 2790, 2118, 0, 0, 0, 0, 2565, 0, 0, 0, 0, 0, 0, 0, 4270, 0, 0, 0, 0, 724, 0, 1320, 0, 3199, 0, 0, 1783, 2298, 0, 368, 0, 3090, 0, 0, 4096, 1680, 0, 2875, 446, 4493, 156, 3797, 4349, 0, 3326, 0, 0, 0, 0, 3846, 2202, 210, 0, 0, 0, 277, 0, 1861, 613, 743, 1530, 0, 1737, 0, 2599, 4883, 0, 3706, 0, 3205, 0, 0, 0, 3340, 3862, 0, 4457, 1442, 0, 2429, 0, 0, 0, 4914, 1657, 0, 1857, 0, 0, 0, 0, 0, 0, 0, 0, 2564, 0, 1804, 1063, 0, 0, 0, 2879, 0, 1738, 139, 0, 0, 804, 0, 0, 0, 0, 0, 0, 0, 2164, 0, 0, 0, 0, 2450, 0, 1000, 1399, 0, 1471, 0, 2248, 0, 2906, 3095, 0, 2463, 0, 2546, 0, 918, 0, 0, 0, 0, 274, 1484, 788, 0, 3897, 0, 13, 0, 0, 0, 2224, 0, 2086, 0, 0, 0, 0, 0, 4714, 0, 0, 3213, 0, 0, 0, 0, 2810, 4344, 3009, 1569, 0, 3446, 296, 1550, 2617, 1428, 391, 0, 0, 667, 4321, 3431, 0, 4840, 0, 4726, 0, 645, 0, 0, 0, 0, 4082, 2310, 0, 2233, 0, 0, 4043, 1120, 3165, 0, 0, 0, 0, 0, 523, 0, 3327, 0, 2281, 8, 1823, 0, 1514, 4675, 0, 0, 0, 0, 0, 337, 0, 3414, 3964, 2608, 2034, 0, 0, 0, 0, 0, 1987, 1882, 1499, 1759, 996, 2302, 2328, 1708, 973, 890, 3200, 0, 801, 0, 0, 0, 0, 0, 4114, 1668, 0, 3791, 3285, 1634, 4789, 1397, 2025, 3761, 3748, 2442, 1877, 0, 0, 0, 0, 0, 0, 0, 0, 4694, 1379, 0, 3103, 2874, 0, 2030, 0, 2946, 0, 1865, 1843, 801, 0, 0, 3897, 1114, 3567, 0, 0, 0, 867, 3641, 553, 0, 0, 0, 1132, 1011, 954, 0, 3847, 0, 1135, 3528, 3898, 3777, 3606, 0, 1379, 0, 538, 1753, 0, 783, 0, 0, 0, 0, 1000, 0, 0, 2264, 0, 0, 4467, 0, 0, 0, 0, 2710, 0, 0, 1164, 0, 0, 0, 1670, 0, 0, 0, 0, 0, 0, 1724, 2236, 0, 0, 0, 0, 4702, 3698, 2236, 0, 0, 2276, 0, 4637, 0, 3899, 0, 4125, 4519, 0, 2881, 0, 0, 0, 1835, 0, 0, 0, 0, 0, 1181, 0, 4668, 0, 2446, 0, 753, 1019, 70, 2521, 186, 0, 0, 4683, 4295, 1701, 1999, 0, 0, 0, 0, 0, 1994, 981, 0, 0, 1217, 0, 797, 0, 0, 4031, 0, 0, 1062, 3532, 1185, 0, 0, 2950, 2337, 0, 45, 861, 4822, 2147, 1870, 241, 0, 0, 0, 573, 0, 3683, 3791, 979, 0, 756, 0, 2575, 0, 0, 0, 1638, 4188, 3250, 0, 0, 0, 0, 0, 0, 3865, 2582, 4276, 1381, 1405, 0, 0, 0, 2590, 0, 3524, 464, 0, 0, 0, 3697, 1988, 1579, 1868, 52, 2462, 0, 2068, 0, 2059, 0, 1453, 0, 0, 0, 3850, 4175, 3935, 2235, 0, 1084, 2238, 2530, 0, 4427, 0, 0, 0, 66, 0, 3156, 0, 4473, 974, 0, 0, 1565, 0, 3838, 0, 0, 0, 4545, 1125, 1759, 4686, 3850, 265, 0, 3349, 0, 0, 4419, 3560, 0, 2316, 2814, 0, 1357, 0, 2648, 0, 0, 732, 0, 0, 0, 0, 616, 4461, 710, 314, 401, 0, 0, 0, 0, 0, 0, 0, 4902, 0, 0, 3898, 0, 1461, 0, 0, 0, 0, 0, 290, 0, 0, 4529, 0, 0, 0, 0, 0, 0, 4530, 1354, 0, 3807, 0, 2217, 103, 0, 0, 1881, 0, 0, 2487, 0, 1289, 0, 0, 4001, 0, 4667, 709, 0, 2086, 0, 0, 0, 3275, 0, 2158, 0, 143, 0, 975, 1058, 4572, 2284, 1157, 0, 0, 662, 3135, 4708, 0, 4263, 1062, 0, 2406, 2438, 2467, 1664, 0, 59, 0, 1143, 2674, 3086, 0, 2964, 3262, 44, 818, 2727, 0, 3785, 0, 579, 4635, 0, 1159, 0, 0, 74, 201, 0, 1100, 4313, 1455, 4208, 4170, 0, 1457, 637, 3437, 0, 1055, 2052, 1035, 371, 0, 0, 0, 2794, 0, 0, 3903, 1530, 1945, 0, 1611, 1360, 0, 1245, 0, 4664, 0, 2343, 0, 0, 2012, 0, 0, 0, 2267, 0, 248, 663, 0, 0, 3730, 0, 2495, 0, 0, 384, 0, 0, 1957, 330, 4172, 0, 324, 0, 1466, 3294, 0, 0, 0, 0, 0, 0, 0, 3975, 718, 0, 3651, 2795, 0, 1092, 0, 4194, 0, 433, 0, 1662, 0, 0, 663, 882, 0, 204, 0, 0, 0, 0, 197, 4190, 1750, 3807, 0, 2282, 849, 0, 439, 0, 1822, 2924, 0, 4561, 597, 1308, 4260, 524, 3068, 332, 0, 0, 4338, 626, 0, 4358, 0, 835, 1932, 0, 405, 3420, 1803, 0, 1320, 985, 0, 0, 0, 0, 2143, 2725, 0, 3100, 0, 0, 2384, 1716, 771, 1402, 0, 627, 3264, 0, 0, 594, 0, 0, 54, 1626, 0, 682, 4069, 0, 0, 0, 0, 1751, 0, 2504, 2900, 0, 2009, 4203, 56, 2562, 4533, 0, 2083, 0, 0, 4365, 4305, 0, 2597, 0, 4504, 0, 3985, 0, 2172, 0, 4323, 0, 127, 129, 2258, 873, 0, 2417, 800, 1814, 2719, 1813, 0, 4440, 0, 139, 4883, 2603, 0, 2511, 0, 1610, 137, 578, 0, 1440, 1656, 0, 992, 0, 2133, 0, 1611, 113, 0, 0, 1628, 0, 1598, 1019, 4368, 0, 1854, 2894, 0, 910, 0, 0, 1695, 1915, 4900, 1913, 3048, 0, 1970, 0, 925, 4324, 0, 0, 2011, 452, 0, 2982, 0, 686, 4059, 0, 4532, 0, 2454, 1889, 1578, 1231, 0, 0, 3637, 0, 1628, 0, 414, 0, 0, 3798, 3280, 448, 599, 3863, 0, 0, 0, 0, 0, 178, 2533, 0, 0, 0, 0, 4594, 0, 1955, 4934, 2569, 4523, 1027, 3711, 396, 2136, 0, 0, 0, 0, 0, 2520, 0, 2243, 369, 3757, 3204, 0, 0, 4617, 0, 0, 0, 0, 0, 0, 0, 0, 1930, 0, 0, 0, 0, 4919, 0, 0, 4126, 1143, 0, 442, 589, 0, 0, 682, 0, 131, 0, 3477, 0, 2125, 0, 76, 4317, 0, 0, 0, 0, 1953, 684, 0, 2425, 0, 2465, 4935, 4371, 4935, 0, 0, 0, 1201, 2452, 1441, 4474, 0, 3908, 46, 915, 0, 513, 2210, 0, 0, 177, 2305, 0, 1137, 4808, 848, 540, 3942, 1116, 0, 386, 1041, 4440, 444, 0, 0, 0, 0, 0, 3062, 3956, 1534, 0, 0, 3760, 0, 4639, 3635, 619, 4392, 957, 2240, 0, 435, 118, 0, 264, 0, 1989, 0, 1321, 0, 0, 1224, 0, 1538, 152, 4844, 0, 0, 2383, 1664, 0, 2487, 0, 0, 0, 0, 0, 1949, 2103, 150, 0, 753, 3607, 0, 1929, 0, 0, 4510, 0, 2309, 1909, 123, 3472, 0, 3871, 0, 0, 0, 0, 0, 764, 2749, 0, 0, 3187, 3838, 214, 0, 0, 0, 0, 1401, 0, 3652, 544, 574, 1119, 976, 2354, 0, 4827, 0, 188, 0, 0, 0, 2509, 0, 4031, 287, 1686, 0, 3359, 3227, 0, 0, 1217, 1444, 4438, 825, 0, 0, 0, 0, 2265, 0, 1871, 4727, 0, 0, 1387, 103, 2320, 1524, 3699, 1507, 960, 158, 0, 0, 0, 0, 1787, 0, 0, 0, 0, 3404, 0, 1444, 928, 0, 2663, 0, 3493, 2541, 1264, 0, 325, 1846, 4577, 0, 0, 2641, 4745, 2311, 0, 1750, 0, 2521, 0, 141, 1506, 1637, 1583, 410, 0, 0, 0, 4681, 1687, 758, 0, 1886, 1759, 0, 800, 0, 0, 458, 0, 32, 502, 0, 0, 1871, 1745, 2534, 552, 2879, 0, 3631, 1897, 4667, 0, 0, 0, 3926, 0, 2084, 0, 508, 0, 1087, 689, 1981, 4722, 4681, 0, 953, 19, 2037, 0, 1529, 2385, 0, 1172, 856, 0, 203, 3268, 623, 2138, 0, 1457, 0, 0, 0, 0, 277, 0, 0, 0, 4724, 0, 3474, 0, 794, 0, 0, 2299, 0, 1187, 4862, 0, 2096, 2836, 0, 4797, 0, 0, 0, 1941, 2271, 0, 1158, 1271, 4582, 0, 4685, 71, 2253, 0, 0, 3886, 3667, 1248, 3780, 1392, 2835, 376, 0, 1580, 1184, 0, 0, 4300, 0, 0, 587, 2161, 2203, 3284, 2323, 0, 0, 0, 0, 1595, 0, 0, 3995, 3058, 0, 0, 804, 444, 2570, 1610, 3754, 0, 66, 296, 0, 3357, 4333, 30, 2078, 83, 2691, 0, 2917, 0, 608, 0, 2475, 0, 3621, 0, 1652, 2170, 0, 0, 1783, 3290, 5, 0, 0, 3678, 2153, 0, 1940, 42, 1183, 2249, 745, 0, 0, 2504, 0, 0, 2217, 0, 0, 1770, 1143, 1850, 2728, 3590, 0, 1502, 0, 1390, 1036, 3869, 3314, 3852, 0, 0, 2292, 3594, 0, 3607, 266, 1347, 0, 139, 0, 858, 112, 3991, 0, 0, 506, 0, 0, 0, 1821, 4481, 81, 0, 0, 127, 1494, 0, 3196, 0, 0, 0, 3856, 0, 1374, 99, 0, 0, 3464, 2857, 0, 2746, 0, 705, 0, 4276, 3525, 0, 0, 3395, 4078, 0, 133, 773, 94, 0, 991, 2372, 3178, 676, 311, 3737, 0, 3024, 1076, 1727, 1687, 0, 1009, 223, 0, 1444, 812, 0, 0, 0, 3793, 0, 3890, 0, 2, 3809, 0, 1830, 1598, 0, 0, 2205, 2262, 0, 1964, 1483, 0, 0, 0, 0, 0, 0, 0, 0, 4074, 1516, 2122, 1769, 0, 0, 689, 747, 0, 1361, 0, 0, 4623, 1733, 3780, 0, 0, 0, 0, 2373, 0, 3122, 3106, 228, 0, 1139, 1716, 2312, 2268, 0, 1145, 148, 0, 0, 81, 3, 193, 1195, 0, 2759, 3471, 2968, 969, 557, 1511, 3195, 0, 2382, 2614, 115, 516, 0, 2912, 4914, 1158, 0, 2099, 0, 0, 0, 0, 0, 3567, 0, 4807, 2933, 1515, 0, 0, 0, 814, 592, 0, 4919, 1496, 1048, 861, 2711, 0, 0, 1221, 1438, 0, 0, 199, 4586, 0, 0, 3783, 1165, 34, 0, 0, 709, 2968, 0, 683, 1203, 0, 576, 1098, 0, 0, 3627, 0, 0, 0, 1396, 0, 4015, 2026, 159, 1776, 1991, 1348, 0, 56, 2345, 0, 649, 140, 0, 1124, 0, 4455, 0, 1371, 3622, 0, 0, 2153, 0, 0, 59, 0, 0, 2568, 2191, 3047, 0, 530, 3185, 0, 862, 0, 3182, 0, 0, 0, 4327, 2321, 0, 2378, 4836, 4807, 0, 1256, 0, 4361, 1367, 2828, 0, 0, 0, 0, 3689, 0, 2410, 0, 0, 1913, 0, 1293, 3957, 0, 0, 68, 4354, 0, 826, 4216, 255, 876, 0, 2180, 4180, 0, 0, 0, 151, 4128, 741, 0, 0, 0, 0, 189, 229, 1518, 2010, 2929, 0, 0, 2670, 212, 0, 3266, 1143, 0, 1854, 0, 661, 179, 1403, 3216, 0, 0, 0, 659, 0, 0, 0, 0, 0, 1820, 1818, 0, 3381, 4581, 848, 0, 1835, 852, 0, 1697, 151, 3794, 1198, 0, 2660, 0, 3106, 0, 0, 1286, 0, 0, 1078, 4769, 1421, 0, 4920, 0, 0, 845, 4412, 1806, 3839, 469, 4654, 0, 126, 0, 0, 0, 913, 126, 0, 4442, 0, 506, 2314, 0, 0, 0, 740, 0, 1731, 0, 173, 678, 700, 3018, 14, 4555, 1334, 0, 2320, 697, 0, 0, 0, 0, 3963, 0, 0, 0, 0, 0, 206, 408, 0, 4750, 0, 2490, 0, 0, 238, 0, 3632, 885, 1512, 0, 1650, 0, 514, 0, 0, 2456, 0, 3943, 1557, 2497, 2800, 0, 0, 618, 0, 0, 0, 0, 2278, 2364, 0, 0, 1407, 1717, 1410, 0, 1033, 0, 0, 0, 1627, 0, 0, 2633, 0, 4214, 1058, 0, 3662, 1332, 702, 1592, 0, 62, 0, 0, 0, 0, 2440, 0, 1875, 423, 1085, 0, 1732, 2553, 2605, 3222, 1924, 1426, 620, 1257, 3628, 1786, 0, 0, 0, 0, 2038, 1282, 2782, 2958, 1112, 2583, 0, 0, 0, 4316, 0, 4485, 2315, 0, 0, 2153, 3794, 125, 851, 1189, 1743, 422, 4278, 0, 2120, 0, 0, 20, 0, 665, 1168, 0, 2627, 922, 2417, 895, 0, 2324, 3781, 0, 204, 1825, 4729, 0, 0, 2184, 1457, 0, 0, 1273, 0, 1155, 0, 3519, 1922, 1134, 874, 0, 3919, 0, 3857, 2508, 674, 0, 1391, 0, 0, 4827, 0, 4001, 0, 0, 0, 2112, 954, 0, 4809, 1945, 771, 572, 1518, 1368, 1388, 861, 4541, 0, 4477, 154, 0, 1160, 4276, 0, 0, 1307, 1877, 0, 1951, 647, 2541, 3442, 236, 1609, 1237, 1971, 0, 0, 193, 935, 3610, 0, 4382, 0, 0, 1855, 0, 0, 156, 3850, 0, 2771, 0, 1302, 0, 3743, 0, 2985, 0, 1091, 0, 0, 0, 2769, 834, 1380, 2316, 0, 0, 0, 1497, 1190, 0, 3931, 3254, 1788, 0, 1180, 636, 4888, 1076, 4163, 3454, 2024, 1017, 2432, 0, 0, 0, 1501, 1184, 0, 2063, 2655, 0, 0, 0, 725, 2187, 0, 1422, 0, 0, 728, 3000, 3962, 0, 4293, 0, 0, 2206, 3011, 2216, 0, 3572, 4212, 0, 1132, 605, 2493, 0, 0, 0, 0, 145, 3155, 466, 868, 0, 2104, 366, 675, 3235, 0, 0, 0, 2879, 0, 0, 830, 0, 1182, 2229, 1342, 0, 0, 1413, 29, 0, 1255, 1675, 0, 819, 98, 3384, 3546, 0, 0, 0, 0, 1917, 3070, 2773, 372, 4271, 3947, 4315, 0, 1730, 671, 0, 0, 0, 311, 1660, 1849, 4084, 977, 2277, 1715, 0, 1893, 0, 448, 0, 0, 765, 2577, 227, 2401, 0, 0, 2624, 0, 0, 4420, 0, 0, 0, 0, 1200, 0, 575, 0, 245, 0, 2385, 1661, 943, 2947, 0, 266, 892, 3187, 4109, 2243, 682, 0, 3474, 0, 1398, 0, 2210, 3605, 4936, 0, 0, 2349, 0, 3795, 157, 3256, 2404, 0, 0, 0, 3778, 0, 43, 1006, 3081, 0, 4677, 992, 0, 0, 422, 0, 3258, 0, 343, 3408, 519, 796, 4536, 0, 0, 1123, 4373, 0, 1772, 0, 1546, 604, 1752, 1703, 0, 2095, 4752, 2460, 0, 3678, 0, 677, 0, 0, 1639, 0, 0, 541, 2743, 1563, 878, 121, 0, 0, 1212, 886, 0, 3073, 77, 0, 0, 1905, 0, 4094, 0, 1241, 0, 0, 893, 640, 1474, 3450, 0, 0, 408, 4772, 0, 528, 2318, 0, 1618, 3684, 3920, 4790, 0, 1448, 1947, 903, 0, 0, 4624, 451, 0, 1016, 92, 359, 1062, 0, 2098, 0, 2238, 1130, 0, 3245, 0, 994, 0, 0, 375, 4126, 1287, 1804, 1178, 4427, 3093, 0, 577, 2543, 4377, 0, 0, 0, 3971, 1585, 4719, 0, 2146, 4488, 2476, 498, 1884, 154, 0, 0, 664, 3161, 313, 0, 0, 1709, 1290, 0, 2263, 0, 1826, 0, 596, 782, 3937, 2057, 4181, 0, 0, 0, 0, 0, 894, 0, 2048, 762, 1188, 548, 0, 0, 4012, 0, 0, 0, 2446, 0, 3671, 2008, 367, 0, 799, 904, 1062, 0, 328, 271, 4211, 1303, 0, 0, 0, 4326, 0, 0, 1717, 0, 0, 0, 0, 3558, 1287, 2479, 2253, 1514, 0, 0, 1913, 1335, 4257, 726, 4529, 0, 0, 626, 2243, 397, 0, 2245, 4017, 3180, 0, 258, 3893, 4084, 0, 0, 610, 4566, 0, 0, 4596, 3765, 822, 3479, 616, 0, 4021, 0, 0, 0, 715, 1681, 0, 2679, 0, 3492, 2342, 792, 4938, 0, 3149, 0, 177, 3297, 312, 2715, 0, 2243, 1841, 0, 1909, 0, 1996, 0, 433, 0, 0, 2591, 399, 945, 2255, 2324, 0, 2332, 2656, 1151, 4574, 2619, 1625, 1914, 0, 251, 0, 321, 0, 0, 294, 4736, 915, 0, 451, 0, 0, 4131, 2536, 2072, 0, 4496, 0, 759, 1212, 0, 3896, 521, 4808, 2513, 0, 0, 1616, 0, 1017, 764, 0, 2297, 0, 0, 1488, 3764, 94, 0, 0, 263, 3903, 1576, 998, 0, 1324, 2000, 1980, 0, 0, 0, 4649, 2612, 0, 0, 0, 2057, 896, 0, 1561, 1105, 995, 0, 0, 1002, 215, 3602, 4569, 0, 817, 2620, 1787, 1147, 843, 4813, 0, 3210, 415, 4866, 1891, 1843, 336, 1231, 184, 0, 1535, 3928, 2065, 2202, 0, 1246, 463, 2028, 3476, 4591, 2135, 0, 4228, 0, 2171, 3118, 2453, 2792, 0, 471, 0, 0, 3886, 2341, 0, 0, 763, 0, 0, 3663, 1488, 2802, 0, 2336, 4311, 2283, 0, 0, 0, 2210, 983, 0, 0, 2548, 1067, 0, 4704, 4191, 0, 2192, 2078, 918, 0, 0, 3088, 0, 405, 0, 1014, 188, 897, 95, 0, 1375, 1956, 2261, 4135, 336, 151, 3983, 612, 0, 3703, 0, 0, 0, 2289, 0, 0, 4416, 1234, 2080, 1618, 467, 1897, 2422, 2176, 333, 0, 0, 1621, 2494, 1738, 1944, 3242, 0, 479, 1612, 3789, 4909, 622, 0, 0, 0, 342, 3409, 0, 0, 3800, 1013, 1086, 752, 0, 352, 0, 0, 1589, 2987, 202, 0, 0, 1523, 646, 657, 0, 4072, 0, 4270, 0, 0, 4558, 3385, 0, 0, 888, 1874, 0, 254, 0, 0, 4320, 0, 0, 0, 1671, 3356, 1069, 3016, 2549, 2374, 491, 0, 0, 2323, 1611, 1195, 4672, 0, 4510, 702, 469, 0, 0, 2569, 2413, 4335, 4435, 1402, 292, 2365, 96, 2264, 80, 4673, 1227, 2864, 0, 3677, 2222, 3595, 0, 1937, 829, 405, 1566, 0, 3595, 0, 1651, 1795, 0, 0, 2700, 0, 0, 3936, 4469, 0, 677, 3410, 511, 0, 0, 0, 4843, 0, 100, 0, 1305, 0, 0, 825, 351, 2018, 2427, 0, 0, 434, 1896, 0, 0, 358, 0, 1245, 0, 1773, 0, 57, 441, 0, 2294, 2559, 2355, 2111, 2366, 0, 899, 95, 0, 0, 427, 3188, 678, 0, 1115, 0, 3646, 1080, 950, 4290, 3863, 4460, 0, 3962, 381, 1233, 2152, 2670, 523, 898, 0, 3768, 2188, 1007, 3176, 272, 1316, 0, 1047, 1219, 0, 4825, 3832, 3396, 919, 0, 0, 449, 422, 4455, 1778, 0, 0, 0, 27, 443, 18, 0, 0, 0, 1287, 0, 4056, 0, 1710, 1552, 0, 4452, 232, 2367, 1418, 0, 3034, 0, 0, 4095, 0, 1738, 2599, 0, 2880, 0, 0, 3131, 1326, 291, 2587, 2423, 1693, 2654, 570, 0, 0, 0, 900, 3427, 4219, 448, 252, 4769, 161, 2449, 4902, 0, 0, 3310, 0, 4131, 2206, 90, 2301, 4257, 4297, 910, 0, 3683, 1501, 0, 905, 0, 0, 4159, 0, 3280, 4398, 4339, 0, 976, 1863, 308, 0, 763, 0, 0, 2368, 2261, 4102, 4491, 2014, 2051, 4719, 1962, 0, 0, 0, 4343, 598, 912, 0, 746, 0, 3725, 1750, 0, 393, 781, 0, 0, 4625, 396, 1258, 1950, 0, 1757, 535, 2202, 1847, 0, 0, 0, 0, 4179, 1799, 0, 3931, 0, 447, 4425, 389, 1885, 0, 1318, 901, 0, 0, 0, 1403, 0, 1478, 280, 2126, 2438, 0, 0, 2455, 1299, 2066, 1536, 694, 2369, 2645, 911, 419, 4904, 2796, 3398, 4058, 3423, 0, 860, 408, 1382, 3518, 398, 1274, 0, 902, 4078, 0, 0, 0, 2115, 0, 0, 0, 611, 1780, 527, 0, 2461, 3891, 751, 2007, 655, 422, 0, 2410, 0, 0, 1013, 0, 1507, 369, 0, 3361, 1872, 2127, 0, 0, 1945, 2387, 966, 0, 2968, 0, 1718, 3514, 2429, 3055, 743, 0, 1300, 4315, 0, 4138, 1040, 0, 1087, 3066, 0, 0, 2698, 0, 4843, 0, 0, 660, 0, 0, 0, 0, 1852, 4747, 2532, 1140, 3055, 0, 0, 0, 912, 938, 770, 411, 4248, 0, 0, 963, 715, 2121, 0, 1958, 0, 3260, 0, 3300, 0, 4526, 0, 1991, 0, 1684, 1400, 939, 1360, 1781, 768, 2271, 4508, 414, 472, 2361, 0, 462, 913, 1908, 214, 0, 226, 428, 17, 402, 1181, 4058, 0, 0, 2028, 0, 0, 3006, 148, 2846, 0, 1632, 1979, 0, 4504, 4685, 0, 473, 3831, 0, 1793, 0, 1577, 587, 4348, 4331, 1434, 1676, 1610, 1476, 4362, 239, 0, 213, 0, 1504, 3340, 226, 0, 0, 0, 69, 4294, 0, 2202, 89, 671, 0, 210, 2533, 1184, 290, 0, 0, 2251, 0, 1008, 0, 0, 1558, 0, 669, 1919, 2905, 10, 3098, 597, 0, 0, 1765, 1508, 342, 660, 0, 1286, 4743, 1292, 149, 0, 94, 2705, 0, 3638, 74, 0, 0, 670, 1678, 110, 1916, 828, 4302, 1406, 399, 1940, 3222, 478, 918, 0, 4738, 4583, 0, 0, 3439, 900, 4706, 0, 1058, 1511, 2255, 0, 0, 2554, 1464, 0, 1840, 2533, 3190, 477, 4573, 740, 3170, 0, 1095, 0, 708, 1196, 1068, 0, 796, 0, 4750, 2538, 4753, 1607, 0, 232, 0, 4073, 1034, 0, 1537, 0, 0, 1394, 1149, 3091, 1838, 2364, 0, 4702, 3045, 1389, 4810, 3454, 3150, 0, 3056, 0, 756, 820, 0, 803, 1855, 4821, 617, 4471, 1855, 4433, 3297, 172, 0, 0, 3174, 0, 1161, 4832, 140, 0, 2095, 4484, 3256, 0, 0, 0, 2290, 1115, 1690, 0, 2631, 0, 0, 1661, 880, 4060, 3479, 0, 0, 661, 2304, 1570, 0, 1943, 0, 0, 4093, 921, 4363, 2467, 2107, 104, 0, 2797, 281, 0, 1489, 406, 0, 409, 0, 2112, 420, 1451, 0, 0, 424, 4251, 2404, 1551, 1898, 3403, 3222, 2459, 0, 0, 685, 0, 758, 0, 278, 437, 1815, 1359, 0, 0, 1140, 109, 267, 1591, 0, 0, 0, 64, 0, 0, 3718, 0, 1526, 4720, 0, 0, 0, 0, 4441, 488, 461, 0, 1854, 128, 806, 2027, 1799, 1254, 1108, 2294, 0, 0, 2184, 1566, 95, 0, 0, 1009, 0, 155, 1860, 0, 0, 0, 1823, 1763, 0, 45, 0, 0, 4622, 0, 0, 4804, 4851, 4258, 1913, 2254, 2966, 0, 665, 2082, 2131, 1548, 999, 1298, 0, 3701, 922, 12, 3468, 0, 1413, 490, 0, 211, 4799, 514, 4045, 748, 0, 428, 1480, 1968, 1923, 1233, 0, 0, 0, 1230, 0, 2343, 0, 0, 2307, 4645, 2634, 0, 0, 1208, 0, 0, 0, 0, 3100, 2380, 0, 0, 0, 257, 509, 0, 0, 768, 3941, 1608, 0, 0, 514, 0, 1608, 0, 0, 0, 0, 1229, 0, 1464, 4061, 323, 778, 2219, 620, 0, 2447, 0, 0, 0, 4113, 3795, 0, 0, 0, 0, 1859, 0, 0, 1802, 0, 24, 0, 2846, 0, 4594, 670, 3070, 1854, 214, 0, 1665, 28, 0, 0, 0, 3515, 486, 3974, 2454, 839, 2272, 2381, 1839, 1731, 0, 170, 726, 2776, 4774, 0, 2716, 3591, 0, 2746, 2718, 1350, 0, 4693, 0, 0, 614, 2873, 1565, 0, 1913, 516, 4607, 1343, 554, 2275, 0, 0, 629, 0, 2067, 0, 3895, 1260, 0, 0, 4502, 0, 3928, 2142, 533, 0, 2616, 0, 0, 2392, 2284, 1828, 2419, 1136, 2611, 0, 63, 84, 1745, 0, 0, 3358, 4114, 0, 4776, 502, 2734, 0, 84, 1861, 4483, 1111, 1900, 1541, 877, 0, 0, 1447, 0, 3242, 0, 0, 0, 0, 0, 3233, 2292, 323, 3614, 3874, 1841, 0, 1285, 0, 2075, 781, 1311, 0, 0, 4749, 3633, 0, 0, 1378, 983, 4392, 0, 0, 1463, 2594, 0, 44, 0, 868, 127, 2153, 1459, 0, 40, 0, 2452, 3543, 2961, 3474, 3459, 205, 4208, 4532, 0, 4121, 1604, 2146, 2682, 0, 0, 90, 2437, 2621, 7, 485, 0, 744, 0, 3874, 2149, 0, 4119, 1716, 3998, 0, 0, 186, 565, 549, 174, 4228, 0 }; static size_t keysym_name_hash_f(const char *key, const char *T) { size_t sum = 0; for (size_t i = 0; key[i] != '\0'; i++) sum += (size_t) (T[i % 32] * key[i]); return sum % 4943; } static inline size_t keysym_name_perfect_hash(const char *key) { return ( keysym_name_G[keysym_name_hash_f(key, "7kXa2psFk0A5Amiu6ABFLT7YNEfwew7F")] + keysym_name_G[keysym_name_hash_f(key, "pJPSPjKmzG50RhZM508VMuIZdLLmwnVm")] ) % 4943; } struct name_keysym { xkb_keysym_t keysym; uint16_t offset; }; static const struct name_keysym name_to_keysym[] = { { 0x00000030, 0 }, /* 0 */ { 0x00000031, 2 }, /* 1 */ { 0x00000032, 4 }, /* 2 */ { 0x00000033, 6 }, /* 3 */ { 0x0000fd10, 8 }, /* 3270_AltCursor */ { 0x0000fd0e, 23 }, /* 3270_Attn */ { 0x0000fd05, 33 }, /* 3270_BackTab */ { 0x0000fd19, 46 }, /* 3270_ChangeScreen */ { 0x0000fd15, 64 }, /* 3270_Copy */ { 0x0000fd0f, 74 }, /* 3270_CursorBlink */ { 0x0000fd1c, 91 }, /* 3270_CursorSelect */ { 0x0000fd1a, 109 }, /* 3270_DeleteWord */ { 0x0000fd01, 125 }, /* 3270_Duplicate */ { 0x0000fd1e, 140 }, /* 3270_Enter */ { 0x0000fd06, 151 }, /* 3270_EraseEOF */ { 0x0000fd07, 165 }, /* 3270_EraseInput */ { 0x0000fd1b, 181 }, /* 3270_ExSelect */ { 0x0000fd02, 195 }, /* 3270_FieldMark */ { 0x0000fd13, 210 }, /* 3270_Ident */ { 0x0000fd12, 221 }, /* 3270_Jump */ { 0x0000fd11, 231 }, /* 3270_KeyClick */ { 0x0000fd04, 245 }, /* 3270_Left2 */ { 0x0000fd0a, 256 }, /* 3270_PA1 */ { 0x0000fd0b, 265 }, /* 3270_PA2 */ { 0x0000fd0c, 274 }, /* 3270_PA3 */ { 0x0000fd16, 283 }, /* 3270_Play */ { 0x0000fd1d, 293 }, /* 3270_PrintScreen */ { 0x0000fd09, 310 }, /* 3270_Quit */ { 0x0000fd18, 320 }, /* 3270_Record */ { 0x0000fd08, 332 }, /* 3270_Reset */ { 0x0000fd03, 343 }, /* 3270_Right2 */ { 0x0000fd14, 355 }, /* 3270_Rule */ { 0x0000fd17, 365 }, /* 3270_Setup */ { 0x0000fd0d, 376 }, /* 3270_Test */ { 0x00000034, 386 }, /* 4 */ { 0x00000035, 388 }, /* 5 */ { 0x00000036, 390 }, /* 6 */ { 0x00000037, 392 }, /* 7 */ { 0x00000038, 394 }, /* 8 */ { 0x00000039, 396 }, /* 9 */ { 0x00000041, 398 }, /* A */ { 0x00000061, 400 }, /* a */ { 0x000000c1, 402 }, /* Aacute */ { 0x000000e1, 409 }, /* aacute */ { 0x01001ea0, 416 }, /* Abelowdot */ { 0x01001ea1, 426 }, /* abelowdot */ { 0x000001ff, 436 }, /* abovedot */ { 0x000001c3, 445 }, /* Abreve */ { 0x000001e3, 452 }, /* abreve */ { 0x01001eae, 459 }, /* Abreveacute */ { 0x01001eaf, 471 }, /* abreveacute */ { 0x01001eb6, 483 }, /* Abrevebelowdot */ { 0x01001eb7, 498 }, /* abrevebelowdot */ { 0x01001eb0, 513 }, /* Abrevegrave */ { 0x01001eb1, 525 }, /* abrevegrave */ { 0x01001eb2, 537 }, /* Abrevehook */ { 0x01001eb3, 548 }, /* abrevehook */ { 0x01001eb4, 559 }, /* Abrevetilde */ { 0x01001eb5, 571 }, /* abrevetilde */ { 0x0000fe70, 583 }, /* AccessX_Enable */ { 0x0000fe71, 598 }, /* AccessX_Feedback_Enable */ { 0x000000c2, 622 }, /* Acircumflex */ { 0x000000e2, 634 }, /* acircumflex */ { 0x01001ea4, 646 }, /* Acircumflexacute */ { 0x01001ea5, 663 }, /* acircumflexacute */ { 0x01001eac, 680 }, /* Acircumflexbelowdot */ { 0x01001ead, 700 }, /* acircumflexbelowdot */ { 0x01001ea6, 720 }, /* Acircumflexgrave */ { 0x01001ea7, 737 }, /* acircumflexgrave */ { 0x01001ea8, 754 }, /* Acircumflexhook */ { 0x01001ea9, 770 }, /* acircumflexhook */ { 0x01001eaa, 786 }, /* Acircumflextilde */ { 0x01001eab, 803 }, /* acircumflextilde */ { 0x000000b4, 820 }, /* acute */ { 0x000000c4, 826 }, /* Adiaeresis */ { 0x000000e4, 837 }, /* adiaeresis */ { 0x000000c6, 848 }, /* AE */ { 0x000000e6, 851 }, /* ae */ { 0x000000c0, 854 }, /* Agrave */ { 0x000000e0, 861 }, /* agrave */ { 0x01001ea2, 868 }, /* Ahook */ { 0x01001ea3, 874 }, /* ahook */ { 0x0000ffe9, 880 }, /* Alt_L */ { 0x0000ffea, 886 }, /* Alt_R */ { 0x000003c0, 892 }, /* Amacron */ { 0x000003e0, 900 }, /* amacron */ { 0x00000026, 908 }, /* ampersand */ { 0x000001a1, 918 }, /* Aogonek */ { 0x000001b1, 926 }, /* aogonek */ { 0x00000027, 934 }, /* apostrophe */ { 0x01002248, 945 }, /* approxeq */ { 0x000008c8, 954 }, /* approximate */ { 0x01000660, 966 }, /* Arabic_0 */ { 0x01000661, 975 }, /* Arabic_1 */ { 0x01000662, 984 }, /* Arabic_2 */ { 0x01000663, 993 }, /* Arabic_3 */ { 0x01000664, 1002 }, /* Arabic_4 */ { 0x01000665, 1011 }, /* Arabic_5 */ { 0x01000666, 1020 }, /* Arabic_6 */ { 0x01000667, 1029 }, /* Arabic_7 */ { 0x01000668, 1038 }, /* Arabic_8 */ { 0x01000669, 1047 }, /* Arabic_9 */ { 0x000005d9, 1056 }, /* Arabic_ain */ { 0x000005c7, 1067 }, /* Arabic_alef */ { 0x000005e9, 1079 }, /* Arabic_alefmaksura */ { 0x000005c8, 1098 }, /* Arabic_beh */ { 0x000005ac, 1109 }, /* Arabic_comma */ { 0x000005d6, 1122 }, /* Arabic_dad */ { 0x000005cf, 1133 }, /* Arabic_dal */ { 0x000005ef, 1144 }, /* Arabic_damma */ { 0x000005ec, 1157 }, /* Arabic_dammatan */ { 0x01000688, 1173 }, /* Arabic_ddal */ { 0x010006cc, 1185 }, /* Arabic_farsi_yeh */ { 0x000005ee, 1202 }, /* Arabic_fatha */ { 0x000005eb, 1215 }, /* Arabic_fathatan */ { 0x000005e1, 1231 }, /* Arabic_feh */ { 0x010006d4, 1242 }, /* Arabic_fullstop */ { 0x010006af, 1258 }, /* Arabic_gaf */ { 0x000005da, 1269 }, /* Arabic_ghain */ { 0x000005e7, 1282 }, /* Arabic_ha */ { 0x000005cd, 1292 }, /* Arabic_hah */ { 0x000005c1, 1303 }, /* Arabic_hamza */ { 0x01000654, 1316 }, /* Arabic_hamza_above */ { 0x01000655, 1335 }, /* Arabic_hamza_below */ { 0x000005c3, 1354 }, /* Arabic_hamzaonalef */ { 0x000005c4, 1373 }, /* Arabic_hamzaonwaw */ { 0x000005c6, 1391 }, /* Arabic_hamzaonyeh */ { 0x000005c5, 1409 }, /* Arabic_hamzaunderalef */ { 0x000005e7, 1431 }, /* Arabic_heh */ { 0x010006be, 1442 }, /* Arabic_heh_doachashmee */ { 0x010006c1, 1465 }, /* Arabic_heh_goal */ { 0x000005cc, 1481 }, /* Arabic_jeem */ { 0x01000698, 1493 }, /* Arabic_jeh */ { 0x000005e3, 1504 }, /* Arabic_kaf */ { 0x000005f0, 1515 }, /* Arabic_kasra */ { 0x000005ed, 1528 }, /* Arabic_kasratan */ { 0x010006a9, 1544 }, /* Arabic_keheh */ { 0x000005ce, 1557 }, /* Arabic_khah */ { 0x000005e4, 1569 }, /* Arabic_lam */ { 0x01000653, 1580 }, /* Arabic_madda_above */ { 0x000005c2, 1599 }, /* Arabic_maddaonalef */ { 0x000005e5, 1618 }, /* Arabic_meem */ { 0x000005e6, 1630 }, /* Arabic_noon */ { 0x010006ba, 1642 }, /* Arabic_noon_ghunna */ { 0x0100067e, 1661 }, /* Arabic_peh */ { 0x0100066a, 1672 }, /* Arabic_percent */ { 0x000005e2, 1687 }, /* Arabic_qaf */ { 0x000005bf, 1698 }, /* Arabic_question_mark */ { 0x000005d1, 1719 }, /* Arabic_ra */ { 0x01000691, 1729 }, /* Arabic_rreh */ { 0x000005d5, 1741 }, /* Arabic_sad */ { 0x000005d3, 1752 }, /* Arabic_seen */ { 0x000005bb, 1764 }, /* Arabic_semicolon */ { 0x000005f1, 1781 }, /* Arabic_shadda */ { 0x000005d4, 1795 }, /* Arabic_sheen */ { 0x000005f2, 1808 }, /* Arabic_sukun */ { 0x01000670, 1821 }, /* Arabic_superscript_alef */ { 0x0000ff7e, 1845 }, /* Arabic_switch */ { 0x000005d7, 1859 }, /* Arabic_tah */ { 0x000005e0, 1870 }, /* Arabic_tatweel */ { 0x01000686, 1885 }, /* Arabic_tcheh */ { 0x000005ca, 1898 }, /* Arabic_teh */ { 0x000005c9, 1909 }, /* Arabic_tehmarbuta */ { 0x000005d0, 1927 }, /* Arabic_thal */ { 0x000005cb, 1939 }, /* Arabic_theh */ { 0x01000679, 1951 }, /* Arabic_tteh */ { 0x010006a4, 1963 }, /* Arabic_veh */ { 0x000005e8, 1974 }, /* Arabic_waw */ { 0x000005ea, 1985 }, /* Arabic_yeh */ { 0x010006d2, 1996 }, /* Arabic_yeh_baree */ { 0x000005d8, 2013 }, /* Arabic_zah */ { 0x000005d2, 2024 }, /* Arabic_zain */ { 0x000000c5, 2036 }, /* Aring */ { 0x000000e5, 2042 }, /* aring */ { 0x0100055b, 2048 }, /* Armenian_accent */ { 0x0100055c, 2064 }, /* Armenian_amanak */ { 0x0100055a, 2080 }, /* Armenian_apostrophe */ { 0x01000538, 2100 }, /* Armenian_AT */ { 0x01000568, 2112 }, /* Armenian_at */ { 0x01000531, 2124 }, /* Armenian_AYB */ { 0x01000561, 2137 }, /* Armenian_ayb */ { 0x01000532, 2150 }, /* Armenian_BEN */ { 0x01000562, 2163 }, /* Armenian_ben */ { 0x0100055d, 2176 }, /* Armenian_but */ { 0x01000549, 2189 }, /* Armenian_CHA */ { 0x01000579, 2202 }, /* Armenian_cha */ { 0x01000534, 2215 }, /* Armenian_DA */ { 0x01000564, 2227 }, /* Armenian_da */ { 0x01000541, 2239 }, /* Armenian_DZA */ { 0x01000571, 2252 }, /* Armenian_dza */ { 0x01000537, 2265 }, /* Armenian_E */ { 0x01000567, 2276 }, /* Armenian_e */ { 0x0100055c, 2287 }, /* Armenian_exclam */ { 0x01000556, 2303 }, /* Armenian_FE */ { 0x01000586, 2315 }, /* Armenian_fe */ { 0x01000589, 2327 }, /* Armenian_full_stop */ { 0x01000542, 2346 }, /* Armenian_GHAT */ { 0x01000572, 2360 }, /* Armenian_ghat */ { 0x01000533, 2374 }, /* Armenian_GIM */ { 0x01000563, 2387 }, /* Armenian_gim */ { 0x01000545, 2400 }, /* Armenian_HI */ { 0x01000575, 2412 }, /* Armenian_hi */ { 0x01000540, 2424 }, /* Armenian_HO */ { 0x01000570, 2436 }, /* Armenian_ho */ { 0x0100058a, 2448 }, /* Armenian_hyphen */ { 0x0100053b, 2464 }, /* Armenian_INI */ { 0x0100056b, 2477 }, /* Armenian_ini */ { 0x0100054b, 2490 }, /* Armenian_JE */ { 0x0100057b, 2502 }, /* Armenian_je */ { 0x01000554, 2514 }, /* Armenian_KE */ { 0x01000584, 2526 }, /* Armenian_ke */ { 0x0100053f, 2538 }, /* Armenian_KEN */ { 0x0100056f, 2551 }, /* Armenian_ken */ { 0x0100053d, 2564 }, /* Armenian_KHE */ { 0x0100056d, 2577 }, /* Armenian_khe */ { 0x01000587, 2590 }, /* Armenian_ligature_ew */ { 0x0100053c, 2611 }, /* Armenian_LYUN */ { 0x0100056c, 2625 }, /* Armenian_lyun */ { 0x01000544, 2639 }, /* Armenian_MEN */ { 0x01000574, 2652 }, /* Armenian_men */ { 0x01000546, 2665 }, /* Armenian_NU */ { 0x01000576, 2677 }, /* Armenian_nu */ { 0x01000555, 2689 }, /* Armenian_O */ { 0x01000585, 2700 }, /* Armenian_o */ { 0x0100055e, 2711 }, /* Armenian_paruyk */ { 0x0100054a, 2727 }, /* Armenian_PE */ { 0x0100057a, 2739 }, /* Armenian_pe */ { 0x01000553, 2751 }, /* Armenian_PYUR */ { 0x01000583, 2765 }, /* Armenian_pyur */ { 0x0100055e, 2779 }, /* Armenian_question */ { 0x0100054c, 2797 }, /* Armenian_RA */ { 0x0100057c, 2809 }, /* Armenian_ra */ { 0x01000550, 2821 }, /* Armenian_RE */ { 0x01000580, 2833 }, /* Armenian_re */ { 0x0100054d, 2845 }, /* Armenian_SE */ { 0x0100057d, 2857 }, /* Armenian_se */ { 0x0100055d, 2869 }, /* Armenian_separation_mark */ { 0x01000547, 2894 }, /* Armenian_SHA */ { 0x01000577, 2907 }, /* Armenian_sha */ { 0x0100055b, 2920 }, /* Armenian_shesht */ { 0x01000543, 2936 }, /* Armenian_TCHE */ { 0x01000573, 2950 }, /* Armenian_tche */ { 0x01000539, 2964 }, /* Armenian_TO */ { 0x01000569, 2976 }, /* Armenian_to */ { 0x0100053e, 2988 }, /* Armenian_TSA */ { 0x0100056e, 3001 }, /* Armenian_tsa */ { 0x01000551, 3014 }, /* Armenian_TSO */ { 0x01000581, 3027 }, /* Armenian_tso */ { 0x0100054f, 3040 }, /* Armenian_TYUN */ { 0x0100057f, 3054 }, /* Armenian_tyun */ { 0x01000589, 3068 }, /* Armenian_verjaket */ { 0x0100054e, 3086 }, /* Armenian_VEV */ { 0x0100057e, 3099 }, /* Armenian_vev */ { 0x01000548, 3112 }, /* Armenian_VO */ { 0x01000578, 3124 }, /* Armenian_vo */ { 0x01000552, 3136 }, /* Armenian_VYUN */ { 0x01000582, 3150 }, /* Armenian_vyun */ { 0x01000535, 3164 }, /* Armenian_YECH */ { 0x01000565, 3178 }, /* Armenian_yech */ { 0x0100058a, 3192 }, /* Armenian_yentamna */ { 0x01000536, 3210 }, /* Armenian_ZA */ { 0x01000566, 3222 }, /* Armenian_za */ { 0x0100053a, 3234 }, /* Armenian_ZHE */ { 0x0100056a, 3247 }, /* Armenian_zhe */ { 0x0000005e, 3260 }, /* asciicircum */ { 0x0000007e, 3272 }, /* asciitilde */ { 0x0000002a, 3283 }, /* asterisk */ { 0x00000040, 3292 }, /* at */ { 0x000000c3, 3295 }, /* Atilde */ { 0x000000e3, 3302 }, /* atilde */ { 0x0000fe7a, 3309 }, /* AudibleBell_Enable */ { 0x00000042, 3328 }, /* B */ { 0x00000062, 3330 }, /* b */ { 0x01001e02, 3332 }, /* Babovedot */ { 0x01001e03, 3342 }, /* babovedot */ { 0x0000005c, 3352 }, /* backslash */ { 0x0000ff08, 3362 }, /* BackSpace */ { 0x1000ff74, 3372 }, /* BackTab */ { 0x00000af4, 3380 }, /* ballotcross */ { 0x0000007c, 3392 }, /* bar */ { 0x01002235, 3396 }, /* because */ { 0x0000ff58, 3404 }, /* Begin */ { 0x000009df, 3410 }, /* blank */ { 0x100000fc, 3416 }, /* block */ { 0x000008a5, 3422 }, /* botintegral */ { 0x000008ac, 3434 }, /* botleftparens */ { 0x000008a8, 3448 }, /* botleftsqbracket */ { 0x000008b2, 3465 }, /* botleftsummation */ { 0x000008ae, 3482 }, /* botrightparens */ { 0x000008aa, 3497 }, /* botrightsqbracket */ { 0x000008b6, 3515 }, /* botrightsummation */ { 0x000009f6, 3533 }, /* bott */ { 0x000008b4, 3538 }, /* botvertsummationconnector */ { 0x0000fe74, 3564 }, /* BounceKeys_Enable */ { 0x0000007b, 3582 }, /* braceleft */ { 0x0000007d, 3592 }, /* braceright */ { 0x0000005b, 3603 }, /* bracketleft */ { 0x0000005d, 3615 }, /* bracketright */ { 0x01002800, 3628 }, /* braille_blank */ { 0x0000fff1, 3642 }, /* braille_dot_1 */ { 0x0000fffa, 3656 }, /* braille_dot_10 */ { 0x0000fff2, 3671 }, /* braille_dot_2 */ { 0x0000fff3, 3685 }, /* braille_dot_3 */ { 0x0000fff4, 3699 }, /* braille_dot_4 */ { 0x0000fff5, 3713 }, /* braille_dot_5 */ { 0x0000fff6, 3727 }, /* braille_dot_6 */ { 0x0000fff7, 3741 }, /* braille_dot_7 */ { 0x0000fff8, 3755 }, /* braille_dot_8 */ { 0x0000fff9, 3769 }, /* braille_dot_9 */ { 0x01002801, 3783 }, /* braille_dots_1 */ { 0x01002803, 3798 }, /* braille_dots_12 */ { 0x01002807, 3814 }, /* braille_dots_123 */ { 0x0100280f, 3831 }, /* braille_dots_1234 */ { 0x0100281f, 3849 }, /* braille_dots_12345 */ { 0x0100283f, 3868 }, /* braille_dots_123456 */ { 0x0100287f, 3888 }, /* braille_dots_1234567 */ { 0x010028ff, 3909 }, /* braille_dots_12345678 */ { 0x010028bf, 3931 }, /* braille_dots_1234568 */ { 0x0100285f, 3952 }, /* braille_dots_123457 */ { 0x010028df, 3972 }, /* braille_dots_1234578 */ { 0x0100289f, 3993 }, /* braille_dots_123458 */ { 0x0100282f, 4013 }, /* braille_dots_12346 */ { 0x0100286f, 4032 }, /* braille_dots_123467 */ { 0x010028ef, 4052 }, /* braille_dots_1234678 */ { 0x010028af, 4073 }, /* braille_dots_123468 */ { 0x0100284f, 4093 }, /* braille_dots_12347 */ { 0x010028cf, 4112 }, /* braille_dots_123478 */ { 0x0100288f, 4132 }, /* braille_dots_12348 */ { 0x01002817, 4151 }, /* braille_dots_1235 */ { 0x01002837, 4169 }, /* braille_dots_12356 */ { 0x01002877, 4188 }, /* braille_dots_123567 */ { 0x010028f7, 4208 }, /* braille_dots_1235678 */ { 0x010028b7, 4229 }, /* braille_dots_123568 */ { 0x01002857, 4249 }, /* braille_dots_12357 */ { 0x010028d7, 4268 }, /* braille_dots_123578 */ { 0x01002897, 4288 }, /* braille_dots_12358 */ { 0x01002827, 4307 }, /* braille_dots_1236 */ { 0x01002867, 4325 }, /* braille_dots_12367 */ { 0x010028e7, 4344 }, /* braille_dots_123678 */ { 0x010028a7, 4364 }, /* braille_dots_12368 */ { 0x01002847, 4383 }, /* braille_dots_1237 */ { 0x010028c7, 4401 }, /* braille_dots_12378 */ { 0x01002887, 4420 }, /* braille_dots_1238 */ { 0x0100280b, 4438 }, /* braille_dots_124 */ { 0x0100281b, 4455 }, /* braille_dots_1245 */ { 0x0100283b, 4473 }, /* braille_dots_12456 */ { 0x0100287b, 4492 }, /* braille_dots_124567 */ { 0x010028fb, 4512 }, /* braille_dots_1245678 */ { 0x010028bb, 4533 }, /* braille_dots_124568 */ { 0x0100285b, 4553 }, /* braille_dots_12457 */ { 0x010028db, 4572 }, /* braille_dots_124578 */ { 0x0100289b, 4592 }, /* braille_dots_12458 */ { 0x0100282b, 4611 }, /* braille_dots_1246 */ { 0x0100286b, 4629 }, /* braille_dots_12467 */ { 0x010028eb, 4648 }, /* braille_dots_124678 */ { 0x010028ab, 4668 }, /* braille_dots_12468 */ { 0x0100284b, 4687 }, /* braille_dots_1247 */ { 0x010028cb, 4705 }, /* braille_dots_12478 */ { 0x0100288b, 4724 }, /* braille_dots_1248 */ { 0x01002813, 4742 }, /* braille_dots_125 */ { 0x01002833, 4759 }, /* braille_dots_1256 */ { 0x01002873, 4777 }, /* braille_dots_12567 */ { 0x010028f3, 4796 }, /* braille_dots_125678 */ { 0x010028b3, 4816 }, /* braille_dots_12568 */ { 0x01002853, 4835 }, /* braille_dots_1257 */ { 0x010028d3, 4853 }, /* braille_dots_12578 */ { 0x01002893, 4872 }, /* braille_dots_1258 */ { 0x01002823, 4890 }, /* braille_dots_126 */ { 0x01002863, 4907 }, /* braille_dots_1267 */ { 0x010028e3, 4925 }, /* braille_dots_12678 */ { 0x010028a3, 4944 }, /* braille_dots_1268 */ { 0x01002843, 4962 }, /* braille_dots_127 */ { 0x010028c3, 4979 }, /* braille_dots_1278 */ { 0x01002883, 4997 }, /* braille_dots_128 */ { 0x01002805, 5014 }, /* braille_dots_13 */ { 0x0100280d, 5030 }, /* braille_dots_134 */ { 0x0100281d, 5047 }, /* braille_dots_1345 */ { 0x0100283d, 5065 }, /* braille_dots_13456 */ { 0x0100287d, 5084 }, /* braille_dots_134567 */ { 0x010028fd, 5104 }, /* braille_dots_1345678 */ { 0x010028bd, 5125 }, /* braille_dots_134568 */ { 0x0100285d, 5145 }, /* braille_dots_13457 */ { 0x010028dd, 5164 }, /* braille_dots_134578 */ { 0x0100289d, 5184 }, /* braille_dots_13458 */ { 0x0100282d, 5203 }, /* braille_dots_1346 */ { 0x0100286d, 5221 }, /* braille_dots_13467 */ { 0x010028ed, 5240 }, /* braille_dots_134678 */ { 0x010028ad, 5260 }, /* braille_dots_13468 */ { 0x0100284d, 5279 }, /* braille_dots_1347 */ { 0x010028cd, 5297 }, /* braille_dots_13478 */ { 0x0100288d, 5316 }, /* braille_dots_1348 */ { 0x01002815, 5334 }, /* braille_dots_135 */ { 0x01002835, 5351 }, /* braille_dots_1356 */ { 0x01002875, 5369 }, /* braille_dots_13567 */ { 0x010028f5, 5388 }, /* braille_dots_135678 */ { 0x010028b5, 5408 }, /* braille_dots_13568 */ { 0x01002855, 5427 }, /* braille_dots_1357 */ { 0x010028d5, 5445 }, /* braille_dots_13578 */ { 0x01002895, 5464 }, /* braille_dots_1358 */ { 0x01002825, 5482 }, /* braille_dots_136 */ { 0x01002865, 5499 }, /* braille_dots_1367 */ { 0x010028e5, 5517 }, /* braille_dots_13678 */ { 0x010028a5, 5536 }, /* braille_dots_1368 */ { 0x01002845, 5554 }, /* braille_dots_137 */ { 0x010028c5, 5571 }, /* braille_dots_1378 */ { 0x01002885, 5589 }, /* braille_dots_138 */ { 0x01002809, 5606 }, /* braille_dots_14 */ { 0x01002819, 5622 }, /* braille_dots_145 */ { 0x01002839, 5639 }, /* braille_dots_1456 */ { 0x01002879, 5657 }, /* braille_dots_14567 */ { 0x010028f9, 5676 }, /* braille_dots_145678 */ { 0x010028b9, 5696 }, /* braille_dots_14568 */ { 0x01002859, 5715 }, /* braille_dots_1457 */ { 0x010028d9, 5733 }, /* braille_dots_14578 */ { 0x01002899, 5752 }, /* braille_dots_1458 */ { 0x01002829, 5770 }, /* braille_dots_146 */ { 0x01002869, 5787 }, /* braille_dots_1467 */ { 0x010028e9, 5805 }, /* braille_dots_14678 */ { 0x010028a9, 5824 }, /* braille_dots_1468 */ { 0x01002849, 5842 }, /* braille_dots_147 */ { 0x010028c9, 5859 }, /* braille_dots_1478 */ { 0x01002889, 5877 }, /* braille_dots_148 */ { 0x01002811, 5894 }, /* braille_dots_15 */ { 0x01002831, 5910 }, /* braille_dots_156 */ { 0x01002871, 5927 }, /* braille_dots_1567 */ { 0x010028f1, 5945 }, /* braille_dots_15678 */ { 0x010028b1, 5964 }, /* braille_dots_1568 */ { 0x01002851, 5982 }, /* braille_dots_157 */ { 0x010028d1, 5999 }, /* braille_dots_1578 */ { 0x01002891, 6017 }, /* braille_dots_158 */ { 0x01002821, 6034 }, /* braille_dots_16 */ { 0x01002861, 6050 }, /* braille_dots_167 */ { 0x010028e1, 6067 }, /* braille_dots_1678 */ { 0x010028a1, 6085 }, /* braille_dots_168 */ { 0x01002841, 6102 }, /* braille_dots_17 */ { 0x010028c1, 6118 }, /* braille_dots_178 */ { 0x01002881, 6135 }, /* braille_dots_18 */ { 0x01002802, 6151 }, /* braille_dots_2 */ { 0x01002806, 6166 }, /* braille_dots_23 */ { 0x0100280e, 6182 }, /* braille_dots_234 */ { 0x0100281e, 6199 }, /* braille_dots_2345 */ { 0x0100283e, 6217 }, /* braille_dots_23456 */ { 0x0100287e, 6236 }, /* braille_dots_234567 */ { 0x010028fe, 6256 }, /* braille_dots_2345678 */ { 0x010028be, 6277 }, /* braille_dots_234568 */ { 0x0100285e, 6297 }, /* braille_dots_23457 */ { 0x010028de, 6316 }, /* braille_dots_234578 */ { 0x0100289e, 6336 }, /* braille_dots_23458 */ { 0x0100282e, 6355 }, /* braille_dots_2346 */ { 0x0100286e, 6373 }, /* braille_dots_23467 */ { 0x010028ee, 6392 }, /* braille_dots_234678 */ { 0x010028ae, 6412 }, /* braille_dots_23468 */ { 0x0100284e, 6431 }, /* braille_dots_2347 */ { 0x010028ce, 6449 }, /* braille_dots_23478 */ { 0x0100288e, 6468 }, /* braille_dots_2348 */ { 0x01002816, 6486 }, /* braille_dots_235 */ { 0x01002836, 6503 }, /* braille_dots_2356 */ { 0x01002876, 6521 }, /* braille_dots_23567 */ { 0x010028f6, 6540 }, /* braille_dots_235678 */ { 0x010028b6, 6560 }, /* braille_dots_23568 */ { 0x01002856, 6579 }, /* braille_dots_2357 */ { 0x010028d6, 6597 }, /* braille_dots_23578 */ { 0x01002896, 6616 }, /* braille_dots_2358 */ { 0x01002826, 6634 }, /* braille_dots_236 */ { 0x01002866, 6651 }, /* braille_dots_2367 */ { 0x010028e6, 6669 }, /* braille_dots_23678 */ { 0x010028a6, 6688 }, /* braille_dots_2368 */ { 0x01002846, 6706 }, /* braille_dots_237 */ { 0x010028c6, 6723 }, /* braille_dots_2378 */ { 0x01002886, 6741 }, /* braille_dots_238 */ { 0x0100280a, 6758 }, /* braille_dots_24 */ { 0x0100281a, 6774 }, /* braille_dots_245 */ { 0x0100283a, 6791 }, /* braille_dots_2456 */ { 0x0100287a, 6809 }, /* braille_dots_24567 */ { 0x010028fa, 6828 }, /* braille_dots_245678 */ { 0x010028ba, 6848 }, /* braille_dots_24568 */ { 0x0100285a, 6867 }, /* braille_dots_2457 */ { 0x010028da, 6885 }, /* braille_dots_24578 */ { 0x0100289a, 6904 }, /* braille_dots_2458 */ { 0x0100282a, 6922 }, /* braille_dots_246 */ { 0x0100286a, 6939 }, /* braille_dots_2467 */ { 0x010028ea, 6957 }, /* braille_dots_24678 */ { 0x010028aa, 6976 }, /* braille_dots_2468 */ { 0x0100284a, 6994 }, /* braille_dots_247 */ { 0x010028ca, 7011 }, /* braille_dots_2478 */ { 0x0100288a, 7029 }, /* braille_dots_248 */ { 0x01002812, 7046 }, /* braille_dots_25 */ { 0x01002832, 7062 }, /* braille_dots_256 */ { 0x01002872, 7079 }, /* braille_dots_2567 */ { 0x010028f2, 7097 }, /* braille_dots_25678 */ { 0x010028b2, 7116 }, /* braille_dots_2568 */ { 0x01002852, 7134 }, /* braille_dots_257 */ { 0x010028d2, 7151 }, /* braille_dots_2578 */ { 0x01002892, 7169 }, /* braille_dots_258 */ { 0x01002822, 7186 }, /* braille_dots_26 */ { 0x01002862, 7202 }, /* braille_dots_267 */ { 0x010028e2, 7219 }, /* braille_dots_2678 */ { 0x010028a2, 7237 }, /* braille_dots_268 */ { 0x01002842, 7254 }, /* braille_dots_27 */ { 0x010028c2, 7270 }, /* braille_dots_278 */ { 0x01002882, 7287 }, /* braille_dots_28 */ { 0x01002804, 7303 }, /* braille_dots_3 */ { 0x0100280c, 7318 }, /* braille_dots_34 */ { 0x0100281c, 7334 }, /* braille_dots_345 */ { 0x0100283c, 7351 }, /* braille_dots_3456 */ { 0x0100287c, 7369 }, /* braille_dots_34567 */ { 0x010028fc, 7388 }, /* braille_dots_345678 */ { 0x010028bc, 7408 }, /* braille_dots_34568 */ { 0x0100285c, 7427 }, /* braille_dots_3457 */ { 0x010028dc, 7445 }, /* braille_dots_34578 */ { 0x0100289c, 7464 }, /* braille_dots_3458 */ { 0x0100282c, 7482 }, /* braille_dots_346 */ { 0x0100286c, 7499 }, /* braille_dots_3467 */ { 0x010028ec, 7517 }, /* braille_dots_34678 */ { 0x010028ac, 7536 }, /* braille_dots_3468 */ { 0x0100284c, 7554 }, /* braille_dots_347 */ { 0x010028cc, 7571 }, /* braille_dots_3478 */ { 0x0100288c, 7589 }, /* braille_dots_348 */ { 0x01002814, 7606 }, /* braille_dots_35 */ { 0x01002834, 7622 }, /* braille_dots_356 */ { 0x01002874, 7639 }, /* braille_dots_3567 */ { 0x010028f4, 7657 }, /* braille_dots_35678 */ { 0x010028b4, 7676 }, /* braille_dots_3568 */ { 0x01002854, 7694 }, /* braille_dots_357 */ { 0x010028d4, 7711 }, /* braille_dots_3578 */ { 0x01002894, 7729 }, /* braille_dots_358 */ { 0x01002824, 7746 }, /* braille_dots_36 */ { 0x01002864, 7762 }, /* braille_dots_367 */ { 0x010028e4, 7779 }, /* braille_dots_3678 */ { 0x010028a4, 7797 }, /* braille_dots_368 */ { 0x01002844, 7814 }, /* braille_dots_37 */ { 0x010028c4, 7830 }, /* braille_dots_378 */ { 0x01002884, 7847 }, /* braille_dots_38 */ { 0x01002808, 7863 }, /* braille_dots_4 */ { 0x01002818, 7878 }, /* braille_dots_45 */ { 0x01002838, 7894 }, /* braille_dots_456 */ { 0x01002878, 7911 }, /* braille_dots_4567 */ { 0x010028f8, 7929 }, /* braille_dots_45678 */ { 0x010028b8, 7948 }, /* braille_dots_4568 */ { 0x01002858, 7966 }, /* braille_dots_457 */ { 0x010028d8, 7983 }, /* braille_dots_4578 */ { 0x01002898, 8001 }, /* braille_dots_458 */ { 0x01002828, 8018 }, /* braille_dots_46 */ { 0x01002868, 8034 }, /* braille_dots_467 */ { 0x010028e8, 8051 }, /* braille_dots_4678 */ { 0x010028a8, 8069 }, /* braille_dots_468 */ { 0x01002848, 8086 }, /* braille_dots_47 */ { 0x010028c8, 8102 }, /* braille_dots_478 */ { 0x01002888, 8119 }, /* braille_dots_48 */ { 0x01002810, 8135 }, /* braille_dots_5 */ { 0x01002830, 8150 }, /* braille_dots_56 */ { 0x01002870, 8166 }, /* braille_dots_567 */ { 0x010028f0, 8183 }, /* braille_dots_5678 */ { 0x010028b0, 8201 }, /* braille_dots_568 */ { 0x01002850, 8218 }, /* braille_dots_57 */ { 0x010028d0, 8234 }, /* braille_dots_578 */ { 0x01002890, 8251 }, /* braille_dots_58 */ { 0x01002820, 8267 }, /* braille_dots_6 */ { 0x01002860, 8282 }, /* braille_dots_67 */ { 0x010028e0, 8298 }, /* braille_dots_678 */ { 0x010028a0, 8315 }, /* braille_dots_68 */ { 0x01002840, 8331 }, /* braille_dots_7 */ { 0x010028c0, 8346 }, /* braille_dots_78 */ { 0x01002880, 8362 }, /* braille_dots_8 */ { 0x0000ff6b, 8377 }, /* Break */ { 0x000001a2, 8383 }, /* breve */ { 0x000000a6, 8389 }, /* brokenbar */ { 0x000006be, 8399 }, /* Byelorussian_SHORTU */ { 0x000006ae, 8419 }, /* Byelorussian_shortu */ { 0x00000043, 8439 }, /* C */ { 0x00000063, 8441 }, /* c */ { 0x0000fea5, 8443 }, /* C_H */ { 0x0000fea4, 8447 }, /* C_h */ { 0x0000fea3, 8451 }, /* c_h */ { 0x000002c5, 8455 }, /* Cabovedot */ { 0x000002e5, 8465 }, /* cabovedot */ { 0x000001c6, 8475 }, /* Cacute */ { 0x000001e6, 8482 }, /* cacute */ { 0x0000ff69, 8489 }, /* Cancel */ { 0x0000ffe5, 8496 }, /* Caps_Lock */ { 0x00000ab8, 8506 }, /* careof */ { 0x00000afc, 8513 }, /* caret */ { 0x000001b7, 8519 }, /* caron */ { 0x000001c8, 8525 }, /* Ccaron */ { 0x000001e8, 8532 }, /* ccaron */ { 0x000000c7, 8539 }, /* Ccedilla */ { 0x000000e7, 8548 }, /* ccedilla */ { 0x000002c6, 8557 }, /* Ccircumflex */ { 0x000002e6, 8569 }, /* ccircumflex */ { 0x000000b8, 8581 }, /* cedilla */ { 0x000000a2, 8589 }, /* cent */ { 0x0000fea2, 8594 }, /* CH */ { 0x0000fea1, 8597 }, /* Ch */ { 0x0000fea0, 8600 }, /* ch */ { 0x000009e1, 8603 }, /* checkerboard */ { 0x00000af3, 8616 }, /* checkmark */ { 0x00000bcf, 8626 }, /* circle */ { 0x0000ff0b, 8633 }, /* Clear */ { 0x1000ff6f, 8639 }, /* ClearLine */ { 0x00000aec, 8649 }, /* club */ { 0x0000ff37, 8654 }, /* Codeinput */ { 0x0000003a, 8664 }, /* colon */ { 0x010020a1, 8670 }, /* ColonSign */ { 0x01000301, 8680 }, /* combining_acute */ { 0x01000323, 8696 }, /* combining_belowdot */ { 0x01000300, 8715 }, /* combining_grave */ { 0x01000309, 8731 }, /* combining_hook */ { 0x01000303, 8746 }, /* combining_tilde */ { 0x0000002c, 8762 }, /* comma */ { 0x0100220b, 8768 }, /* containsas */ { 0x0000ffe3, 8779 }, /* Control_L */ { 0x0000ffe4, 8789 }, /* Control_R */ { 0x000000a9, 8799 }, /* copyright */ { 0x000009e4, 8809 }, /* cr */ { 0x000009ee, 8812 }, /* crossinglines */ { 0x010020a2, 8826 }, /* CruzeiroSign */ { 0x0100221b, 8839 }, /* cuberoot */ { 0x000000a4, 8848 }, /* currency */ { 0x00000aff, 8857 }, /* cursor */ { 0x000006e1, 8864 }, /* Cyrillic_A */ { 0x000006c1, 8875 }, /* Cyrillic_a */ { 0x000006e2, 8886 }, /* Cyrillic_BE */ { 0x000006c2, 8898 }, /* Cyrillic_be */ { 0x000006fe, 8910 }, /* Cyrillic_CHE */ { 0x000006de, 8923 }, /* Cyrillic_che */ { 0x010004b6, 8936 }, /* Cyrillic_CHE_descender */ { 0x010004b7, 8959 }, /* Cyrillic_che_descender */ { 0x010004b8, 8982 }, /* Cyrillic_CHE_vertstroke */ { 0x010004b9, 9006 }, /* Cyrillic_che_vertstroke */ { 0x000006e4, 9030 }, /* Cyrillic_DE */ { 0x000006c4, 9042 }, /* Cyrillic_de */ { 0x000006bf, 9054 }, /* Cyrillic_DZHE */ { 0x000006af, 9068 }, /* Cyrillic_dzhe */ { 0x000006fc, 9082 }, /* Cyrillic_E */ { 0x000006dc, 9093 }, /* Cyrillic_e */ { 0x000006e6, 9104 }, /* Cyrillic_EF */ { 0x000006c6, 9116 }, /* Cyrillic_ef */ { 0x000006ec, 9128 }, /* Cyrillic_EL */ { 0x000006cc, 9140 }, /* Cyrillic_el */ { 0x000006ed, 9152 }, /* Cyrillic_EM */ { 0x000006cd, 9164 }, /* Cyrillic_em */ { 0x000006ee, 9176 }, /* Cyrillic_EN */ { 0x000006ce, 9188 }, /* Cyrillic_en */ { 0x010004a2, 9200 }, /* Cyrillic_EN_descender */ { 0x010004a3, 9222 }, /* Cyrillic_en_descender */ { 0x000006f2, 9244 }, /* Cyrillic_ER */ { 0x000006d2, 9256 }, /* Cyrillic_er */ { 0x000006f3, 9268 }, /* Cyrillic_ES */ { 0x000006d3, 9280 }, /* Cyrillic_es */ { 0x000006e7, 9292 }, /* Cyrillic_GHE */ { 0x000006c7, 9305 }, /* Cyrillic_ghe */ { 0x01000492, 9318 }, /* Cyrillic_GHE_bar */ { 0x01000493, 9335 }, /* Cyrillic_ghe_bar */ { 0x000006e8, 9352 }, /* Cyrillic_HA */ { 0x000006c8, 9364 }, /* Cyrillic_ha */ { 0x010004b2, 9376 }, /* Cyrillic_HA_descender */ { 0x010004b3, 9398 }, /* Cyrillic_ha_descender */ { 0x000006ff, 9420 }, /* Cyrillic_HARDSIGN */ { 0x000006df, 9438 }, /* Cyrillic_hardsign */ { 0x000006e9, 9456 }, /* Cyrillic_I */ { 0x000006c9, 9467 }, /* Cyrillic_i */ { 0x010004e2, 9478 }, /* Cyrillic_I_macron */ { 0x010004e3, 9496 }, /* Cyrillic_i_macron */ { 0x000006e5, 9514 }, /* Cyrillic_IE */ { 0x000006c5, 9526 }, /* Cyrillic_ie */ { 0x000006b3, 9538 }, /* Cyrillic_IO */ { 0x000006a3, 9550 }, /* Cyrillic_io */ { 0x000006b8, 9562 }, /* Cyrillic_JE */ { 0x000006a8, 9574 }, /* Cyrillic_je */ { 0x000006eb, 9586 }, /* Cyrillic_KA */ { 0x000006cb, 9598 }, /* Cyrillic_ka */ { 0x0100049a, 9610 }, /* Cyrillic_KA_descender */ { 0x0100049b, 9632 }, /* Cyrillic_ka_descender */ { 0x0100049c, 9654 }, /* Cyrillic_KA_vertstroke */ { 0x0100049d, 9677 }, /* Cyrillic_ka_vertstroke */ { 0x000006b9, 9700 }, /* Cyrillic_LJE */ { 0x000006a9, 9713 }, /* Cyrillic_lje */ { 0x000006ba, 9726 }, /* Cyrillic_NJE */ { 0x000006aa, 9739 }, /* Cyrillic_nje */ { 0x000006ef, 9752 }, /* Cyrillic_O */ { 0x000006cf, 9763 }, /* Cyrillic_o */ { 0x010004e8, 9774 }, /* Cyrillic_O_bar */ { 0x010004e9, 9789 }, /* Cyrillic_o_bar */ { 0x000006f0, 9804 }, /* Cyrillic_PE */ { 0x000006d0, 9816 }, /* Cyrillic_pe */ { 0x010004d8, 9828 }, /* Cyrillic_SCHWA */ { 0x010004d9, 9843 }, /* Cyrillic_schwa */ { 0x000006fb, 9858 }, /* Cyrillic_SHA */ { 0x000006db, 9871 }, /* Cyrillic_sha */ { 0x000006fd, 9884 }, /* Cyrillic_SHCHA */ { 0x000006dd, 9899 }, /* Cyrillic_shcha */ { 0x010004ba, 9914 }, /* Cyrillic_SHHA */ { 0x010004bb, 9928 }, /* Cyrillic_shha */ { 0x000006ea, 9942 }, /* Cyrillic_SHORTI */ { 0x000006ca, 9958 }, /* Cyrillic_shorti */ { 0x000006f8, 9974 }, /* Cyrillic_SOFTSIGN */ { 0x000006d8, 9992 }, /* Cyrillic_softsign */ { 0x000006f4, 10010 }, /* Cyrillic_TE */ { 0x000006d4, 10022 }, /* Cyrillic_te */ { 0x000006e3, 10034 }, /* Cyrillic_TSE */ { 0x000006c3, 10047 }, /* Cyrillic_tse */ { 0x000006f5, 10060 }, /* Cyrillic_U */ { 0x000006d5, 10071 }, /* Cyrillic_u */ { 0x010004ee, 10082 }, /* Cyrillic_U_macron */ { 0x010004ef, 10100 }, /* Cyrillic_u_macron */ { 0x010004ae, 10118 }, /* Cyrillic_U_straight */ { 0x010004af, 10138 }, /* Cyrillic_u_straight */ { 0x010004b0, 10158 }, /* Cyrillic_U_straight_bar */ { 0x010004b1, 10182 }, /* Cyrillic_u_straight_bar */ { 0x000006f7, 10206 }, /* Cyrillic_VE */ { 0x000006d7, 10218 }, /* Cyrillic_ve */ { 0x000006f1, 10230 }, /* Cyrillic_YA */ { 0x000006d1, 10242 }, /* Cyrillic_ya */ { 0x000006f9, 10254 }, /* Cyrillic_YERU */ { 0x000006d9, 10268 }, /* Cyrillic_yeru */ { 0x000006e0, 10282 }, /* Cyrillic_YU */ { 0x000006c0, 10294 }, /* Cyrillic_yu */ { 0x000006fa, 10306 }, /* Cyrillic_ZE */ { 0x000006da, 10318 }, /* Cyrillic_ze */ { 0x000006f6, 10330 }, /* Cyrillic_ZHE */ { 0x000006d6, 10343 }, /* Cyrillic_zhe */ { 0x01000496, 10356 }, /* Cyrillic_ZHE_descender */ { 0x01000497, 10379 }, /* Cyrillic_zhe_descender */ { 0x00000044, 10402 }, /* D */ { 0x00000064, 10404 }, /* d */ { 0x01001e0a, 10406 }, /* Dabovedot */ { 0x01001e0b, 10416 }, /* dabovedot */ { 0x1000fe27, 10426 }, /* Dacute_accent */ { 0x00000af1, 10440 }, /* dagger */ { 0x000001cf, 10447 }, /* Dcaron */ { 0x000001ef, 10454 }, /* dcaron */ { 0x1000fe2c, 10461 }, /* Dcedilla_accent */ { 0x1000fe5e, 10477 }, /* Dcircumflex_accent */ { 0x1000fe22, 10496 }, /* Ddiaeresis */ { 0x0000fe81, 10507 }, /* dead_A */ { 0x0000fe80, 10514 }, /* dead_a */ { 0x0000fe64, 10521 }, /* dead_abovecomma */ { 0x0000fe56, 10537 }, /* dead_abovedot */ { 0x0000fe65, 10551 }, /* dead_abovereversedcomma */ { 0x0000fe58, 10575 }, /* dead_abovering */ { 0x0000fe91, 10590 }, /* dead_aboveverticalline */ { 0x0000fe51, 10613 }, /* dead_acute */ { 0x0000fe6b, 10624 }, /* dead_belowbreve */ { 0x0000fe69, 10640 }, /* dead_belowcircumflex */ { 0x0000fe6e, 10661 }, /* dead_belowcomma */ { 0x0000fe6c, 10677 }, /* dead_belowdiaeresis */ { 0x0000fe60, 10697 }, /* dead_belowdot */ { 0x0000fe68, 10711 }, /* dead_belowmacron */ { 0x0000fe67, 10728 }, /* dead_belowring */ { 0x0000fe6a, 10743 }, /* dead_belowtilde */ { 0x0000fe92, 10759 }, /* dead_belowverticalline */ { 0x0000fe55, 10782 }, /* dead_breve */ { 0x0000fe8b, 10793 }, /* dead_capital_schwa */ { 0x0000fe5a, 10812 }, /* dead_caron */ { 0x0000fe5b, 10823 }, /* dead_cedilla */ { 0x0000fe52, 10836 }, /* dead_circumflex */ { 0x0000fe6f, 10852 }, /* dead_currency */ { 0x0000fe65, 10866 }, /* dead_dasia */ { 0x0000fe57, 10877 }, /* dead_diaeresis */ { 0x0000fe59, 10892 }, /* dead_doubleacute */ { 0x0000fe66, 10909 }, /* dead_doublegrave */ { 0x0000fe83, 10926 }, /* dead_E */ { 0x0000fe82, 10933 }, /* dead_e */ { 0x0000fe50, 10940 }, /* dead_grave */ { 0x0000fe8c, 10951 }, /* dead_greek */ { 0x0000fe8d, 10962 }, /* dead_hamza */ { 0x0000fe61, 10973 }, /* dead_hook */ { 0x0000fe62, 10983 }, /* dead_horn */ { 0x0000fe85, 10993 }, /* dead_I */ { 0x0000fe84, 11000 }, /* dead_i */ { 0x0000fe6d, 11007 }, /* dead_invertedbreve */ { 0x0000fe5d, 11026 }, /* dead_iota */ { 0x0000fe93, 11036 }, /* dead_longsolidusoverlay */ { 0x0000fe90, 11060 }, /* dead_lowline */ { 0x0000fe54, 11073 }, /* dead_macron */ { 0x0000fe87, 11085 }, /* dead_O */ { 0x0000fe86, 11092 }, /* dead_o */ { 0x0000fe5c, 11099 }, /* dead_ogonek */ { 0x0000fe53, 11111 }, /* dead_perispomeni */ { 0x0000fe64, 11128 }, /* dead_psili */ { 0x0000fe8b, 11139 }, /* dead_SCHWA */ { 0x0000fe8a, 11150 }, /* dead_schwa */ { 0x0000fe5f, 11161 }, /* dead_semivoiced_sound */ { 0x0000fe8a, 11183 }, /* dead_small_schwa */ { 0x0000fe63, 11200 }, /* dead_stroke */ { 0x0000fe53, 11212 }, /* dead_tilde */ { 0x0000fe89, 11223 }, /* dead_U */ { 0x0000fe88, 11230 }, /* dead_u */ { 0x0000fe5e, 11237 }, /* dead_voiced_sound */ { 0x00000abd, 11255 }, /* decimalpoint */ { 0x000000b0, 11268 }, /* degree */ { 0x0000ffff, 11275 }, /* Delete */ { 0x1000ff73, 11282 }, /* DeleteChar */ { 0x1000ff71, 11293 }, /* DeleteLine */ { 0x1000fe60, 11304 }, /* Dgrave_accent */ { 0x000000a8, 11318 }, /* diaeresis */ { 0x00000aed, 11328 }, /* diamond */ { 0x00000aa5, 11336 }, /* digitspace */ { 0x0100222c, 11347 }, /* dintegral */ { 0x000000f7, 11357 }, /* division */ { 0x00000024, 11366 }, /* dollar */ { 0x010020ab, 11373 }, /* DongSign */ { 0x00000aaf, 11382 }, /* doubbaselinedot */ { 0x000001bd, 11398 }, /* doubleacute */ { 0x00000af2, 11410 }, /* doubledagger */ { 0x00000afe, 11423 }, /* doublelowquotemark */ { 0x0000ff54, 11442 }, /* Down */ { 0x000008fe, 11447 }, /* downarrow */ { 0x00000ba8, 11457 }, /* downcaret */ { 0x00000bd6, 11467 }, /* downshoe */ { 0x00000bc4, 11476 }, /* downstile */ { 0x00000bc2, 11486 }, /* downtack */ { 0x1000ff00, 11495 }, /* DRemove */ { 0x1000feb0, 11503 }, /* Dring_accent */ { 0x000001d0, 11516 }, /* Dstroke */ { 0x000001f0, 11524 }, /* dstroke */ { 0x1000fe7e, 11532 }, /* Dtilde */ { 0x00000045, 11539 }, /* E */ { 0x00000065, 11541 }, /* e */ { 0x000003cc, 11543 }, /* Eabovedot */ { 0x000003ec, 11553 }, /* eabovedot */ { 0x000000c9, 11563 }, /* Eacute */ { 0x000000e9, 11570 }, /* eacute */ { 0x01001eb8, 11577 }, /* Ebelowdot */ { 0x01001eb9, 11587 }, /* ebelowdot */ { 0x000001cc, 11597 }, /* Ecaron */ { 0x000001ec, 11604 }, /* ecaron */ { 0x000000ca, 11611 }, /* Ecircumflex */ { 0x000000ea, 11623 }, /* ecircumflex */ { 0x01001ebe, 11635 }, /* Ecircumflexacute */ { 0x01001ebf, 11652 }, /* ecircumflexacute */ { 0x01001ec6, 11669 }, /* Ecircumflexbelowdot */ { 0x01001ec7, 11689 }, /* ecircumflexbelowdot */ { 0x01001ec0, 11709 }, /* Ecircumflexgrave */ { 0x01001ec1, 11726 }, /* ecircumflexgrave */ { 0x01001ec2, 11743 }, /* Ecircumflexhook */ { 0x01001ec3, 11759 }, /* ecircumflexhook */ { 0x01001ec4, 11775 }, /* Ecircumflextilde */ { 0x01001ec5, 11792 }, /* ecircumflextilde */ { 0x010020a0, 11809 }, /* EcuSign */ { 0x000000cb, 11817 }, /* Ediaeresis */ { 0x000000eb, 11828 }, /* ediaeresis */ { 0x000000c8, 11839 }, /* Egrave */ { 0x000000e8, 11846 }, /* egrave */ { 0x01001eba, 11853 }, /* Ehook */ { 0x01001ebb, 11859 }, /* ehook */ { 0x01002088, 11865 }, /* eightsubscript */ { 0x01002078, 11880 }, /* eightsuperior */ { 0x0000ff2f, 11894 }, /* Eisu_Shift */ { 0x0000ff30, 11905 }, /* Eisu_toggle */ { 0x01002208, 11917 }, /* elementof */ { 0x00000aae, 11927 }, /* ellipsis */ { 0x00000aa3, 11936 }, /* em3space */ { 0x00000aa4, 11945 }, /* em4space */ { 0x000003aa, 11954 }, /* Emacron */ { 0x000003ba, 11962 }, /* emacron */ { 0x00000aa9, 11970 }, /* emdash */ { 0x00000ade, 11977 }, /* emfilledcircle */ { 0x00000adf, 11992 }, /* emfilledrect */ { 0x00000ace, 12005 }, /* emopencircle */ { 0x00000acf, 12018 }, /* emopenrectangle */ { 0x01002205, 12034 }, /* emptyset */ { 0x00000aa1, 12043 }, /* emspace */ { 0x0000ff57, 12051 }, /* End */ { 0x00000aaa, 12055 }, /* endash */ { 0x00000ae6, 12062 }, /* enfilledcircbullet */ { 0x00000ae7, 12081 }, /* enfilledsqbullet */ { 0x000003bd, 12098 }, /* ENG */ { 0x000003bf, 12102 }, /* eng */ { 0x00000ae0, 12106 }, /* enopencircbullet */ { 0x00000ae1, 12123 }, /* enopensquarebullet */ { 0x00000aa2, 12142 }, /* enspace */ { 0x000001ca, 12150 }, /* Eogonek */ { 0x000001ea, 12158 }, /* eogonek */ { 0x0000003d, 12166 }, /* equal */ { 0x0000ff1b, 12172 }, /* Escape */ { 0x000000d0, 12179 }, /* ETH */ { 0x000000d0, 12183 }, /* Eth */ { 0x000000f0, 12187 }, /* eth */ { 0x01001ebc, 12191 }, /* Etilde */ { 0x01001ebd, 12198 }, /* etilde */ { 0x000020ac, 12205 }, /* EuroSign */ { 0x00000021, 12214 }, /* exclam */ { 0x000000a1, 12221 }, /* exclamdown */ { 0x0000ff62, 12232 }, /* Execute */ { 0x1000ff76, 12240 }, /* Ext16bit_L */ { 0x1000ff77, 12251 }, /* Ext16bit_R */ { 0x010001b7, 12262 }, /* EZH */ { 0x01000292, 12266 }, /* ezh */ { 0x00000046, 12270 }, /* F */ { 0x00000066, 12272 }, /* f */ { 0x0000ffbe, 12274 }, /* F1 */ { 0x0000ffc7, 12277 }, /* F10 */ { 0x0000ffc8, 12281 }, /* F11 */ { 0x0000ffc9, 12285 }, /* F12 */ { 0x0000ffca, 12289 }, /* F13 */ { 0x0000ffcb, 12293 }, /* F14 */ { 0x0000ffcc, 12297 }, /* F15 */ { 0x0000ffcd, 12301 }, /* F16 */ { 0x0000ffce, 12305 }, /* F17 */ { 0x0000ffcf, 12309 }, /* F18 */ { 0x0000ffd0, 12313 }, /* F19 */ { 0x0000ffbf, 12317 }, /* F2 */ { 0x0000ffd1, 12320 }, /* F20 */ { 0x0000ffd2, 12324 }, /* F21 */ { 0x0000ffd3, 12328 }, /* F22 */ { 0x0000ffd4, 12332 }, /* F23 */ { 0x0000ffd5, 12336 }, /* F24 */ { 0x0000ffd6, 12340 }, /* F25 */ { 0x0000ffd7, 12344 }, /* F26 */ { 0x0000ffd8, 12348 }, /* F27 */ { 0x0000ffd9, 12352 }, /* F28 */ { 0x0000ffda, 12356 }, /* F29 */ { 0x0000ffc0, 12360 }, /* F3 */ { 0x0000ffdb, 12363 }, /* F30 */ { 0x0000ffdc, 12367 }, /* F31 */ { 0x0000ffdd, 12371 }, /* F32 */ { 0x0000ffde, 12375 }, /* F33 */ { 0x0000ffdf, 12379 }, /* F34 */ { 0x0000ffe0, 12383 }, /* F35 */ { 0x0000ffc1, 12387 }, /* F4 */ { 0x0000ffc2, 12390 }, /* F5 */ { 0x0000ffc3, 12393 }, /* F6 */ { 0x0000ffc4, 12396 }, /* F7 */ { 0x0000ffc5, 12399 }, /* F8 */ { 0x0000ffc6, 12402 }, /* F9 */ { 0x01001e1e, 12405 }, /* Fabovedot */ { 0x01001e1f, 12415 }, /* fabovedot */ { 0x010006f0, 12425 }, /* Farsi_0 */ { 0x010006f1, 12433 }, /* Farsi_1 */ { 0x010006f2, 12441 }, /* Farsi_2 */ { 0x010006f3, 12449 }, /* Farsi_3 */ { 0x010006f4, 12457 }, /* Farsi_4 */ { 0x010006f5, 12465 }, /* Farsi_5 */ { 0x010006f6, 12473 }, /* Farsi_6 */ { 0x010006f7, 12481 }, /* Farsi_7 */ { 0x010006f8, 12489 }, /* Farsi_8 */ { 0x010006f9, 12497 }, /* Farsi_9 */ { 0x010006cc, 12505 }, /* Farsi_yeh */ { 0x00000af8, 12515 }, /* femalesymbol */ { 0x000009e3, 12528 }, /* ff */ { 0x010020a3, 12531 }, /* FFrancSign */ { 0x00000abb, 12542 }, /* figdash */ { 0x00000adc, 12550 }, /* filledlefttribullet */ { 0x00000adb, 12570 }, /* filledrectbullet */ { 0x00000add, 12587 }, /* filledrighttribullet */ { 0x00000ae9, 12608 }, /* filledtribulletdown */ { 0x00000ae8, 12628 }, /* filledtribulletup */ { 0x0000ff68, 12646 }, /* Find */ { 0x0000fed0, 12651 }, /* First_Virtual_Screen */ { 0x00000ac5, 12672 }, /* fiveeighths */ { 0x00000ab7, 12684 }, /* fivesixths */ { 0x01002085, 12695 }, /* fivesubscript */ { 0x01002075, 12709 }, /* fivesuperior */ { 0x00000ab5, 12722 }, /* fourfifths */ { 0x01002084, 12733 }, /* foursubscript */ { 0x01002074, 12747 }, /* foursuperior */ { 0x0100221c, 12760 }, /* fourthroot */ { 0x000008f6, 12771 }, /* function */ { 0x00000047, 12780 }, /* G */ { 0x00000067, 12782 }, /* g */ { 0x000002d5, 12784 }, /* Gabovedot */ { 0x000002f5, 12794 }, /* gabovedot */ { 0x000002ab, 12804 }, /* Gbreve */ { 0x000002bb, 12811 }, /* gbreve */ { 0x010001e6, 12818 }, /* Gcaron */ { 0x010001e7, 12825 }, /* gcaron */ { 0x000003ab, 12832 }, /* Gcedilla */ { 0x000003bb, 12841 }, /* gcedilla */ { 0x000002d8, 12850 }, /* Gcircumflex */ { 0x000002f8, 12862 }, /* gcircumflex */ { 0x010010d0, 12874 }, /* Georgian_an */ { 0x010010d1, 12886 }, /* Georgian_ban */ { 0x010010ea, 12899 }, /* Georgian_can */ { 0x010010ed, 12912 }, /* Georgian_char */ { 0x010010e9, 12926 }, /* Georgian_chin */ { 0x010010ec, 12940 }, /* Georgian_cil */ { 0x010010d3, 12953 }, /* Georgian_don */ { 0x010010d4, 12966 }, /* Georgian_en */ { 0x010010f6, 12978 }, /* Georgian_fi */ { 0x010010d2, 12990 }, /* Georgian_gan */ { 0x010010e6, 13003 }, /* Georgian_ghan */ { 0x010010f0, 13017 }, /* Georgian_hae */ { 0x010010f4, 13030 }, /* Georgian_har */ { 0x010010f1, 13043 }, /* Georgian_he */ { 0x010010f2, 13055 }, /* Georgian_hie */ { 0x010010f5, 13068 }, /* Georgian_hoe */ { 0x010010d8, 13081 }, /* Georgian_in */ { 0x010010ef, 13093 }, /* Georgian_jhan */ { 0x010010eb, 13107 }, /* Georgian_jil */ { 0x010010d9, 13120 }, /* Georgian_kan */ { 0x010010e5, 13133 }, /* Georgian_khar */ { 0x010010da, 13147 }, /* Georgian_las */ { 0x010010db, 13160 }, /* Georgian_man */ { 0x010010dc, 13173 }, /* Georgian_nar */ { 0x010010dd, 13186 }, /* Georgian_on */ { 0x010010de, 13198 }, /* Georgian_par */ { 0x010010e4, 13211 }, /* Georgian_phar */ { 0x010010e7, 13225 }, /* Georgian_qar */ { 0x010010e0, 13238 }, /* Georgian_rae */ { 0x010010e1, 13251 }, /* Georgian_san */ { 0x010010e8, 13264 }, /* Georgian_shin */ { 0x010010d7, 13278 }, /* Georgian_tan */ { 0x010010e2, 13291 }, /* Georgian_tar */ { 0x010010e3, 13304 }, /* Georgian_un */ { 0x010010d5, 13316 }, /* Georgian_vin */ { 0x010010f3, 13329 }, /* Georgian_we */ { 0x010010ee, 13341 }, /* Georgian_xan */ { 0x010010d6, 13354 }, /* Georgian_zen */ { 0x010010df, 13367 }, /* Georgian_zhar */ { 0x00000060, 13381 }, /* grave */ { 0x0000003e, 13387 }, /* greater */ { 0x000008be, 13395 }, /* greaterthanequal */ { 0x000007ae, 13412 }, /* Greek_accentdieresis */ { 0x000007c1, 13433 }, /* Greek_ALPHA */ { 0x000007e1, 13445 }, /* Greek_alpha */ { 0x000007a1, 13457 }, /* Greek_ALPHAaccent */ { 0x000007b1, 13475 }, /* Greek_alphaaccent */ { 0x000007c2, 13493 }, /* Greek_BETA */ { 0x000007e2, 13504 }, /* Greek_beta */ { 0x000007d7, 13515 }, /* Greek_CHI */ { 0x000007f7, 13525 }, /* Greek_chi */ { 0x000007c4, 13535 }, /* Greek_DELTA */ { 0x000007e4, 13547 }, /* Greek_delta */ { 0x000007c5, 13559 }, /* Greek_EPSILON */ { 0x000007e5, 13573 }, /* Greek_epsilon */ { 0x000007a2, 13587 }, /* Greek_EPSILONaccent */ { 0x000007b2, 13607 }, /* Greek_epsilonaccent */ { 0x000007c7, 13627 }, /* Greek_ETA */ { 0x000007e7, 13637 }, /* Greek_eta */ { 0x000007a3, 13647 }, /* Greek_ETAaccent */ { 0x000007b3, 13663 }, /* Greek_etaaccent */ { 0x000007f3, 13679 }, /* Greek_finalsmallsigma */ { 0x000007c3, 13701 }, /* Greek_GAMMA */ { 0x000007e3, 13713 }, /* Greek_gamma */ { 0x000007af, 13725 }, /* Greek_horizbar */ { 0x000007c9, 13740 }, /* Greek_IOTA */ { 0x000007e9, 13751 }, /* Greek_iota */ { 0x000007a4, 13762 }, /* Greek_IOTAaccent */ { 0x000007b4, 13779 }, /* Greek_iotaaccent */ { 0x000007b6, 13796 }, /* Greek_iotaaccentdieresis */ { 0x000007a5, 13821 }, /* Greek_IOTAdiaeresis */ { 0x000007a5, 13841 }, /* Greek_IOTAdieresis */ { 0x000007b5, 13860 }, /* Greek_iotadieresis */ { 0x000007ca, 13879 }, /* Greek_KAPPA */ { 0x000007ea, 13891 }, /* Greek_kappa */ { 0x000007cb, 13903 }, /* Greek_LAMBDA */ { 0x000007eb, 13916 }, /* Greek_lambda */ { 0x000007cb, 13929 }, /* Greek_LAMDA */ { 0x000007eb, 13941 }, /* Greek_lamda */ { 0x000007cc, 13953 }, /* Greek_MU */ { 0x000007ec, 13962 }, /* Greek_mu */ { 0x000007cd, 13971 }, /* Greek_NU */ { 0x000007ed, 13980 }, /* Greek_nu */ { 0x000007d9, 13989 }, /* Greek_OMEGA */ { 0x000007f9, 14001 }, /* Greek_omega */ { 0x000007ab, 14013 }, /* Greek_OMEGAaccent */ { 0x000007bb, 14031 }, /* Greek_omegaaccent */ { 0x000007cf, 14049 }, /* Greek_OMICRON */ { 0x000007ef, 14063 }, /* Greek_omicron */ { 0x000007a7, 14077 }, /* Greek_OMICRONaccent */ { 0x000007b7, 14097 }, /* Greek_omicronaccent */ { 0x000007d6, 14117 }, /* Greek_PHI */ { 0x000007f6, 14127 }, /* Greek_phi */ { 0x000007d0, 14137 }, /* Greek_PI */ { 0x000007f0, 14146 }, /* Greek_pi */ { 0x000007d8, 14155 }, /* Greek_PSI */ { 0x000007f8, 14165 }, /* Greek_psi */ { 0x000007d1, 14175 }, /* Greek_RHO */ { 0x000007f1, 14185 }, /* Greek_rho */ { 0x000007d2, 14195 }, /* Greek_SIGMA */ { 0x000007f2, 14207 }, /* Greek_sigma */ { 0x0000ff7e, 14219 }, /* Greek_switch */ { 0x000007d4, 14232 }, /* Greek_TAU */ { 0x000007f4, 14242 }, /* Greek_tau */ { 0x000007c8, 14252 }, /* Greek_THETA */ { 0x000007e8, 14264 }, /* Greek_theta */ { 0x000007d5, 14276 }, /* Greek_UPSILON */ { 0x000007f5, 14290 }, /* Greek_upsilon */ { 0x000007a8, 14304 }, /* Greek_UPSILONaccent */ { 0x000007b8, 14324 }, /* Greek_upsilonaccent */ { 0x000007ba, 14344 }, /* Greek_upsilonaccentdieresis */ { 0x000007a9, 14372 }, /* Greek_UPSILONdieresis */ { 0x000007b9, 14394 }, /* Greek_upsilondieresis */ { 0x000007ce, 14416 }, /* Greek_XI */ { 0x000007ee, 14425 }, /* Greek_xi */ { 0x000007c6, 14434 }, /* Greek_ZETA */ { 0x000007e6, 14445 }, /* Greek_zeta */ { 0x100000be, 14456 }, /* guilder */ { 0x000000ab, 14464 }, /* guillemetleft */ { 0x000000bb, 14478 }, /* guillemetright */ { 0x000000ab, 14493 }, /* guillemotleft */ { 0x000000bb, 14507 }, /* guillemotright */ { 0x00000048, 14522 }, /* H */ { 0x00000068, 14524 }, /* h */ { 0x00000aa8, 14526 }, /* hairspace */ { 0x0000ff31, 14536 }, /* Hangul */ { 0x00000ebf, 14543 }, /* Hangul_A */ { 0x00000ec0, 14552 }, /* Hangul_AE */ { 0x00000ef6, 14562 }, /* Hangul_AraeA */ { 0x00000ef7, 14575 }, /* Hangul_AraeAE */ { 0x0000ff39, 14589 }, /* Hangul_Banja */ { 0x00000eba, 14602 }, /* Hangul_Cieuc */ { 0x0000ff37, 14615 }, /* Hangul_Codeinput */ { 0x00000ea7, 14632 }, /* Hangul_Dikeud */ { 0x00000ec4, 14646 }, /* Hangul_E */ { 0x0000ff33, 14655 }, /* Hangul_End */ { 0x00000ec3, 14666 }, /* Hangul_EO */ { 0x00000ed1, 14676 }, /* Hangul_EU */ { 0x0000ff34, 14686 }, /* Hangul_Hanja */ { 0x00000ebe, 14699 }, /* Hangul_Hieuh */ { 0x00000ed3, 14712 }, /* Hangul_I */ { 0x00000eb7, 14721 }, /* Hangul_Ieung */ { 0x00000eea, 14734 }, /* Hangul_J_Cieuc */ { 0x00000eda, 14749 }, /* Hangul_J_Dikeud */ { 0x00000eee, 14765 }, /* Hangul_J_Hieuh */ { 0x00000ee8, 14780 }, /* Hangul_J_Ieung */ { 0x00000ee9, 14795 }, /* Hangul_J_Jieuj */ { 0x00000eeb, 14810 }, /* Hangul_J_Khieuq */ { 0x00000ed4, 14826 }, /* Hangul_J_Kiyeog */ { 0x00000ed6, 14842 }, /* Hangul_J_KiyeogSios */ { 0x00000ef9, 14862 }, /* Hangul_J_KkogjiDalrinIeung */ { 0x00000ee3, 14889 }, /* Hangul_J_Mieum */ { 0x00000ed7, 14904 }, /* Hangul_J_Nieun */ { 0x00000ed9, 14919 }, /* Hangul_J_NieunHieuh */ { 0x00000ed8, 14939 }, /* Hangul_J_NieunJieuj */ { 0x00000ef8, 14959 }, /* Hangul_J_PanSios */ { 0x00000eed, 14976 }, /* Hangul_J_Phieuf */ { 0x00000ee4, 14992 }, /* Hangul_J_Pieub */ { 0x00000ee5, 15007 }, /* Hangul_J_PieubSios */ { 0x00000edb, 15026 }, /* Hangul_J_Rieul */ { 0x00000ee2, 15041 }, /* Hangul_J_RieulHieuh */ { 0x00000edc, 15061 }, /* Hangul_J_RieulKiyeog */ { 0x00000edd, 15082 }, /* Hangul_J_RieulMieum */ { 0x00000ee1, 15102 }, /* Hangul_J_RieulPhieuf */ { 0x00000ede, 15123 }, /* Hangul_J_RieulPieub */ { 0x00000edf, 15143 }, /* Hangul_J_RieulSios */ { 0x00000ee0, 15162 }, /* Hangul_J_RieulTieut */ { 0x00000ee6, 15182 }, /* Hangul_J_Sios */ { 0x00000ed5, 15196 }, /* Hangul_J_SsangKiyeog */ { 0x00000ee7, 15217 }, /* Hangul_J_SsangSios */ { 0x00000eec, 15236 }, /* Hangul_J_Tieut */ { 0x00000efa, 15251 }, /* Hangul_J_YeorinHieuh */ { 0x0000ff35, 15272 }, /* Hangul_Jamo */ { 0x0000ff38, 15284 }, /* Hangul_Jeonja */ { 0x00000eb8, 15298 }, /* Hangul_Jieuj */ { 0x00000ebb, 15311 }, /* Hangul_Khieuq */ { 0x00000ea1, 15325 }, /* Hangul_Kiyeog */ { 0x00000ea3, 15339 }, /* Hangul_KiyeogSios */ { 0x00000ef3, 15357 }, /* Hangul_KkogjiDalrinIeung */ { 0x00000eb1, 15382 }, /* Hangul_Mieum */ { 0x0000ff3d, 15395 }, /* Hangul_MultipleCandidate */ { 0x00000ea4, 15420 }, /* Hangul_Nieun */ { 0x00000ea6, 15433 }, /* Hangul_NieunHieuh */ { 0x00000ea5, 15451 }, /* Hangul_NieunJieuj */ { 0x00000ec7, 15469 }, /* Hangul_O */ { 0x00000eca, 15478 }, /* Hangul_OE */ { 0x00000ef2, 15488 }, /* Hangul_PanSios */ { 0x00000ebd, 15503 }, /* Hangul_Phieuf */ { 0x00000eb2, 15517 }, /* Hangul_Pieub */ { 0x00000eb4, 15530 }, /* Hangul_PieubSios */ { 0x0000ff3b, 15547 }, /* Hangul_PostHanja */ { 0x0000ff3a, 15564 }, /* Hangul_PreHanja */ { 0x0000ff3e, 15580 }, /* Hangul_PreviousCandidate */ { 0x00000ea9, 15605 }, /* Hangul_Rieul */ { 0x00000eb0, 15618 }, /* Hangul_RieulHieuh */ { 0x00000eaa, 15636 }, /* Hangul_RieulKiyeog */ { 0x00000eab, 15655 }, /* Hangul_RieulMieum */ { 0x00000eaf, 15673 }, /* Hangul_RieulPhieuf */ { 0x00000eac, 15692 }, /* Hangul_RieulPieub */ { 0x00000ead, 15710 }, /* Hangul_RieulSios */ { 0x00000eae, 15727 }, /* Hangul_RieulTieut */ { 0x00000eef, 15745 }, /* Hangul_RieulYeorinHieuh */ { 0x0000ff36, 15769 }, /* Hangul_Romaja */ { 0x0000ff3c, 15783 }, /* Hangul_SingleCandidate */ { 0x00000eb5, 15806 }, /* Hangul_Sios */ { 0x0000ff3f, 15818 }, /* Hangul_Special */ { 0x00000ea8, 15833 }, /* Hangul_SsangDikeud */ { 0x00000eb9, 15852 }, /* Hangul_SsangJieuj */ { 0x00000ea2, 15870 }, /* Hangul_SsangKiyeog */ { 0x00000eb3, 15889 }, /* Hangul_SsangPieub */ { 0x00000eb6, 15907 }, /* Hangul_SsangSios */ { 0x0000ff32, 15924 }, /* Hangul_Start */ { 0x00000ef0, 15937 }, /* Hangul_SunkyeongeumMieum */ { 0x00000ef4, 15962 }, /* Hangul_SunkyeongeumPhieuf */ { 0x00000ef1, 15988 }, /* Hangul_SunkyeongeumPieub */ { 0x0000ff7e, 16013 }, /* Hangul_switch */ { 0x00000ebc, 16027 }, /* Hangul_Tieut */ { 0x00000ecc, 16040 }, /* Hangul_U */ { 0x00000ec8, 16049 }, /* Hangul_WA */ { 0x00000ec9, 16059 }, /* Hangul_WAE */ { 0x00000ece, 16070 }, /* Hangul_WE */ { 0x00000ecd, 16080 }, /* Hangul_WEO */ { 0x00000ecf, 16091 }, /* Hangul_WI */ { 0x00000ec1, 16101 }, /* Hangul_YA */ { 0x00000ec2, 16111 }, /* Hangul_YAE */ { 0x00000ec6, 16122 }, /* Hangul_YE */ { 0x00000ec5, 16132 }, /* Hangul_YEO */ { 0x00000ef5, 16143 }, /* Hangul_YeorinHieuh */ { 0x00000ed2, 16162 }, /* Hangul_YI */ { 0x00000ecb, 16172 }, /* Hangul_YO */ { 0x00000ed0, 16182 }, /* Hangul_YU */ { 0x0000ff29, 16192 }, /* Hankaku */ { 0x000002a6, 16200 }, /* Hcircumflex */ { 0x000002b6, 16212 }, /* hcircumflex */ { 0x00000aee, 16224 }, /* heart */ { 0x00000ce0, 16230 }, /* hebrew_aleph */ { 0x00000cf2, 16243 }, /* hebrew_ayin */ { 0x00000ce1, 16255 }, /* hebrew_bet */ { 0x00000ce1, 16266 }, /* hebrew_beth */ { 0x00000ce7, 16278 }, /* hebrew_chet */ { 0x00000ce3, 16290 }, /* hebrew_dalet */ { 0x00000ce3, 16303 }, /* hebrew_daleth */ { 0x00000cdf, 16317 }, /* hebrew_doublelowline */ { 0x00000cea, 16338 }, /* hebrew_finalkaph */ { 0x00000ced, 16355 }, /* hebrew_finalmem */ { 0x00000cef, 16371 }, /* hebrew_finalnun */ { 0x00000cf3, 16387 }, /* hebrew_finalpe */ { 0x00000cf5, 16402 }, /* hebrew_finalzade */ { 0x00000cf5, 16419 }, /* hebrew_finalzadi */ { 0x00000ce2, 16436 }, /* hebrew_gimel */ { 0x00000ce2, 16449 }, /* hebrew_gimmel */ { 0x00000ce4, 16463 }, /* hebrew_he */ { 0x00000ce7, 16473 }, /* hebrew_het */ { 0x00000ceb, 16484 }, /* hebrew_kaph */ { 0x00000cf7, 16496 }, /* hebrew_kuf */ { 0x00000cec, 16507 }, /* hebrew_lamed */ { 0x00000cee, 16520 }, /* hebrew_mem */ { 0x00000cf0, 16531 }, /* hebrew_nun */ { 0x00000cf4, 16542 }, /* hebrew_pe */ { 0x00000cf7, 16552 }, /* hebrew_qoph */ { 0x00000cf8, 16564 }, /* hebrew_resh */ { 0x00000cf1, 16576 }, /* hebrew_samech */ { 0x00000cf1, 16590 }, /* hebrew_samekh */ { 0x00000cf9, 16604 }, /* hebrew_shin */ { 0x0000ff7e, 16616 }, /* Hebrew_switch */ { 0x00000cfa, 16630 }, /* hebrew_taf */ { 0x00000cfa, 16641 }, /* hebrew_taw */ { 0x00000ce8, 16652 }, /* hebrew_tet */ { 0x00000ce8, 16663 }, /* hebrew_teth */ { 0x00000ce5, 16675 }, /* hebrew_waw */ { 0x00000ce9, 16686 }, /* hebrew_yod */ { 0x00000cf6, 16697 }, /* hebrew_zade */ { 0x00000cf6, 16709 }, /* hebrew_zadi */ { 0x00000ce6, 16721 }, /* hebrew_zain */ { 0x00000ce6, 16733 }, /* hebrew_zayin */ { 0x0000ff6a, 16746 }, /* Help */ { 0x0000ff23, 16751 }, /* Henkan */ { 0x0000ff23, 16758 }, /* Henkan_Mode */ { 0x00000ada, 16770 }, /* hexagram */ { 0x0000ff25, 16779 }, /* Hiragana */ { 0x0000ff27, 16788 }, /* Hiragana_Katakana */ { 0x0000ff50, 16806 }, /* Home */ { 0x000008a3, 16811 }, /* horizconnector */ { 0x000009ef, 16826 }, /* horizlinescan1 */ { 0x000009f0, 16841 }, /* horizlinescan3 */ { 0x000009f1, 16856 }, /* horizlinescan5 */ { 0x000009f2, 16871 }, /* horizlinescan7 */ { 0x000009f3, 16886 }, /* horizlinescan9 */ { 0x1000ff74, 16901 }, /* hpBackTab */ { 0x100000fc, 16911 }, /* hpblock */ { 0x1000ff6f, 16919 }, /* hpClearLine */ { 0x1000ff73, 16931 }, /* hpDeleteChar */ { 0x1000ff71, 16944 }, /* hpDeleteLine */ { 0x100000be, 16957 }, /* hpguilder */ { 0x1000ff72, 16967 }, /* hpInsertChar */ { 0x1000ff70, 16980 }, /* hpInsertLine */ { 0x100000ee, 16993 }, /* hpIO */ { 0x1000ff75, 16998 }, /* hpKP_BackTab */ { 0x100000af, 17011 }, /* hplira */ { 0x100000f6, 17018 }, /* hplongminus */ { 0x1000ff48, 17030 }, /* hpModelock1 */ { 0x1000ff49, 17042 }, /* hpModelock2 */ { 0x100000a8, 17054 }, /* hpmute_acute */ { 0x100000aa, 17067 }, /* hpmute_asciicircum */ { 0x100000ac, 17086 }, /* hpmute_asciitilde */ { 0x100000ab, 17104 }, /* hpmute_diaeresis */ { 0x100000a9, 17121 }, /* hpmute_grave */ { 0x1000ff6c, 17134 }, /* hpReset */ { 0x1000ff6d, 17142 }, /* hpSystem */ { 0x1000ff6e, 17151 }, /* hpUser */ { 0x100000ee, 17158 }, /* hpYdiaeresis */ { 0x000002a1, 17171 }, /* Hstroke */ { 0x000002b1, 17179 }, /* hstroke */ { 0x000009e2, 17187 }, /* ht */ { 0x0000ffed, 17190 }, /* Hyper_L */ { 0x0000ffee, 17198 }, /* Hyper_R */ { 0x000000ad, 17206 }, /* hyphen */ { 0x00000049, 17213 }, /* I */ { 0x00000069, 17215 }, /* i */ { 0x000002a9, 17217 }, /* Iabovedot */ { 0x000000cd, 17227 }, /* Iacute */ { 0x000000ed, 17234 }, /* iacute */ { 0x01001eca, 17241 }, /* Ibelowdot */ { 0x01001ecb, 17251 }, /* ibelowdot */ { 0x0100012c, 17261 }, /* Ibreve */ { 0x0100012d, 17268 }, /* ibreve */ { 0x000000ce, 17275 }, /* Icircumflex */ { 0x000000ee, 17287 }, /* icircumflex */ { 0x000008cf, 17299 }, /* identical */ { 0x000000cf, 17309 }, /* Idiaeresis */ { 0x000000ef, 17320 }, /* idiaeresis */ { 0x000002b9, 17331 }, /* idotless */ { 0x000008cd, 17340 }, /* ifonlyif */ { 0x000000cc, 17349 }, /* Igrave */ { 0x000000ec, 17356 }, /* igrave */ { 0x01001ec8, 17363 }, /* Ihook */ { 0x01001ec9, 17369 }, /* ihook */ { 0x000003cf, 17375 }, /* Imacron */ { 0x000003ef, 17383 }, /* imacron */ { 0x000008ce, 17391 }, /* implies */ { 0x000008da, 17399 }, /* includedin */ { 0x000008db, 17410 }, /* includes */ { 0x000008c2, 17419 }, /* infinity */ { 0x0000ff63, 17428 }, /* Insert */ { 0x1000ff72, 17435 }, /* InsertChar */ { 0x1000ff70, 17446 }, /* InsertLine */ { 0x000008bf, 17457 }, /* integral */ { 0x000008dc, 17466 }, /* intersection */ { 0x100000ee, 17479 }, /* IO */ { 0x000003c7, 17482 }, /* Iogonek */ { 0x000003e7, 17490 }, /* iogonek */ { 0x0000fe33, 17498 }, /* ISO_Center_Object */ { 0x0000fe30, 17516 }, /* ISO_Continuous_Underline */ { 0x0000fe31, 17541 }, /* ISO_Discontinuous_Underline */ { 0x0000fe32, 17569 }, /* ISO_Emphasize */ { 0x0000fe34, 17583 }, /* ISO_Enter */ { 0x0000fe2f, 17593 }, /* ISO_Fast_Cursor_Down */ { 0x0000fe2c, 17614 }, /* ISO_Fast_Cursor_Left */ { 0x0000fe2d, 17635 }, /* ISO_Fast_Cursor_Right */ { 0x0000fe2e, 17657 }, /* ISO_Fast_Cursor_Up */ { 0x0000fe0c, 17676 }, /* ISO_First_Group */ { 0x0000fe0d, 17692 }, /* ISO_First_Group_Lock */ { 0x0000fe06, 17713 }, /* ISO_Group_Latch */ { 0x0000fe07, 17729 }, /* ISO_Group_Lock */ { 0x0000ff7e, 17744 }, /* ISO_Group_Shift */ { 0x0000fe0e, 17760 }, /* ISO_Last_Group */ { 0x0000fe0f, 17775 }, /* ISO_Last_Group_Lock */ { 0x0000fe20, 17795 }, /* ISO_Left_Tab */ { 0x0000fe02, 17808 }, /* ISO_Level2_Latch */ { 0x0000fe04, 17825 }, /* ISO_Level3_Latch */ { 0x0000fe05, 17842 }, /* ISO_Level3_Lock */ { 0x0000fe03, 17858 }, /* ISO_Level3_Shift */ { 0x0000fe12, 17875 }, /* ISO_Level5_Latch */ { 0x0000fe13, 17892 }, /* ISO_Level5_Lock */ { 0x0000fe11, 17908 }, /* ISO_Level5_Shift */ { 0x0000fe01, 17925 }, /* ISO_Lock */ { 0x0000fe22, 17934 }, /* ISO_Move_Line_Down */ { 0x0000fe21, 17953 }, /* ISO_Move_Line_Up */ { 0x0000fe08, 17970 }, /* ISO_Next_Group */ { 0x0000fe09, 17985 }, /* ISO_Next_Group_Lock */ { 0x0000fe24, 18005 }, /* ISO_Partial_Line_Down */ { 0x0000fe23, 18027 }, /* ISO_Partial_Line_Up */ { 0x0000fe25, 18047 }, /* ISO_Partial_Space_Left */ { 0x0000fe26, 18070 }, /* ISO_Partial_Space_Right */ { 0x0000fe0a, 18094 }, /* ISO_Prev_Group */ { 0x0000fe0b, 18109 }, /* ISO_Prev_Group_Lock */ { 0x0000fe2b, 18129 }, /* ISO_Release_Both_Margins */ { 0x0000fe29, 18154 }, /* ISO_Release_Margin_Left */ { 0x0000fe2a, 18178 }, /* ISO_Release_Margin_Right */ { 0x0000fe27, 18203 }, /* ISO_Set_Margin_Left */ { 0x0000fe28, 18223 }, /* ISO_Set_Margin_Right */ { 0x000003a5, 18244 }, /* Itilde */ { 0x000003b5, 18251 }, /* itilde */ { 0x0000004a, 18258 }, /* J */ { 0x0000006a, 18260 }, /* j */ { 0x000002ac, 18262 }, /* Jcircumflex */ { 0x000002bc, 18274 }, /* jcircumflex */ { 0x00000bca, 18286 }, /* jot */ { 0x0000004b, 18290 }, /* K */ { 0x0000006b, 18292 }, /* k */ { 0x000004b1, 18294 }, /* kana_A */ { 0x000004a7, 18301 }, /* kana_a */ { 0x000004c1, 18308 }, /* kana_CHI */ { 0x000004a3, 18317 }, /* kana_closingbracket */ { 0x000004a4, 18337 }, /* kana_comma */ { 0x000004a5, 18348 }, /* kana_conjunctive */ { 0x000004b4, 18365 }, /* kana_E */ { 0x000004aa, 18372 }, /* kana_e */ { 0x000004cc, 18379 }, /* kana_FU */ { 0x000004a1, 18387 }, /* kana_fullstop */ { 0x000004ca, 18401 }, /* kana_HA */ { 0x000004cd, 18409 }, /* kana_HE */ { 0x000004cb, 18417 }, /* kana_HI */ { 0x000004ce, 18425 }, /* kana_HO */ { 0x000004cc, 18433 }, /* kana_HU */ { 0x000004b2, 18441 }, /* kana_I */ { 0x000004a8, 18448 }, /* kana_i */ { 0x000004b6, 18455 }, /* kana_KA */ { 0x000004b9, 18463 }, /* kana_KE */ { 0x000004b7, 18471 }, /* kana_KI */ { 0x000004ba, 18479 }, /* kana_KO */ { 0x000004b8, 18487 }, /* kana_KU */ { 0x0000ff2d, 18495 }, /* Kana_Lock */ { 0x000004cf, 18505 }, /* kana_MA */ { 0x000004d2, 18513 }, /* kana_ME */ { 0x000004d0, 18521 }, /* kana_MI */ { 0x000004a5, 18529 }, /* kana_middledot */ { 0x000004d3, 18544 }, /* kana_MO */ { 0x000004d1, 18552 }, /* kana_MU */ { 0x000004dd, 18560 }, /* kana_N */ { 0x000004c5, 18567 }, /* kana_NA */ { 0x000004c8, 18575 }, /* kana_NE */ { 0x000004c6, 18583 }, /* kana_NI */ { 0x000004c9, 18591 }, /* kana_NO */ { 0x000004c7, 18599 }, /* kana_NU */ { 0x000004b5, 18607 }, /* kana_O */ { 0x000004ab, 18614 }, /* kana_o */ { 0x000004a2, 18621 }, /* kana_openingbracket */ { 0x000004d7, 18641 }, /* kana_RA */ { 0x000004da, 18649 }, /* kana_RE */ { 0x000004d8, 18657 }, /* kana_RI */ { 0x000004db, 18665 }, /* kana_RO */ { 0x000004d9, 18673 }, /* kana_RU */ { 0x000004bb, 18681 }, /* kana_SA */ { 0x000004be, 18689 }, /* kana_SE */ { 0x000004bc, 18697 }, /* kana_SHI */ { 0x0000ff2e, 18706 }, /* Kana_Shift */ { 0x000004bf, 18717 }, /* kana_SO */ { 0x000004bd, 18725 }, /* kana_SU */ { 0x0000ff7e, 18733 }, /* kana_switch */ { 0x000004c0, 18745 }, /* kana_TA */ { 0x000004c3, 18753 }, /* kana_TE */ { 0x000004c1, 18761 }, /* kana_TI */ { 0x000004c4, 18769 }, /* kana_TO */ { 0x000004c2, 18777 }, /* kana_TSU */ { 0x000004af, 18786 }, /* kana_tsu */ { 0x000004c2, 18795 }, /* kana_TU */ { 0x000004af, 18803 }, /* kana_tu */ { 0x000004b3, 18811 }, /* kana_U */ { 0x000004a9, 18818 }, /* kana_u */ { 0x000004dc, 18825 }, /* kana_WA */ { 0x000004a6, 18833 }, /* kana_WO */ { 0x000004d4, 18841 }, /* kana_YA */ { 0x000004ac, 18849 }, /* kana_ya */ { 0x000004d6, 18857 }, /* kana_YO */ { 0x000004ae, 18865 }, /* kana_yo */ { 0x000004d5, 18873 }, /* kana_YU */ { 0x000004ad, 18881 }, /* kana_yu */ { 0x0000ff21, 18889 }, /* Kanji */ { 0x0000ff37, 18895 }, /* Kanji_Bangou */ { 0x000003a2, 18908 }, /* kappa */ { 0x0000ff26, 18914 }, /* Katakana */ { 0x000003d3, 18923 }, /* Kcedilla */ { 0x000003f3, 18932 }, /* kcedilla */ { 0x00000eff, 18941 }, /* Korean_Won */ { 0x0000ffb0, 18952 }, /* KP_0 */ { 0x0000ffb1, 18957 }, /* KP_1 */ { 0x0000ffb2, 18962 }, /* KP_2 */ { 0x0000ffb3, 18967 }, /* KP_3 */ { 0x0000ffb4, 18972 }, /* KP_4 */ { 0x0000ffb5, 18977 }, /* KP_5 */ { 0x0000ffb6, 18982 }, /* KP_6 */ { 0x0000ffb7, 18987 }, /* KP_7 */ { 0x0000ffb8, 18992 }, /* KP_8 */ { 0x0000ffb9, 18997 }, /* KP_9 */ { 0x0000ffab, 19002 }, /* KP_Add */ { 0x1000ff75, 19009 }, /* KP_BackTab */ { 0x0000ff9d, 19020 }, /* KP_Begin */ { 0x0000ffae, 19029 }, /* KP_Decimal */ { 0x0000ff9f, 19040 }, /* KP_Delete */ { 0x0000ffaf, 19050 }, /* KP_Divide */ { 0x0000ff99, 19060 }, /* KP_Down */ { 0x0000ff9c, 19068 }, /* KP_End */ { 0x0000ff8d, 19075 }, /* KP_Enter */ { 0x0000ffbd, 19084 }, /* KP_Equal */ { 0x0000ff91, 19093 }, /* KP_F1 */ { 0x0000ff92, 19099 }, /* KP_F2 */ { 0x0000ff93, 19105 }, /* KP_F3 */ { 0x0000ff94, 19111 }, /* KP_F4 */ { 0x0000ff95, 19117 }, /* KP_Home */ { 0x0000ff9e, 19125 }, /* KP_Insert */ { 0x0000ff96, 19135 }, /* KP_Left */ { 0x0000ffaa, 19143 }, /* KP_Multiply */ { 0x0000ff9b, 19155 }, /* KP_Next */ { 0x0000ff9b, 19163 }, /* KP_Page_Down */ { 0x0000ff9a, 19176 }, /* KP_Page_Up */ { 0x0000ff9a, 19187 }, /* KP_Prior */ { 0x0000ff98, 19196 }, /* KP_Right */ { 0x0000ffac, 19205 }, /* KP_Separator */ { 0x0000ff80, 19218 }, /* KP_Space */ { 0x0000ffad, 19227 }, /* KP_Subtract */ { 0x0000ff89, 19239 }, /* KP_Tab */ { 0x0000ff97, 19246 }, /* KP_Up */ { 0x000003a2, 19252 }, /* kra */ { 0x0000004c, 19256 }, /* L */ { 0x0000006c, 19258 }, /* l */ { 0x0000ffc8, 19260 }, /* L1 */ { 0x0000ffd1, 19263 }, /* L10 */ { 0x0000ffc9, 19267 }, /* L2 */ { 0x0000ffca, 19270 }, /* L3 */ { 0x0000ffcb, 19273 }, /* L4 */ { 0x0000ffcc, 19276 }, /* L5 */ { 0x0000ffcd, 19279 }, /* L6 */ { 0x0000ffce, 19282 }, /* L7 */ { 0x0000ffcf, 19285 }, /* L8 */ { 0x0000ffd0, 19288 }, /* L9 */ { 0x000001c5, 19291 }, /* Lacute */ { 0x000001e5, 19298 }, /* lacute */ { 0x0000fed4, 19305 }, /* Last_Virtual_Screen */ { 0x00000ad9, 19325 }, /* latincross */ { 0x01001e36, 19336 }, /* Lbelowdot */ { 0x01001e37, 19346 }, /* lbelowdot */ { 0x000001a5, 19356 }, /* Lcaron */ { 0x000001b5, 19363 }, /* lcaron */ { 0x000003a6, 19370 }, /* Lcedilla */ { 0x000003b6, 19379 }, /* lcedilla */ { 0x0000ff51, 19388 }, /* Left */ { 0x00000abc, 19393 }, /* leftanglebracket */ { 0x000008fb, 19410 }, /* leftarrow */ { 0x00000ba3, 19420 }, /* leftcaret */ { 0x00000ad2, 19430 }, /* leftdoublequotemark */ { 0x000008af, 19450 }, /* leftmiddlecurlybrace */ { 0x00000acc, 19471 }, /* leftopentriangle */ { 0x00000aea, 19488 }, /* leftpointer */ { 0x000008a1, 19500 }, /* leftradical */ { 0x00000bda, 19512 }, /* leftshoe */ { 0x00000ad0, 19521 }, /* leftsinglequotemark */ { 0x000009f4, 19541 }, /* leftt */ { 0x00000bdc, 19547 }, /* lefttack */ { 0x0000003c, 19556 }, /* less */ { 0x000008bc, 19561 }, /* lessthanequal */ { 0x000009e5, 19575 }, /* lf */ { 0x0000ff0a, 19578 }, /* Linefeed */ { 0x100000af, 19587 }, /* lira */ { 0x010020a4, 19592 }, /* LiraSign */ { 0x000008de, 19601 }, /* logicaland */ { 0x000008df, 19612 }, /* logicalor */ { 0x100000f6, 19622 }, /* longminus */ { 0x000009ed, 19632 }, /* lowleftcorner */ { 0x000009ea, 19646 }, /* lowrightcorner */ { 0x000001a3, 19661 }, /* Lstroke */ { 0x000001b3, 19669 }, /* lstroke */ { 0x0000004d, 19677 }, /* M */ { 0x0000006d, 19679 }, /* m */ { 0x01001e40, 19681 }, /* Mabovedot */ { 0x01001e41, 19691 }, /* mabovedot */ { 0x000006b5, 19701 }, /* Macedonia_DSE */ { 0x000006a5, 19715 }, /* Macedonia_dse */ { 0x000006b2, 19729 }, /* Macedonia_GJE */ { 0x000006a2, 19743 }, /* Macedonia_gje */ { 0x000006bc, 19757 }, /* Macedonia_KJE */ { 0x000006ac, 19771 }, /* Macedonia_kje */ { 0x000000af, 19785 }, /* macron */ { 0x0000ff3e, 19792 }, /* Mae_Koho */ { 0x00000af7, 19801 }, /* malesymbol */ { 0x00000af0, 19812 }, /* maltesecross */ { 0x00000abf, 19825 }, /* marker */ { 0x000000ba, 19832 }, /* masculine */ { 0x0000ff2c, 19842 }, /* Massyo */ { 0x0000ff67, 19849 }, /* Menu */ { 0x0000ffe7, 19854 }, /* Meta_L */ { 0x0000ffe8, 19861 }, /* Meta_R */ { 0x010020a5, 19868 }, /* MillSign */ { 0x0000002d, 19877 }, /* minus */ { 0x00000ad6, 19883 }, /* minutes */ { 0x0000ff7e, 19891 }, /* Mode_switch */ { 0x0000fe77, 19903 }, /* MouseKeys_Accel_Enable */ { 0x0000fe76, 19926 }, /* MouseKeys_Enable */ { 0x000000b5, 19943 }, /* mu */ { 0x0000ff22, 19946 }, /* Muhenkan */ { 0x0000ff20, 19955 }, /* Multi_key */ { 0x0000ff3d, 19965 }, /* MultipleCandidate */ { 0x000000d7, 19983 }, /* multiply */ { 0x00000af6, 19992 }, /* musicalflat */ { 0x00000af5, 20004 }, /* musicalsharp */ { 0x100000a8, 20017 }, /* mute_acute */ { 0x100000aa, 20028 }, /* mute_asciicircum */ { 0x100000ac, 20045 }, /* mute_asciitilde */ { 0x100000ab, 20061 }, /* mute_diaeresis */ { 0x100000a9, 20076 }, /* mute_grave */ { 0x0000004e, 20087 }, /* N */ { 0x0000006e, 20089 }, /* n */ { 0x000008c5, 20091 }, /* nabla */ { 0x000001d1, 20097 }, /* Nacute */ { 0x000001f1, 20104 }, /* nacute */ { 0x010020a6, 20111 }, /* NairaSign */ { 0x000001d2, 20121 }, /* Ncaron */ { 0x000001f2, 20128 }, /* ncaron */ { 0x000003d1, 20135 }, /* Ncedilla */ { 0x000003f1, 20144 }, /* ncedilla */ { 0x010020aa, 20153 }, /* NewSheqelSign */ { 0x0000ff56, 20167 }, /* Next */ { 0x0000fed2, 20172 }, /* Next_Virtual_Screen */ { 0x01002089, 20192 }, /* ninesubscript */ { 0x01002079, 20206 }, /* ninesuperior */ { 0x000009e8, 20219 }, /* nl */ { 0x000000a0, 20222 }, /* nobreakspace */ { 0x00000000, 20235 }, /* NoSymbol */ { 0x01002247, 20244 }, /* notapproxeq */ { 0x01002209, 20256 }, /* notelementof */ { 0x000008bd, 20269 }, /* notequal */ { 0x01002262, 20278 }, /* notidentical */ { 0x000000ac, 20291 }, /* notsign */ { 0x000000d1, 20299 }, /* Ntilde */ { 0x000000f1, 20306 }, /* ntilde */ { 0x0000ff7f, 20313 }, /* Num_Lock */ { 0x00000023, 20322 }, /* numbersign */ { 0x000006b0, 20333 }, /* numerosign */ { 0x0000004f, 20344 }, /* O */ { 0x0000006f, 20346 }, /* o */ { 0x000000d3, 20348 }, /* Oacute */ { 0x000000f3, 20355 }, /* oacute */ { 0x0100019f, 20362 }, /* Obarred */ { 0x01000275, 20370 }, /* obarred */ { 0x01001ecc, 20378 }, /* Obelowdot */ { 0x01001ecd, 20388 }, /* obelowdot */ { 0x010001d1, 20398 }, /* Ocaron */ { 0x010001d2, 20405 }, /* ocaron */ { 0x000000d4, 20412 }, /* Ocircumflex */ { 0x000000f4, 20424 }, /* ocircumflex */ { 0x01001ed0, 20436 }, /* Ocircumflexacute */ { 0x01001ed1, 20453 }, /* ocircumflexacute */ { 0x01001ed8, 20470 }, /* Ocircumflexbelowdot */ { 0x01001ed9, 20490 }, /* ocircumflexbelowdot */ { 0x01001ed2, 20510 }, /* Ocircumflexgrave */ { 0x01001ed3, 20527 }, /* ocircumflexgrave */ { 0x01001ed4, 20544 }, /* Ocircumflexhook */ { 0x01001ed5, 20560 }, /* ocircumflexhook */ { 0x01001ed6, 20576 }, /* Ocircumflextilde */ { 0x01001ed7, 20593 }, /* ocircumflextilde */ { 0x000000d6, 20610 }, /* Odiaeresis */ { 0x000000f6, 20621 }, /* odiaeresis */ { 0x000001d5, 20632 }, /* Odoubleacute */ { 0x000001f5, 20645 }, /* odoubleacute */ { 0x000013bc, 20658 }, /* OE */ { 0x000013bd, 20661 }, /* oe */ { 0x000001b2, 20664 }, /* ogonek */ { 0x000000d2, 20671 }, /* Ograve */ { 0x000000f2, 20678 }, /* ograve */ { 0x01001ece, 20685 }, /* Ohook */ { 0x01001ecf, 20691 }, /* ohook */ { 0x010001a0, 20697 }, /* Ohorn */ { 0x010001a1, 20703 }, /* ohorn */ { 0x01001eda, 20709 }, /* Ohornacute */ { 0x01001edb, 20720 }, /* ohornacute */ { 0x01001ee2, 20731 }, /* Ohornbelowdot */ { 0x01001ee3, 20745 }, /* ohornbelowdot */ { 0x01001edc, 20759 }, /* Ohorngrave */ { 0x01001edd, 20770 }, /* ohorngrave */ { 0x01001ede, 20781 }, /* Ohornhook */ { 0x01001edf, 20791 }, /* ohornhook */ { 0x01001ee0, 20801 }, /* Ohorntilde */ { 0x01001ee1, 20812 }, /* ohorntilde */ { 0x000003d2, 20823 }, /* Omacron */ { 0x000003f2, 20831 }, /* omacron */ { 0x00000ac3, 20839 }, /* oneeighth */ { 0x00000ab2, 20849 }, /* onefifth */ { 0x000000bd, 20858 }, /* onehalf */ { 0x000000bc, 20866 }, /* onequarter */ { 0x00000ab6, 20877 }, /* onesixth */ { 0x01002081, 20886 }, /* onesubscript */ { 0x000000b9, 20899 }, /* onesuperior */ { 0x00000ab0, 20911 }, /* onethird */ { 0x000000d8, 20920 }, /* Ooblique */ { 0x000000f8, 20929 }, /* ooblique */ { 0x00000ae2, 20938 }, /* openrectbullet */ { 0x00000ae5, 20953 }, /* openstar */ { 0x00000ae4, 20962 }, /* opentribulletdown */ { 0x00000ae3, 20980 }, /* opentribulletup */ { 0x000000aa, 20996 }, /* ordfeminine */ { 0x000000ba, 21008 }, /* ordmasculine */ { 0x1004ff44, 21021 }, /* osfActivate */ { 0x1004ff31, 21033 }, /* osfAddMode */ { 0x1004ff08, 21044 }, /* osfBackSpace */ { 0x1004ff07, 21057 }, /* osfBackTab */ { 0x1004ff5a, 21068 }, /* osfBeginData */ { 0x1004ff58, 21081 }, /* osfBeginLine */ { 0x1004ff69, 21094 }, /* osfCancel */ { 0x1004ff0b, 21104 }, /* osfClear */ { 0x1004ff02, 21113 }, /* osfCopy */ { 0x1004ff03, 21121 }, /* osfCut */ { 0x1004ffff, 21128 }, /* osfDelete */ { 0x1004ff72, 21138 }, /* osfDeselectAll */ { 0x1004ff54, 21153 }, /* osfDown */ { 0x1004ff59, 21161 }, /* osfEndData */ { 0x1004ff57, 21172 }, /* osfEndLine */ { 0x1004ff1b, 21183 }, /* osfEscape */ { 0x1004ff74, 21193 }, /* osfExtend */ { 0x1004ff6a, 21203 }, /* osfHelp */ { 0x1004ff63, 21211 }, /* osfInsert */ { 0x1004ff51, 21221 }, /* osfLeft */ { 0x1004ff67, 21229 }, /* osfMenu */ { 0x1004ff45, 21237 }, /* osfMenuBar */ { 0x1004ff5e, 21248 }, /* osfNextField */ { 0x1004ff5c, 21261 }, /* osfNextMenu */ { 0x1004ff42, 21273 }, /* osfPageDown */ { 0x1004ff40, 21285 }, /* osfPageLeft */ { 0x1004ff43, 21297 }, /* osfPageRight */ { 0x1004ff41, 21310 }, /* osfPageUp */ { 0x1004ff04, 21320 }, /* osfPaste */ { 0x1004ff5d, 21329 }, /* osfPrevField */ { 0x1004ff5b, 21342 }, /* osfPrevMenu */ { 0x1004ff32, 21354 }, /* osfPrimaryPaste */ { 0x1004ff33, 21370 }, /* osfQuickPaste */ { 0x1004ff73, 21384 }, /* osfReselect */ { 0x1004ff78, 21396 }, /* osfRestore */ { 0x1004ff53, 21407 }, /* osfRight */ { 0x1004ff60, 21416 }, /* osfSelect */ { 0x1004ff71, 21426 }, /* osfSelectAll */ { 0x1004ff65, 21439 }, /* osfUndo */ { 0x1004ff52, 21447 }, /* osfUp */ { 0x000000d8, 21453 }, /* Oslash */ { 0x000000f8, 21460 }, /* oslash */ { 0x000000d5, 21467 }, /* Otilde */ { 0x000000f5, 21474 }, /* otilde */ { 0x00000bc0, 21481 }, /* overbar */ { 0x0000fe78, 21489 }, /* Overlay1_Enable */ { 0x0000fe79, 21505 }, /* Overlay2_Enable */ { 0x0000047e, 21521 }, /* overline */ { 0x00000050, 21530 }, /* P */ { 0x00000070, 21532 }, /* p */ { 0x01001e56, 21534 }, /* Pabovedot */ { 0x01001e57, 21544 }, /* pabovedot */ { 0x0000ff56, 21554 }, /* Page_Down */ { 0x0000ff55, 21564 }, /* Page_Up */ { 0x000000b6, 21572 }, /* paragraph */ { 0x00000028, 21582 }, /* parenleft */ { 0x00000029, 21592 }, /* parenright */ { 0x01002202, 21603 }, /* partdifferential */ { 0x000008ef, 21620 }, /* partialderivative */ { 0x0000ff13, 21638 }, /* Pause */ { 0x00000025, 21644 }, /* percent */ { 0x0000002e, 21652 }, /* period */ { 0x000000b7, 21659 }, /* periodcentered */ { 0x00000ad5, 21674 }, /* permille */ { 0x010020a7, 21683 }, /* PesetaSign */ { 0x00000afb, 21694 }, /* phonographcopyright */ { 0x0000002b, 21714 }, /* plus */ { 0x000000b1, 21719 }, /* plusminus */ { 0x0000fefa, 21729 }, /* Pointer_Accelerate */ { 0x0000fee9, 21748 }, /* Pointer_Button1 */ { 0x0000feea, 21764 }, /* Pointer_Button2 */ { 0x0000feeb, 21780 }, /* Pointer_Button3 */ { 0x0000feec, 21796 }, /* Pointer_Button4 */ { 0x0000feed, 21812 }, /* Pointer_Button5 */ { 0x0000fee8, 21828 }, /* Pointer_Button_Dflt */ { 0x0000feef, 21848 }, /* Pointer_DblClick1 */ { 0x0000fef0, 21866 }, /* Pointer_DblClick2 */ { 0x0000fef1, 21884 }, /* Pointer_DblClick3 */ { 0x0000fef2, 21902 }, /* Pointer_DblClick4 */ { 0x0000fef3, 21920 }, /* Pointer_DblClick5 */ { 0x0000feee, 21938 }, /* Pointer_DblClick_Dflt */ { 0x0000fefb, 21960 }, /* Pointer_DfltBtnNext */ { 0x0000fefc, 21980 }, /* Pointer_DfltBtnPrev */ { 0x0000fee3, 22000 }, /* Pointer_Down */ { 0x0000fee6, 22013 }, /* Pointer_DownLeft */ { 0x0000fee7, 22030 }, /* Pointer_DownRight */ { 0x0000fef5, 22048 }, /* Pointer_Drag1 */ { 0x0000fef6, 22062 }, /* Pointer_Drag2 */ { 0x0000fef7, 22076 }, /* Pointer_Drag3 */ { 0x0000fef8, 22090 }, /* Pointer_Drag4 */ { 0x0000fefd, 22104 }, /* Pointer_Drag5 */ { 0x0000fef4, 22118 }, /* Pointer_Drag_Dflt */ { 0x0000fef9, 22136 }, /* Pointer_EnableKeys */ { 0x0000fee0, 22155 }, /* Pointer_Left */ { 0x0000fee1, 22168 }, /* Pointer_Right */ { 0x0000fee2, 22182 }, /* Pointer_Up */ { 0x0000fee4, 22193 }, /* Pointer_UpLeft */ { 0x0000fee5, 22208 }, /* Pointer_UpRight */ { 0x00000ad4, 22224 }, /* prescription */ { 0x0000fed1, 22237 }, /* Prev_Virtual_Screen */ { 0x0000ff3e, 22257 }, /* PreviousCandidate */ { 0x0000ff61, 22275 }, /* Print */ { 0x0000ff55, 22281 }, /* Prior */ { 0x000004b0, 22287 }, /* prolongedsound */ { 0x00000aa6, 22302 }, /* punctspace */ { 0x00000051, 22313 }, /* Q */ { 0x00000071, 22315 }, /* q */ { 0x00000bcc, 22317 }, /* quad */ { 0x0000003f, 22322 }, /* question */ { 0x000000bf, 22331 }, /* questiondown */ { 0x00000022, 22344 }, /* quotedbl */ { 0x00000060, 22353 }, /* quoteleft */ { 0x00000027, 22363 }, /* quoteright */ { 0x00000052, 22374 }, /* R */ { 0x00000072, 22376 }, /* r */ { 0x0000ffd2, 22378 }, /* R1 */ { 0x0000ffdb, 22381 }, /* R10 */ { 0x0000ffdc, 22385 }, /* R11 */ { 0x0000ffdd, 22389 }, /* R12 */ { 0x0000ffde, 22393 }, /* R13 */ { 0x0000ffdf, 22397 }, /* R14 */ { 0x0000ffe0, 22401 }, /* R15 */ { 0x0000ffd3, 22405 }, /* R2 */ { 0x0000ffd4, 22408 }, /* R3 */ { 0x0000ffd5, 22411 }, /* R4 */ { 0x0000ffd6, 22414 }, /* R5 */ { 0x0000ffd7, 22417 }, /* R6 */ { 0x0000ffd8, 22420 }, /* R7 */ { 0x0000ffd9, 22423 }, /* R8 */ { 0x0000ffda, 22426 }, /* R9 */ { 0x000001c0, 22429 }, /* Racute */ { 0x000001e0, 22436 }, /* racute */ { 0x000008d6, 22443 }, /* radical */ { 0x000001d8, 22451 }, /* Rcaron */ { 0x000001f8, 22458 }, /* rcaron */ { 0x000003a3, 22465 }, /* Rcedilla */ { 0x000003b3, 22474 }, /* rcedilla */ { 0x0000ff66, 22483 }, /* Redo */ { 0x000000ae, 22488 }, /* registered */ { 0x0000fe72, 22499 }, /* RepeatKeys_Enable */ { 0x1000ff6c, 22517 }, /* Reset */ { 0x0000ff0d, 22523 }, /* Return */ { 0x0000ff53, 22530 }, /* Right */ { 0x00000abe, 22536 }, /* rightanglebracket */ { 0x000008fd, 22554 }, /* rightarrow */ { 0x00000ba6, 22565 }, /* rightcaret */ { 0x00000ad3, 22576 }, /* rightdoublequotemark */ { 0x000008b0, 22597 }, /* rightmiddlecurlybrace */ { 0x000008b7, 22619 }, /* rightmiddlesummation */ { 0x00000acd, 22640 }, /* rightopentriangle */ { 0x00000aeb, 22658 }, /* rightpointer */ { 0x00000bd8, 22671 }, /* rightshoe */ { 0x00000ad1, 22681 }, /* rightsinglequotemark */ { 0x000009f5, 22702 }, /* rightt */ { 0x00000bfc, 22709 }, /* righttack */ { 0x0000ff24, 22719 }, /* Romaji */ { 0x010020a8, 22726 }, /* RupeeSign */ { 0x00000053, 22736 }, /* S */ { 0x00000073, 22738 }, /* s */ { 0x01001e60, 22740 }, /* Sabovedot */ { 0x01001e61, 22750 }, /* sabovedot */ { 0x000001a6, 22760 }, /* Sacute */ { 0x000001b6, 22767 }, /* sacute */ { 0x000001a9, 22774 }, /* Scaron */ { 0x000001b9, 22781 }, /* scaron */ { 0x000001aa, 22788 }, /* Scedilla */ { 0x000001ba, 22797 }, /* scedilla */ { 0x0100018f, 22806 }, /* SCHWA */ { 0x01000259, 22812 }, /* schwa */ { 0x000002de, 22818 }, /* Scircumflex */ { 0x000002fe, 22830 }, /* scircumflex */ { 0x0000ff7e, 22842 }, /* script_switch */ { 0x0000ff14, 22856 }, /* Scroll_Lock */ { 0x00000ad7, 22868 }, /* seconds */ { 0x000000a7, 22876 }, /* section */ { 0x0000ff60, 22884 }, /* Select */ { 0x0000003b, 22891 }, /* semicolon */ { 0x000004df, 22901 }, /* semivoicedsound */ { 0x000006b1, 22917 }, /* Serbian_DJE */ { 0x000006a1, 22929 }, /* Serbian_dje */ { 0x000006bf, 22941 }, /* Serbian_DZE */ { 0x000006af, 22953 }, /* Serbian_dze */ { 0x000006b8, 22965 }, /* Serbian_JE */ { 0x000006a8, 22976 }, /* Serbian_je */ { 0x000006b9, 22987 }, /* Serbian_LJE */ { 0x000006a9, 22999 }, /* Serbian_lje */ { 0x000006ba, 23011 }, /* Serbian_NJE */ { 0x000006aa, 23023 }, /* Serbian_nje */ { 0x000006bb, 23035 }, /* Serbian_TSHE */ { 0x000006ab, 23048 }, /* Serbian_tshe */ { 0x00000ac6, 23061 }, /* seveneighths */ { 0x01002087, 23074 }, /* sevensubscript */ { 0x01002077, 23089 }, /* sevensuperior */ { 0x0000ffe1, 23103 }, /* Shift_L */ { 0x0000ffe6, 23111 }, /* Shift_Lock */ { 0x0000ffe2, 23122 }, /* Shift_R */ { 0x00000aca, 23130 }, /* signaturemark */ { 0x00000aac, 23144 }, /* signifblank */ { 0x000008c9, 23156 }, /* similarequal */ { 0x0000ff3c, 23169 }, /* SingleCandidate */ { 0x00000afd, 23185 }, /* singlelowquotemark */ { 0x01000d85, 23204 }, /* Sinh_a */ { 0x01000d86, 23211 }, /* Sinh_aa */ { 0x01000dcf, 23219 }, /* Sinh_aa2 */ { 0x01000d87, 23228 }, /* Sinh_ae */ { 0x01000dd0, 23236 }, /* Sinh_ae2 */ { 0x01000d88, 23245 }, /* Sinh_aee */ { 0x01000dd1, 23254 }, /* Sinh_aee2 */ { 0x01000d93, 23264 }, /* Sinh_ai */ { 0x01000ddb, 23272 }, /* Sinh_ai2 */ { 0x01000dca, 23281 }, /* Sinh_al */ { 0x01000d96, 23289 }, /* Sinh_au */ { 0x01000dde, 23297 }, /* Sinh_au2 */ { 0x01000db6, 23306 }, /* Sinh_ba */ { 0x01000db7, 23314 }, /* Sinh_bha */ { 0x01000da0, 23323 }, /* Sinh_ca */ { 0x01000da1, 23331 }, /* Sinh_cha */ { 0x01000da9, 23340 }, /* Sinh_dda */ { 0x01000daa, 23349 }, /* Sinh_ddha */ { 0x01000daf, 23359 }, /* Sinh_dha */ { 0x01000db0, 23368 }, /* Sinh_dhha */ { 0x01000d91, 23378 }, /* Sinh_e */ { 0x01000dd9, 23385 }, /* Sinh_e2 */ { 0x01000d92, 23393 }, /* Sinh_ee */ { 0x01000dda, 23401 }, /* Sinh_ee2 */ { 0x01000dc6, 23410 }, /* Sinh_fa */ { 0x01000d9c, 23418 }, /* Sinh_ga */ { 0x01000d9d, 23426 }, /* Sinh_gha */ { 0x01000d83, 23435 }, /* Sinh_h2 */ { 0x01000dc4, 23443 }, /* Sinh_ha */ { 0x01000d89, 23451 }, /* Sinh_i */ { 0x01000dd2, 23458 }, /* Sinh_i2 */ { 0x01000d8a, 23466 }, /* Sinh_ii */ { 0x01000dd3, 23474 }, /* Sinh_ii2 */ { 0x01000da2, 23483 }, /* Sinh_ja */ { 0x01000da3, 23491 }, /* Sinh_jha */ { 0x01000da5, 23500 }, /* Sinh_jnya */ { 0x01000d9a, 23510 }, /* Sinh_ka */ { 0x01000d9b, 23518 }, /* Sinh_kha */ { 0x01000df4, 23527 }, /* Sinh_kunddaliya */ { 0x01000dbd, 23543 }, /* Sinh_la */ { 0x01000dc5, 23551 }, /* Sinh_lla */ { 0x01000d8f, 23560 }, /* Sinh_lu */ { 0x01000ddf, 23568 }, /* Sinh_lu2 */ { 0x01000d90, 23577 }, /* Sinh_luu */ { 0x01000df3, 23586 }, /* Sinh_luu2 */ { 0x01000db8, 23596 }, /* Sinh_ma */ { 0x01000db9, 23604 }, /* Sinh_mba */ { 0x01000db1, 23613 }, /* Sinh_na */ { 0x01000dac, 23621 }, /* Sinh_ndda */ { 0x01000db3, 23631 }, /* Sinh_ndha */ { 0x01000d82, 23641 }, /* Sinh_ng */ { 0x01000d9e, 23649 }, /* Sinh_ng2 */ { 0x01000d9f, 23658 }, /* Sinh_nga */ { 0x01000da6, 23667 }, /* Sinh_nja */ { 0x01000dab, 23676 }, /* Sinh_nna */ { 0x01000da4, 23685 }, /* Sinh_nya */ { 0x01000d94, 23694 }, /* Sinh_o */ { 0x01000ddc, 23701 }, /* Sinh_o2 */ { 0x01000d95, 23709 }, /* Sinh_oo */ { 0x01000ddd, 23717 }, /* Sinh_oo2 */ { 0x01000db4, 23726 }, /* Sinh_pa */ { 0x01000db5, 23734 }, /* Sinh_pha */ { 0x01000dbb, 23743 }, /* Sinh_ra */ { 0x01000d8d, 23751 }, /* Sinh_ri */ { 0x01000d8e, 23759 }, /* Sinh_rii */ { 0x01000dd8, 23768 }, /* Sinh_ru2 */ { 0x01000df2, 23777 }, /* Sinh_ruu2 */ { 0x01000dc3, 23787 }, /* Sinh_sa */ { 0x01000dc1, 23795 }, /* Sinh_sha */ { 0x01000dc2, 23804 }, /* Sinh_ssha */ { 0x01000dad, 23814 }, /* Sinh_tha */ { 0x01000dae, 23823 }, /* Sinh_thha */ { 0x01000da7, 23833 }, /* Sinh_tta */ { 0x01000da8, 23842 }, /* Sinh_ttha */ { 0x01000d8b, 23852 }, /* Sinh_u */ { 0x01000dd4, 23859 }, /* Sinh_u2 */ { 0x01000d8c, 23867 }, /* Sinh_uu */ { 0x01000dd6, 23875 }, /* Sinh_uu2 */ { 0x01000dc0, 23884 }, /* Sinh_va */ { 0x01000dba, 23892 }, /* Sinh_ya */ { 0x01002086, 23900 }, /* sixsubscript */ { 0x01002076, 23913 }, /* sixsuperior */ { 0x0000002f, 23925 }, /* slash */ { 0x0000fe73, 23931 }, /* SlowKeys_Enable */ { 0x000009e0, 23947 }, /* soliddiamond */ { 0x00000020, 23960 }, /* space */ { 0x0100221a, 23966 }, /* squareroot */ { 0x000000df, 23977 }, /* ssharp */ { 0x000000a3, 23984 }, /* sterling */ { 0x0000fe75, 23993 }, /* StickyKeys_Enable */ { 0x01002263, 24011 }, /* stricteq */ { 0x0000ff66, 24020 }, /* SunAgain */ { 0x0000ff7e, 24029 }, /* SunAltGraph */ { 0x1005ff77, 24041 }, /* SunAudioLowerVolume */ { 0x1005ff78, 24061 }, /* SunAudioMute */ { 0x1005ff79, 24074 }, /* SunAudioRaiseVolume */ { 0x0000ff20, 24094 }, /* SunCompose */ { 0x1005ff72, 24105 }, /* SunCopy */ { 0x1005ff75, 24113 }, /* SunCut */ { 0x1005ff10, 24120 }, /* SunF36 */ { 0x1005ff11, 24127 }, /* SunF37 */ { 0x1005ff03, 24134 }, /* SunFA_Acute */ { 0x1005ff05, 24146 }, /* SunFA_Cedilla */ { 0x1005ff01, 24160 }, /* SunFA_Circum */ { 0x1005ff04, 24173 }, /* SunFA_Diaeresis */ { 0x1005ff00, 24189 }, /* SunFA_Grave */ { 0x1005ff02, 24201 }, /* SunFA_Tilde */ { 0x0000ff68, 24213 }, /* SunFind */ { 0x1005ff71, 24221 }, /* SunFront */ { 0x1005ff73, 24230 }, /* SunOpen */ { 0x0000ff56, 24238 }, /* SunPageDown */ { 0x0000ff55, 24250 }, /* SunPageUp */ { 0x1005ff74, 24260 }, /* SunPaste */ { 0x1005ff76, 24269 }, /* SunPowerSwitch */ { 0x1005ff7d, 24284 }, /* SunPowerSwitchShift */ { 0x0000ff61, 24304 }, /* SunPrint_Screen */ { 0x1005ff70, 24320 }, /* SunProps */ { 0x0000ff69, 24329 }, /* SunStop */ { 0x1005ff60, 24337 }, /* SunSys_Req */ { 0x0000ff65, 24348 }, /* SunUndo */ { 0x1005ff7a, 24356 }, /* SunVideoDegauss */ { 0x1005ff7b, 24372 }, /* SunVideoLowerBrightness */ { 0x1005ff7c, 24396 }, /* SunVideoRaiseBrightness */ { 0x0000ffeb, 24420 }, /* Super_L */ { 0x0000ffec, 24428 }, /* Super_R */ { 0x0000ff15, 24436 }, /* Sys_Req */ { 0x1000ff6d, 24444 }, /* System */ { 0x00000054, 24451 }, /* T */ { 0x00000074, 24453 }, /* t */ { 0x0000ff09, 24455 }, /* Tab */ { 0x01001e6a, 24459 }, /* Tabovedot */ { 0x01001e6b, 24469 }, /* tabovedot */ { 0x000001ab, 24479 }, /* Tcaron */ { 0x000001bb, 24486 }, /* tcaron */ { 0x000001de, 24493 }, /* Tcedilla */ { 0x000001fe, 24502 }, /* tcedilla */ { 0x00000af9, 24511 }, /* telephone */ { 0x00000afa, 24521 }, /* telephonerecorder */ { 0x0000fed5, 24539 }, /* Terminate_Server */ { 0x00000ddf, 24556 }, /* Thai_baht */ { 0x00000dba, 24566 }, /* Thai_bobaimai */ { 0x00000da8, 24580 }, /* Thai_chochan */ { 0x00000daa, 24593 }, /* Thai_chochang */ { 0x00000da9, 24607 }, /* Thai_choching */ { 0x00000dac, 24621 }, /* Thai_chochoe */ { 0x00000dae, 24634 }, /* Thai_dochada */ { 0x00000db4, 24647 }, /* Thai_dodek */ { 0x00000dbd, 24658 }, /* Thai_fofa */ { 0x00000dbf, 24668 }, /* Thai_fofan */ { 0x00000dcb, 24679 }, /* Thai_hohip */ { 0x00000dce, 24690 }, /* Thai_honokhuk */ { 0x00000da2, 24704 }, /* Thai_khokhai */ { 0x00000da5, 24717 }, /* Thai_khokhon */ { 0x00000da3, 24730 }, /* Thai_khokhuat */ { 0x00000da4, 24744 }, /* Thai_khokhwai */ { 0x00000da6, 24758 }, /* Thai_khorakhang */ { 0x00000da1, 24774 }, /* Thai_kokai */ { 0x00000de5, 24785 }, /* Thai_lakkhangyao */ { 0x00000df7, 24802 }, /* Thai_lekchet */ { 0x00000df5, 24815 }, /* Thai_lekha */ { 0x00000df6, 24826 }, /* Thai_lekhok */ { 0x00000df9, 24838 }, /* Thai_lekkao */ { 0x00000df1, 24850 }, /* Thai_leknung */ { 0x00000df8, 24863 }, /* Thai_lekpaet */ { 0x00000df3, 24876 }, /* Thai_leksam */ { 0x00000df4, 24888 }, /* Thai_leksi */ { 0x00000df2, 24899 }, /* Thai_leksong */ { 0x00000df0, 24912 }, /* Thai_leksun */ { 0x00000dcc, 24924 }, /* Thai_lochula */ { 0x00000dc5, 24937 }, /* Thai_loling */ { 0x00000dc6, 24949 }, /* Thai_lu */ { 0x00000deb, 24957 }, /* Thai_maichattawa */ { 0x00000de8, 24974 }, /* Thai_maiek */ { 0x00000dd1, 24985 }, /* Thai_maihanakat */ { 0x00000dde, 25001 }, /* Thai_maihanakat_maitho */ { 0x00000de7, 25024 }, /* Thai_maitaikhu */ { 0x00000de9, 25039 }, /* Thai_maitho */ { 0x00000dea, 25051 }, /* Thai_maitri */ { 0x00000de6, 25063 }, /* Thai_maiyamok */ { 0x00000dc1, 25077 }, /* Thai_moma */ { 0x00000da7, 25087 }, /* Thai_ngongu */ { 0x00000ded, 25099 }, /* Thai_nikhahit */ { 0x00000db3, 25113 }, /* Thai_nonen */ { 0x00000db9, 25124 }, /* Thai_nonu */ { 0x00000dcd, 25134 }, /* Thai_oang */ { 0x00000dcf, 25144 }, /* Thai_paiyannoi */ { 0x00000dda, 25159 }, /* Thai_phinthu */ { 0x00000dbe, 25172 }, /* Thai_phophan */ { 0x00000dbc, 25185 }, /* Thai_phophung */ { 0x00000dc0, 25199 }, /* Thai_phosamphao */ { 0x00000dbb, 25215 }, /* Thai_popla */ { 0x00000dc3, 25226 }, /* Thai_rorua */ { 0x00000dc4, 25237 }, /* Thai_ru */ { 0x00000dd0, 25245 }, /* Thai_saraa */ { 0x00000dd2, 25256 }, /* Thai_saraaa */ { 0x00000de1, 25268 }, /* Thai_saraae */ { 0x00000de4, 25280 }, /* Thai_saraaimaimalai */ { 0x00000de3, 25300 }, /* Thai_saraaimaimuan */ { 0x00000dd3, 25319 }, /* Thai_saraam */ { 0x00000de0, 25331 }, /* Thai_sarae */ { 0x00000dd4, 25342 }, /* Thai_sarai */ { 0x00000dd5, 25353 }, /* Thai_saraii */ { 0x00000de2, 25365 }, /* Thai_sarao */ { 0x00000dd8, 25376 }, /* Thai_sarau */ { 0x00000dd6, 25387 }, /* Thai_saraue */ { 0x00000dd7, 25399 }, /* Thai_sarauee */ { 0x00000dd9, 25412 }, /* Thai_sarauu */ { 0x00000dc9, 25424 }, /* Thai_sorusi */ { 0x00000dc8, 25436 }, /* Thai_sosala */ { 0x00000dab, 25448 }, /* Thai_soso */ { 0x00000dca, 25458 }, /* Thai_sosua */ { 0x00000dec, 25469 }, /* Thai_thanthakhat */ { 0x00000db1, 25486 }, /* Thai_thonangmontho */ { 0x00000db2, 25505 }, /* Thai_thophuthao */ { 0x00000db7, 25521 }, /* Thai_thothahan */ { 0x00000db0, 25536 }, /* Thai_thothan */ { 0x00000db8, 25549 }, /* Thai_thothong */ { 0x00000db6, 25563 }, /* Thai_thothung */ { 0x00000daf, 25577 }, /* Thai_topatak */ { 0x00000db5, 25590 }, /* Thai_totao */ { 0x00000dc7, 25601 }, /* Thai_wowaen */ { 0x00000dc2, 25613 }, /* Thai_yoyak */ { 0x00000dad, 25624 }, /* Thai_yoying */ { 0x000008c0, 25636 }, /* therefore */ { 0x00000aa7, 25646 }, /* thinspace */ { 0x000000de, 25656 }, /* THORN */ { 0x000000de, 25662 }, /* Thorn */ { 0x000000fe, 25668 }, /* thorn */ { 0x00000ac4, 25674 }, /* threeeighths */ { 0x00000ab4, 25687 }, /* threefifths */ { 0x000000be, 25699 }, /* threequarters */ { 0x01002083, 25713 }, /* threesubscript */ { 0x000000b3, 25728 }, /* threesuperior */ { 0x0100222d, 25742 }, /* tintegral */ { 0x000008a4, 25752 }, /* topintegral */ { 0x000008ab, 25764 }, /* topleftparens */ { 0x000008a2, 25778 }, /* topleftradical */ { 0x000008a7, 25793 }, /* topleftsqbracket */ { 0x000008b1, 25810 }, /* topleftsummation */ { 0x000008ad, 25827 }, /* toprightparens */ { 0x000008a9, 25842 }, /* toprightsqbracket */ { 0x000008b5, 25860 }, /* toprightsummation */ { 0x000009f7, 25878 }, /* topt */ { 0x000008b3, 25883 }, /* topvertsummationconnector */ { 0x0000ff2b, 25909 }, /* Touroku */ { 0x00000ac9, 25917 }, /* trademark */ { 0x00000acb, 25927 }, /* trademarkincircle */ { 0x000003ac, 25945 }, /* Tslash */ { 0x000003bc, 25952 }, /* tslash */ { 0x00000ab3, 25959 }, /* twofifths */ { 0x01002082, 25969 }, /* twosubscript */ { 0x000000b2, 25982 }, /* twosuperior */ { 0x00000ab1, 25994 }, /* twothirds */ { 0x00000055, 26004 }, /* U */ { 0x00000075, 26006 }, /* u */ { 0x000000da, 26008 }, /* Uacute */ { 0x000000fa, 26015 }, /* uacute */ { 0x01001ee4, 26022 }, /* Ubelowdot */ { 0x01001ee5, 26032 }, /* ubelowdot */ { 0x000002dd, 26042 }, /* Ubreve */ { 0x000002fd, 26049 }, /* ubreve */ { 0x000000db, 26056 }, /* Ucircumflex */ { 0x000000fb, 26068 }, /* ucircumflex */ { 0x000000dc, 26080 }, /* Udiaeresis */ { 0x000000fc, 26091 }, /* udiaeresis */ { 0x000001db, 26102 }, /* Udoubleacute */ { 0x000001fb, 26115 }, /* udoubleacute */ { 0x000000d9, 26128 }, /* Ugrave */ { 0x000000f9, 26135 }, /* ugrave */ { 0x01001ee6, 26142 }, /* Uhook */ { 0x01001ee7, 26148 }, /* uhook */ { 0x010001af, 26154 }, /* Uhorn */ { 0x010001b0, 26160 }, /* uhorn */ { 0x01001ee8, 26166 }, /* Uhornacute */ { 0x01001ee9, 26177 }, /* uhornacute */ { 0x01001ef0, 26188 }, /* Uhornbelowdot */ { 0x01001ef1, 26202 }, /* uhornbelowdot */ { 0x01001eea, 26216 }, /* Uhorngrave */ { 0x01001eeb, 26227 }, /* uhorngrave */ { 0x01001eec, 26238 }, /* Uhornhook */ { 0x01001eed, 26248 }, /* uhornhook */ { 0x01001eee, 26258 }, /* Uhorntilde */ { 0x01001eef, 26269 }, /* uhorntilde */ { 0x000006bd, 26280 }, /* Ukrainian_GHE_WITH_UPTURN */ { 0x000006ad, 26306 }, /* Ukrainian_ghe_with_upturn */ { 0x000006b6, 26332 }, /* Ukrainian_I */ { 0x000006a6, 26344 }, /* Ukrainian_i */ { 0x000006b4, 26356 }, /* Ukrainian_IE */ { 0x000006a4, 26369 }, /* Ukrainian_ie */ { 0x000006b7, 26382 }, /* Ukrainian_YI */ { 0x000006a7, 26395 }, /* Ukrainian_yi */ { 0x000006b6, 26408 }, /* Ukranian_I */ { 0x000006a6, 26419 }, /* Ukranian_i */ { 0x000006b4, 26430 }, /* Ukranian_JE */ { 0x000006a4, 26442 }, /* Ukranian_je */ { 0x000006b7, 26454 }, /* Ukranian_YI */ { 0x000006a7, 26466 }, /* Ukranian_yi */ { 0x000003de, 26478 }, /* Umacron */ { 0x000003fe, 26486 }, /* umacron */ { 0x00000bc6, 26494 }, /* underbar */ { 0x0000005f, 26503 }, /* underscore */ { 0x0000ff65, 26514 }, /* Undo */ { 0x000008dd, 26519 }, /* union */ { 0x000003d9, 26525 }, /* Uogonek */ { 0x000003f9, 26533 }, /* uogonek */ { 0x0000ff52, 26541 }, /* Up */ { 0x000008fc, 26544 }, /* uparrow */ { 0x00000ba9, 26552 }, /* upcaret */ { 0x000009ec, 26560 }, /* upleftcorner */ { 0x000009eb, 26573 }, /* uprightcorner */ { 0x00000bc3, 26587 }, /* upshoe */ { 0x00000bd3, 26594 }, /* upstile */ { 0x00000bce, 26602 }, /* uptack */ { 0x000001d9, 26609 }, /* Uring */ { 0x000001f9, 26615 }, /* uring */ { 0x1000ff6e, 26621 }, /* User */ { 0x000003dd, 26626 }, /* Utilde */ { 0x000003fd, 26633 }, /* utilde */ { 0x00000056, 26640 }, /* V */ { 0x00000076, 26642 }, /* v */ { 0x000008c1, 26644 }, /* variation */ { 0x000009f8, 26654 }, /* vertbar */ { 0x000008a6, 26662 }, /* vertconnector */ { 0x000004de, 26676 }, /* voicedsound */ { 0x00ffffff, 26688 }, /* VoidSymbol */ { 0x000009e9, 26699 }, /* vt */ { 0x00000057, 26702 }, /* W */ { 0x00000077, 26704 }, /* w */ { 0x01001e82, 26706 }, /* Wacute */ { 0x01001e83, 26713 }, /* wacute */ { 0x01000174, 26720 }, /* Wcircumflex */ { 0x01000175, 26732 }, /* wcircumflex */ { 0x01001e84, 26744 }, /* Wdiaeresis */ { 0x01001e85, 26755 }, /* wdiaeresis */ { 0x01001e80, 26766 }, /* Wgrave */ { 0x01001e81, 26773 }, /* wgrave */ { 0x010020a9, 26780 }, /* WonSign */ { 0x00000058, 26788 }, /* X */ { 0x00000078, 26790 }, /* x */ { 0x01001e8a, 26792 }, /* Xabovedot */ { 0x01001e8b, 26802 }, /* xabovedot */ { 0x100811b9, 26812 }, /* XF8610ChannelsDown */ { 0x100811b8, 26831 }, /* XF8610ChannelsUp */ { 0x1008126f, 26848 }, /* XF863DMode */ { 0x1008124e, 26859 }, /* XF86Accessibility */ { 0x1008ff39, 26877 }, /* XF86AddFavorite */ { 0x100811ad, 26893 }, /* XF86Addressbook */ { 0x10081230, 26909 }, /* XF86ALSToggle */ { 0x1008ff50, 26923 }, /* XF86ApplicationLeft */ { 0x1008ff51, 26943 }, /* XF86ApplicationRight */ { 0x10081244, 26964 }, /* XF86AppSelect */ { 0x10081177, 26978 }, /* XF86AspectRatio */ { 0x10081247, 26994 }, /* XF86Assistant */ { 0x1008121c, 27008 }, /* XF86AttendantOff */ { 0x1008121b, 27025 }, /* XF86AttendantOn */ { 0x1008121d, 27041 }, /* XF86AttendantToggle */ { 0x10081188, 27061 }, /* XF86Audio */ { 0x10081175, 27071 }, /* XF86AudioChannelMode */ { 0x1008ff9b, 27092 }, /* XF86AudioCycleTrack */ { 0x1008126e, 27112 }, /* XF86AudioDesc */ { 0x1008ff97, 27126 }, /* XF86AudioForward */ { 0x1008ff11, 27143 }, /* XF86AudioLowerVolume */ { 0x1008ff32, 27164 }, /* XF86AudioMedia */ { 0x1008ffb2, 27179 }, /* XF86AudioMicMute */ { 0x1008ff12, 27196 }, /* XF86AudioMute */ { 0x1008ff17, 27210 }, /* XF86AudioNext */ { 0x1008ff31, 27224 }, /* XF86AudioPause */ { 0x1008ff14, 27239 }, /* XF86AudioPlay */ { 0x1008ffb6, 27253 }, /* XF86AudioPreset */ { 0x1008ff16, 27269 }, /* XF86AudioPrev */ { 0x1008ff13, 27283 }, /* XF86AudioRaiseVolume */ { 0x1008ff99, 27304 }, /* XF86AudioRandomPlay */ { 0x1008ff1c, 27324 }, /* XF86AudioRecord */ { 0x1008ff98, 27340 }, /* XF86AudioRepeat */ { 0x1008ff3e, 27356 }, /* XF86AudioRewind */ { 0x1008ff15, 27372 }, /* XF86AudioStop */ { 0x1008127d, 27386 }, /* XF86AutopilotEngageToggle */ { 0x1008ff8d, 27412 }, /* XF86Away */ { 0x1008ff26, 27421 }, /* XF86Back */ { 0x1008ff3f, 27430 }, /* XF86BackForward */ { 0x1008ff93, 27446 }, /* XF86Battery */ { 0x1008ffa6, 27458 }, /* XF86Blue */ { 0x1008ff94, 27467 }, /* XF86Bluetooth */ { 0x1008ff52, 27481 }, /* XF86Book */ { 0x1008119b, 27490 }, /* XF86Break */ { 0x1008ff3b, 27500 }, /* XF86BrightnessAdjust */ { 0x100810f4, 27521 }, /* XF86BrightnessAuto */ { 0x10081251, 27540 }, /* XF86BrightnessMax */ { 0x10081250, 27558 }, /* XF86BrightnessMin */ { 0x10081240, 27576 }, /* XF86Buttonconfig */ { 0x1008ff54, 27593 }, /* XF86Calculater */ { 0x1008ff1d, 27608 }, /* XF86Calculator */ { 0x1008ff20, 27623 }, /* XF86Calendar */ { 0x1008124c, 27636 }, /* XF86CameraAccessDisable */ { 0x1008124b, 27660 }, /* XF86CameraAccessEnable */ { 0x1008124d, 27683 }, /* XF86CameraAccessToggle */ { 0x10081218, 27706 }, /* XF86CameraDown */ { 0x10081210, 27721 }, /* XF86CameraFocus */ { 0x10081219, 27737 }, /* XF86CameraLeft */ { 0x1008121a, 27752 }, /* XF86CameraRight */ { 0x10081217, 27768 }, /* XF86CameraUp */ { 0x10081215, 27781 }, /* XF86CameraZoomIn */ { 0x10081216, 27798 }, /* XF86CameraZoomOut */ { 0x1008ff53, 27816 }, /* XF86CD */ { 0x10081193, 27823 }, /* XF86ChannelDown */ { 0x10081192, 27839 }, /* XF86ChannelUp */ { 0x1008ff55, 27853 }, /* XF86Clear */ { 0x1008fe21, 27863 }, /* XF86ClearGrab */ { 0x10081286, 27877 }, /* XF86ClearvuSonar */ { 0x1008ff56, 27894 }, /* XF86Close */ { 0x1008ff3d, 27904 }, /* XF86Community */ { 0x100811b6, 27918 }, /* XF86ContextMenu */ { 0x1008ff22, 27934 }, /* XF86ContrastAdjust */ { 0x10081243, 27953 }, /* XF86ControlPanel */ { 0x1008ff57, 27970 }, /* XF86Copy */ { 0x1008ff58, 27979 }, /* XF86Cut */ { 0x1008ff9c, 27987 }, /* XF86CycleAngle */ { 0x10081277, 28002 }, /* XF86Data */ { 0x100811aa, 28011 }, /* XF86Database */ { 0x1008124a, 28024 }, /* XF86Dictate */ { 0x1008ff59, 28036 }, /* XF86Display */ { 0x100810f5, 28048 }, /* XF86DisplayOff */ { 0x100811af, 28063 }, /* XF86DisplayToggle */ { 0x1008ff5b, 28081 }, /* XF86Documents */ { 0x1008124f, 28095 }, /* XF86DoNotDisturb */ { 0x1008ff5a, 28112 }, /* XF86DOS */ { 0x10081283, 28120 }, /* XF86DualRangeRadar */ { 0x10081185, 28139 }, /* XF86DVD */ { 0x100811a6, 28147 }, /* XF86Editor */ { 0x1008ff2c, 28158 }, /* XF86Eject */ { 0x10081249, 28168 }, /* XF86EmojiPicker */ { 0x1008ff5c, 28184 }, /* XF86Excel */ { 0x1008ff5d, 28194 }, /* XF86Explorer */ { 0x10081275, 28207 }, /* XF86FastReverse */ { 0x1008ff30, 28223 }, /* XF86Favorites */ { 0x1008ff3c, 28237 }, /* XF86Finance */ { 0x10081281, 28249 }, /* XF86FishingChart */ { 0x100811d0, 28266 }, /* XF86Fn */ { 0x100811de, 28273 }, /* XF86Fn_1 */ { 0x100811df, 28282 }, /* XF86Fn_2 */ { 0x100811e4, 28291 }, /* XF86Fn_B */ { 0x100811e0, 28300 }, /* XF86Fn_D */ { 0x100811e1, 28309 }, /* XF86Fn_E */ { 0x100811d1, 28318 }, /* XF86Fn_Esc */ { 0x100811e2, 28329 }, /* XF86Fn_F */ { 0x100811d2, 28338 }, /* XF86Fn_F1 */ { 0x100811db, 28348 }, /* XF86Fn_F10 */ { 0x100811dc, 28359 }, /* XF86Fn_F11 */ { 0x100811dd, 28370 }, /* XF86Fn_F12 */ { 0x100811d3, 28381 }, /* XF86Fn_F2 */ { 0x100811d4, 28391 }, /* XF86Fn_F3 */ { 0x100811d5, 28401 }, /* XF86Fn_F4 */ { 0x100811d6, 28411 }, /* XF86Fn_F5 */ { 0x100811d7, 28421 }, /* XF86Fn_F6 */ { 0x100811d8, 28431 }, /* XF86Fn_F7 */ { 0x100811d9, 28441 }, /* XF86Fn_F8 */ { 0x100811da, 28451 }, /* XF86Fn_F9 */ { 0x100811e3, 28461 }, /* XF86Fn_S */ { 0x100811e5, 28470 }, /* XF86FnRightShift */ { 0x1008ff27, 28487 }, /* XF86Forward */ { 0x1008ff9d, 28499 }, /* XF86FrameBack */ { 0x1008ff9e, 28513 }, /* XF86FrameForward */ { 0x1008ffb8, 28530 }, /* XF86FullScreen */ { 0x1008ff5e, 28545 }, /* XF86Game */ { 0x1008ff5f, 28554 }, /* XF86Go */ { 0x10081162, 28561 }, /* XF86GoTo */ { 0x100811a8, 28570 }, /* XF86GraphicsEditor */ { 0x1008ffa4, 28589 }, /* XF86Green */ { 0x100811be, 28599 }, /* XF86HangupPhone */ { 0x1008ffa8, 28615 }, /* XF86Hibernate */ { 0x1008ff37, 28629 }, /* XF86History */ { 0x1008ff18, 28641 }, /* XF86HomePage */ { 0x1008ff3a, 28654 }, /* XF86HotLinks */ { 0x100811ba, 28667 }, /* XF86Images */ { 0x10081166, 28678 }, /* XF86Info */ { 0x1008ff60, 28687 }, /* XF86iTouch */ { 0x10081242, 28698 }, /* XF86Journal */ { 0x1008ff06, 28710 }, /* XF86KbdBrightnessDown */ { 0x1008ff05, 28732 }, /* XF86KbdBrightnessUp */ { 0x10081264, 28752 }, /* XF86KbdInputAssistAccept */ { 0x10081265, 28777 }, /* XF86KbdInputAssistCancel */ { 0x10081261, 28802 }, /* XF86KbdInputAssistNext */ { 0x10081263, 28825 }, /* XF86KbdInputAssistNextgroup */ { 0x10081260, 28853 }, /* XF86KbdInputAssistPrev */ { 0x10081262, 28876 }, /* XF86KbdInputAssistPrevgroup */ { 0x100812b8, 28904 }, /* XF86KbdLcdMenu1 */ { 0x100812b9, 28920 }, /* XF86KbdLcdMenu2 */ { 0x100812ba, 28936 }, /* XF86KbdLcdMenu3 */ { 0x100812bb, 28952 }, /* XF86KbdLcdMenu4 */ { 0x100812bc, 28968 }, /* XF86KbdLcdMenu5 */ { 0x1008ff04, 28984 }, /* XF86KbdLightOnOff */ { 0x1008ffb3, 29002 }, /* XF86Keyboard */ { 0x1008ff40, 29015 }, /* XF86Launch0 */ { 0x1008ff41, 29027 }, /* XF86Launch1 */ { 0x1008ff42, 29039 }, /* XF86Launch2 */ { 0x1008ff43, 29051 }, /* XF86Launch3 */ { 0x1008ff44, 29063 }, /* XF86Launch4 */ { 0x1008ff45, 29075 }, /* XF86Launch5 */ { 0x1008ff46, 29087 }, /* XF86Launch6 */ { 0x1008ff47, 29099 }, /* XF86Launch7 */ { 0x1008ff48, 29111 }, /* XF86Launch8 */ { 0x1008ff49, 29123 }, /* XF86Launch9 */ { 0x1008ff4a, 29135 }, /* XF86LaunchA */ { 0x1008ff4b, 29147 }, /* XF86LaunchB */ { 0x1008ff4c, 29159 }, /* XF86LaunchC */ { 0x1008ff4d, 29171 }, /* XF86LaunchD */ { 0x1008ff4e, 29183 }, /* XF86LaunchE */ { 0x1008ff4f, 29195 }, /* XF86LaunchF */ { 0x10081269, 29207 }, /* XF86LeftDown */ { 0x10081268, 29220 }, /* XF86LeftUp */ { 0x1008ff35, 29231 }, /* XF86LightBulb */ { 0x1008121e, 29245 }, /* XF86LightsToggle */ { 0x100811bf, 29262 }, /* XF86LinkPhone */ { 0x1008fe25, 29276 }, /* XF86LogGrabInfo */ { 0x1008ff61, 29292 }, /* XF86LogOff */ { 0x1008fe24, 29303 }, /* XF86LogWindowTree */ { 0x10081290, 29321 }, /* XF86Macro1 */ { 0x10081299, 29332 }, /* XF86Macro10 */ { 0x1008129a, 29344 }, /* XF86Macro11 */ { 0x1008129b, 29356 }, /* XF86Macro12 */ { 0x1008129c, 29368 }, /* XF86Macro13 */ { 0x1008129d, 29380 }, /* XF86Macro14 */ { 0x1008129e, 29392 }, /* XF86Macro15 */ { 0x1008129f, 29404 }, /* XF86Macro16 */ { 0x100812a0, 29416 }, /* XF86Macro17 */ { 0x100812a1, 29428 }, /* XF86Macro18 */ { 0x100812a2, 29440 }, /* XF86Macro19 */ { 0x10081291, 29452 }, /* XF86Macro2 */ { 0x100812a3, 29463 }, /* XF86Macro20 */ { 0x100812a4, 29475 }, /* XF86Macro21 */ { 0x100812a5, 29487 }, /* XF86Macro22 */ { 0x100812a6, 29499 }, /* XF86Macro23 */ { 0x100812a7, 29511 }, /* XF86Macro24 */ { 0x100812a8, 29523 }, /* XF86Macro25 */ { 0x100812a9, 29535 }, /* XF86Macro26 */ { 0x100812aa, 29547 }, /* XF86Macro27 */ { 0x100812ab, 29559 }, /* XF86Macro28 */ { 0x100812ac, 29571 }, /* XF86Macro29 */ { 0x10081292, 29583 }, /* XF86Macro3 */ { 0x100812ad, 29594 }, /* XF86Macro30 */ { 0x10081293, 29606 }, /* XF86Macro4 */ { 0x10081294, 29617 }, /* XF86Macro5 */ { 0x10081295, 29628 }, /* XF86Macro6 */ { 0x10081296, 29639 }, /* XF86Macro7 */ { 0x10081297, 29650 }, /* XF86Macro8 */ { 0x10081298, 29661 }, /* XF86Macro9 */ { 0x100812b3, 29672 }, /* XF86MacroPreset1 */ { 0x100812b4, 29689 }, /* XF86MacroPreset2 */ { 0x100812b5, 29706 }, /* XF86MacroPreset3 */ { 0x100812b2, 29723 }, /* XF86MacroPresetCycle */ { 0x100812b0, 29744 }, /* XF86MacroRecordStart */ { 0x100812b1, 29765 }, /* XF86MacroRecordStop */ { 0x1008ff19, 29785 }, /* XF86Mail */ { 0x1008ff90, 29794 }, /* XF86MailForward */ { 0x1008ff62, 29810 }, /* XF86Market */ { 0x1008127e, 29821 }, /* XF86MarkWaypoint */ { 0x10081170, 29838 }, /* XF86MediaLanguageMenu */ { 0x10081183, 29860 }, /* XF86MediaPlayer */ { 0x10081199, 29876 }, /* XF86MediaPlaySlow */ { 0x100811b7, 29894 }, /* XF86MediaRepeat */ { 0x10081186, 29910 }, /* XF86MediaSelectAuxiliary */ { 0x1008117a, 29935 }, /* XF86MediaSelectCable */ { 0x1008ff53, 29956 }, /* XF86MediaSelectCD */ { 0x10081185, 29974 }, /* XF86MediaSelectDVD */ { 0x1008116e, 29993 }, /* XF86MediaSelectHome */ { 0x10081178, 30013 }, /* XF86MediaSelectPC */ { 0x1008116a, 30031 }, /* XF86MediaSelectProgramGuide */ { 0x10081181, 30059 }, /* XF86MediaSelectRadio */ { 0x1008117d, 30080 }, /* XF86MediaSelectSatellite */ { 0x10081180, 30105 }, /* XF86MediaSelectTape */ { 0x10081184, 30125 }, /* XF86MediaSelectTeletext */ { 0x10081182, 30149 }, /* XF86MediaSelectTuner */ { 0x10081179, 30170 }, /* XF86MediaSelectTV */ { 0x1008117b, 30188 }, /* XF86MediaSelectVCR */ { 0x1008117c, 30207 }, /* XF86MediaSelectVCRPlus */ { 0x10081171, 30230 }, /* XF86MediaTitleMenu */ { 0x1008126b, 30249 }, /* XF86MediaTopMenu */ { 0x1008ff63, 30266 }, /* XF86Meeting */ { 0x1008ff1e, 30278 }, /* XF86Memo */ { 0x1008ff65, 30287 }, /* XF86MenuKB */ { 0x1008ff66, 30298 }, /* XF86MenuPB */ { 0x1008ff8e, 30309 }, /* XF86Messenger */ { 0x1008ff01, 30323 }, /* XF86ModeLock */ { 0x100810f4, 30336 }, /* XF86MonBrightnessAuto */ { 0x1008ff07, 30358 }, /* XF86MonBrightnessCycle */ { 0x1008ff03, 30381 }, /* XF86MonBrightnessDown */ { 0x1008ff02, 30403 }, /* XF86MonBrightnessUp */ { 0x1008ff92, 30423 }, /* XF86Music */ { 0x1008ff33, 30433 }, /* XF86MyComputer */ { 0x1008ff67, 30448 }, /* XF86MySites */ { 0x10081280, 30460 }, /* XF86NavChart */ { 0x10081288, 30473 }, /* XF86NavInfo */ { 0x1008ff68, 30485 }, /* XF86New */ { 0x1008ff69, 30493 }, /* XF86News */ { 0x1008fe22, 30502 }, /* XF86Next_VMode */ { 0x1008127b, 30517 }, /* XF86NextElement */ { 0x10081270, 30533 }, /* XF86NextFavorite */ { 0x100811bc, 30550 }, /* XF86NotificationCenter */ { 0x1008119d, 30573 }, /* XF86NumberEntryMode */ { 0x10081200, 30593 }, /* XF86Numeric0 */ { 0x10081201, 30606 }, /* XF86Numeric1 */ { 0x1008126c, 30619 }, /* XF86Numeric11 */ { 0x1008126d, 30633 }, /* XF86Numeric12 */ { 0x10081202, 30647 }, /* XF86Numeric2 */ { 0x10081203, 30660 }, /* XF86Numeric3 */ { 0x10081204, 30673 }, /* XF86Numeric4 */ { 0x10081205, 30686 }, /* XF86Numeric5 */ { 0x10081206, 30699 }, /* XF86Numeric6 */ { 0x10081207, 30712 }, /* XF86Numeric7 */ { 0x10081208, 30725 }, /* XF86Numeric8 */ { 0x10081209, 30738 }, /* XF86Numeric9 */ { 0x1008120c, 30751 }, /* XF86NumericA */ { 0x1008120d, 30764 }, /* XF86NumericB */ { 0x1008120e, 30777 }, /* XF86NumericC */ { 0x1008120f, 30790 }, /* XF86NumericD */ { 0x1008120b, 30803 }, /* XF86NumericPound */ { 0x1008120a, 30820 }, /* XF86NumericStar */ { 0x1008ff6a, 30836 }, /* XF86OfficeHome */ { 0x10081160, 30851 }, /* XF86OK */ { 0x10081278, 30858 }, /* XF86OnScreenKeyboard */ { 0x1008ff6b, 30879 }, /* XF86Open */ { 0x1008ff38, 30888 }, /* XF86OpenURL */ { 0x1008ff6c, 30900 }, /* XF86Option */ { 0x1008ff6d, 30911 }, /* XF86Paste */ { 0x10081272, 30921 }, /* XF86PauseRecord */ { 0x100812bd, 30937 }, /* XF86PerformanceMode */ { 0x1008ff6e, 30957 }, /* XF86Phone */ { 0x100811bd, 30967 }, /* XF86PickupPhone */ { 0x1008ff91, 30983 }, /* XF86Pictures */ { 0x1008ff21, 30996 }, /* XF86PowerDown */ { 0x1008ff2a, 31010 }, /* XF86PowerOff */ { 0x100811a9, 31023 }, /* XF86Presentation */ { 0x1008fe23, 31040 }, /* XF86Prev_VMode */ { 0x1008127c, 31055 }, /* XF86PreviousElement */ { 0x10081279, 31075 }, /* XF86PrivacyScreenToggle */ { 0x1008ff70, 31099 }, /* XF86Q */ { 0x10081284, 31105 }, /* XF86RadarOverlay */ { 0x1008ffa3, 31122 }, /* XF86Red */ { 0x1008ff29, 31130 }, /* XF86Refresh */ { 0x10081232, 31142 }, /* XF86RefreshRateToggle */ { 0x1008ff73, 31164 }, /* XF86Reload */ { 0x1008ff72, 31175 }, /* XF86Reply */ { 0x1008ffb5, 31185 }, /* XF86RFKill */ { 0x10081267, 31196 }, /* XF86RightDown */ { 0x10081266, 31210 }, /* XF86RightUp */ { 0x1008ff24, 31222 }, /* XF86RockerDown */ { 0x1008ff25, 31237 }, /* XF86RockerEnter */ { 0x1008ff23, 31253 }, /* XF86RockerUp */ { 0x1008126a, 31266 }, /* XF86RootMenu */ { 0x1008ff74, 31279 }, /* XF86RotateWindows */ { 0x1008ff76, 31297 }, /* XF86RotationKB */ { 0x1008ffb7, 31312 }, /* XF86RotationLockToggle */ { 0x1008ff75, 31335 }, /* XF86RotationPB */ { 0x1008ff77, 31350 }, /* XF86Save */ { 0x1008ff2d, 31359 }, /* XF86ScreenSaver */ { 0x10081245, 31375 }, /* XF86Screensaver */ { 0x1008ff7a, 31391 }, /* XF86ScrollClick */ { 0x1008ff79, 31407 }, /* XF86ScrollDown */ { 0x1008ff78, 31422 }, /* XF86ScrollUp */ { 0x1008ff1b, 31435 }, /* XF86Search */ { 0x1008ffa0, 31446 }, /* XF86Select */ { 0x1008127a, 31457 }, /* XF86SelectiveScreenshot */ { 0x1008ff7b, 31481 }, /* XF86Send */ { 0x1008ff36, 31490 }, /* XF86Shop */ { 0x10081287, 31499 }, /* XF86SidevuSonar */ { 0x10081282, 31515 }, /* XF86SingleRangeRadar */ { 0x1008ff2f, 31536 }, /* XF86Sleep */ { 0x10081276, 31546 }, /* XF86SlowReverse */ { 0x1008127f, 31562 }, /* XF86Sos */ { 0x1008ff7c, 31570 }, /* XF86Spell */ { 0x100811b0, 31580 }, /* XF86SpellCheck */ { 0x1008ff7d, 31595 }, /* XF86SplitScreen */ { 0x100810dc, 31611 }, /* XF86Sport */ { 0x1008ff10, 31621 }, /* XF86Standby */ { 0x1008ff1a, 31633 }, /* XF86Start */ { 0x1008ff28, 31643 }, /* XF86Stop */ { 0x10081271, 31652 }, /* XF86StopRecord */ { 0x1008ff9a, 31667 }, /* XF86Subtitle */ { 0x1008ff7e, 31680 }, /* XF86Support */ { 0x1008ffa7, 31692 }, /* XF86Suspend */ { 0x1008fe01, 31704 }, /* XF86Switch_VT_1 */ { 0x1008fe0a, 31720 }, /* XF86Switch_VT_10 */ { 0x1008fe0b, 31737 }, /* XF86Switch_VT_11 */ { 0x1008fe0c, 31754 }, /* XF86Switch_VT_12 */ { 0x1008fe02, 31771 }, /* XF86Switch_VT_2 */ { 0x1008fe03, 31787 }, /* XF86Switch_VT_3 */ { 0x1008fe04, 31803 }, /* XF86Switch_VT_4 */ { 0x1008fe05, 31819 }, /* XF86Switch_VT_5 */ { 0x1008fe06, 31835 }, /* XF86Switch_VT_6 */ { 0x1008fe07, 31851 }, /* XF86Switch_VT_7 */ { 0x1008fe08, 31867 }, /* XF86Switch_VT_8 */ { 0x1008fe09, 31883 }, /* XF86Switch_VT_9 */ { 0x10081241, 31899 }, /* XF86Taskmanager */ { 0x1008ff7f, 31915 }, /* XF86TaskPane */ { 0x1008ff80, 31928 }, /* XF86Terminal */ { 0x1008ff9f, 31941 }, /* XF86Time */ { 0x1008ff1f, 31950 }, /* XF86ToDoList */ { 0x1008ff81, 31963 }, /* XF86Tools */ { 0x1008ffa2, 31973 }, /* XF86TopMenu */ { 0x1008ffb1, 31985 }, /* XF86TouchpadOff */ { 0x1008ffb0, 32001 }, /* XF86TouchpadOn */ { 0x1008ffa9, 32016 }, /* XF86TouchpadToggle */ { 0x10081285, 32035 }, /* XF86TraditionalSonar */ { 0x1008ff82, 32056 }, /* XF86Travel */ { 0x1008fe20, 32067 }, /* XF86Ungrab */ { 0x10081274, 32078 }, /* XF86Unmute */ { 0x1008ff85, 32089 }, /* XF86User1KB */ { 0x1008ff86, 32101 }, /* XF86User2KB */ { 0x1008ff84, 32113 }, /* XF86UserPB */ { 0x1008ff96, 32124 }, /* XF86UWB */ { 0x1008ff34, 32132 }, /* XF86VendorHome */ { 0x10081168, 32147 }, /* XF86VendorLogo */ { 0x1008ff87, 32162 }, /* XF86Video */ { 0x100811a0, 32172 }, /* XF86VideoPhone */ { 0x1008ffa1, 32187 }, /* XF86View */ { 0x10081273, 32196 }, /* XF86VOD */ { 0x10081246, 32204 }, /* XF86VoiceCommand */ { 0x100811ac, 32221 }, /* XF86Voicemail */ { 0x1008ff2b, 32235 }, /* XF86WakeUp */ { 0x1008ff8f, 32246 }, /* XF86WebCam */ { 0x1008ff88, 32257 }, /* XF86WheelButton */ { 0x1008ff95, 32273 }, /* XF86WLAN */ { 0x1008ff89, 32282 }, /* XF86Word */ { 0x10081211, 32291 }, /* XF86WPSButton */ { 0x1008ffb4, 32305 }, /* XF86WWAN */ { 0x1008ff2e, 32314 }, /* XF86WWW */ { 0x1008ff8a, 32322 }, /* XF86Xfer */ { 0x1008ffa5, 32331 }, /* XF86Yellow */ { 0x1008ff8b, 32342 }, /* XF86ZoomIn */ { 0x1008ff8c, 32353 }, /* XF86ZoomOut */ { 0x100811a4, 32365 }, /* XF86ZoomReset */ { 0x00000059, 32379 }, /* Y */ { 0x00000079, 32381 }, /* y */ { 0x000000dd, 32383 }, /* Yacute */ { 0x000000fd, 32390 }, /* yacute */ { 0x01001ef4, 32397 }, /* Ybelowdot */ { 0x01001ef5, 32407 }, /* ybelowdot */ { 0x01000176, 32417 }, /* Ycircumflex */ { 0x01000177, 32429 }, /* ycircumflex */ { 0x000013be, 32441 }, /* Ydiaeresis */ { 0x000000ff, 32452 }, /* ydiaeresis */ { 0x000000a5, 32463 }, /* yen */ { 0x01001ef2, 32467 }, /* Ygrave */ { 0x01001ef3, 32474 }, /* ygrave */ { 0x01001ef6, 32481 }, /* Yhook */ { 0x01001ef7, 32487 }, /* yhook */ { 0x01001ef8, 32493 }, /* Ytilde */ { 0x01001ef9, 32500 }, /* ytilde */ { 0x0000005a, 32507 }, /* Z */ { 0x0000007a, 32509 }, /* z */ { 0x000001af, 32511 }, /* Zabovedot */ { 0x000001bf, 32521 }, /* zabovedot */ { 0x000001ac, 32531 }, /* Zacute */ { 0x000001bc, 32538 }, /* zacute */ { 0x000001ae, 32545 }, /* Zcaron */ { 0x000001be, 32552 }, /* zcaron */ { 0x0000ff3d, 32559 }, /* Zen_Koho */ { 0x0000ff28, 32568 }, /* Zenkaku */ { 0x0000ff2a, 32576 }, /* Zenkaku_Hankaku */ { 0x01002080, 32592 }, /* zerosubscript */ { 0x01002070, 32606 }, /* zerosuperior */ { 0x010001b5, 32619 }, /* Zstroke */ { 0x010001b6, 32627 }, /* zstroke */ }; static const struct name_keysym keysym_to_name[] = { { 0x00000000, 20235 }, /* NoSymbol */ { 0x00000020, 23960 }, /* space */ { 0x00000021, 12214 }, /* exclam */ { 0x00000022, 22344 }, /* quotedbl */ { 0x00000023, 20322 }, /* numbersign */ { 0x00000024, 11366 }, /* dollar */ { 0x00000025, 21644 }, /* percent */ { 0x00000026, 908 }, /* ampersand */ { 0x00000027, 934 }, /* apostrophe */ { 0x00000028, 21582 }, /* parenleft */ { 0x00000029, 21592 }, /* parenright */ { 0x0000002a, 3283 }, /* asterisk */ { 0x0000002b, 21714 }, /* plus */ { 0x0000002c, 8762 }, /* comma */ { 0x0000002d, 19877 }, /* minus */ { 0x0000002e, 21652 }, /* period */ { 0x0000002f, 23925 }, /* slash */ { 0x00000030, 0 }, /* 0 */ { 0x00000031, 2 }, /* 1 */ { 0x00000032, 4 }, /* 2 */ { 0x00000033, 6 }, /* 3 */ { 0x00000034, 386 }, /* 4 */ { 0x00000035, 388 }, /* 5 */ { 0x00000036, 390 }, /* 6 */ { 0x00000037, 392 }, /* 7 */ { 0x00000038, 394 }, /* 8 */ { 0x00000039, 396 }, /* 9 */ { 0x0000003a, 8664 }, /* colon */ { 0x0000003b, 22891 }, /* semicolon */ { 0x0000003c, 19556 }, /* less */ { 0x0000003d, 12166 }, /* equal */ { 0x0000003e, 13387 }, /* greater */ { 0x0000003f, 22322 }, /* question */ { 0x00000040, 3292 }, /* at */ { 0x00000041, 398 }, /* A */ { 0x00000042, 3328 }, /* B */ { 0x00000043, 8439 }, /* C */ { 0x00000044, 10402 }, /* D */ { 0x00000045, 11539 }, /* E */ { 0x00000046, 12270 }, /* F */ { 0x00000047, 12780 }, /* G */ { 0x00000048, 14522 }, /* H */ { 0x00000049, 17213 }, /* I */ { 0x0000004a, 18258 }, /* J */ { 0x0000004b, 18290 }, /* K */ { 0x0000004c, 19256 }, /* L */ { 0x0000004d, 19677 }, /* M */ { 0x0000004e, 20087 }, /* N */ { 0x0000004f, 20344 }, /* O */ { 0x00000050, 21530 }, /* P */ { 0x00000051, 22313 }, /* Q */ { 0x00000052, 22374 }, /* R */ { 0x00000053, 22736 }, /* S */ { 0x00000054, 24451 }, /* T */ { 0x00000055, 26004 }, /* U */ { 0x00000056, 26640 }, /* V */ { 0x00000057, 26702 }, /* W */ { 0x00000058, 26788 }, /* X */ { 0x00000059, 32379 }, /* Y */ { 0x0000005a, 32507 }, /* Z */ { 0x0000005b, 3603 }, /* bracketleft */ { 0x0000005c, 3352 }, /* backslash */ { 0x0000005d, 3615 }, /* bracketright */ { 0x0000005e, 3260 }, /* asciicircum */ { 0x0000005f, 26503 }, /* underscore */ { 0x00000060, 13381 }, /* grave */ { 0x00000061, 400 }, /* a */ { 0x00000062, 3330 }, /* b */ { 0x00000063, 8441 }, /* c */ { 0x00000064, 10404 }, /* d */ { 0x00000065, 11541 }, /* e */ { 0x00000066, 12272 }, /* f */ { 0x00000067, 12782 }, /* g */ { 0x00000068, 14524 }, /* h */ { 0x00000069, 17215 }, /* i */ { 0x0000006a, 18260 }, /* j */ { 0x0000006b, 18292 }, /* k */ { 0x0000006c, 19258 }, /* l */ { 0x0000006d, 19679 }, /* m */ { 0x0000006e, 20089 }, /* n */ { 0x0000006f, 20346 }, /* o */ { 0x00000070, 21532 }, /* p */ { 0x00000071, 22315 }, /* q */ { 0x00000072, 22376 }, /* r */ { 0x00000073, 22738 }, /* s */ { 0x00000074, 24453 }, /* t */ { 0x00000075, 26006 }, /* u */ { 0x00000076, 26642 }, /* v */ { 0x00000077, 26704 }, /* w */ { 0x00000078, 26790 }, /* x */ { 0x00000079, 32381 }, /* y */ { 0x0000007a, 32509 }, /* z */ { 0x0000007b, 3582 }, /* braceleft */ { 0x0000007c, 3392 }, /* bar */ { 0x0000007d, 3592 }, /* braceright */ { 0x0000007e, 3272 }, /* asciitilde */ { 0x000000a0, 20222 }, /* nobreakspace */ { 0x000000a1, 12221 }, /* exclamdown */ { 0x000000a2, 8589 }, /* cent */ { 0x000000a3, 23984 }, /* sterling */ { 0x000000a4, 8848 }, /* currency */ { 0x000000a5, 32463 }, /* yen */ { 0x000000a6, 8389 }, /* brokenbar */ { 0x000000a7, 22876 }, /* section */ { 0x000000a8, 11318 }, /* diaeresis */ { 0x000000a9, 8799 }, /* copyright */ { 0x000000aa, 20996 }, /* ordfeminine */ { 0x000000ab, 14493 }, /* guillemotleft */ { 0x000000ac, 20291 }, /* notsign */ { 0x000000ad, 17206 }, /* hyphen */ { 0x000000ae, 22488 }, /* registered */ { 0x000000af, 19785 }, /* macron */ { 0x000000b0, 11268 }, /* degree */ { 0x000000b1, 21719 }, /* plusminus */ { 0x000000b2, 25982 }, /* twosuperior */ { 0x000000b3, 25728 }, /* threesuperior */ { 0x000000b4, 820 }, /* acute */ { 0x000000b5, 19943 }, /* mu */ { 0x000000b6, 21572 }, /* paragraph */ { 0x000000b7, 21659 }, /* periodcentered */ { 0x000000b8, 8581 }, /* cedilla */ { 0x000000b9, 20899 }, /* onesuperior */ { 0x000000ba, 19832 }, /* masculine */ { 0x000000bb, 14507 }, /* guillemotright */ { 0x000000bc, 20866 }, /* onequarter */ { 0x000000bd, 20858 }, /* onehalf */ { 0x000000be, 25699 }, /* threequarters */ { 0x000000bf, 22331 }, /* questiondown */ { 0x000000c0, 854 }, /* Agrave */ { 0x000000c1, 402 }, /* Aacute */ { 0x000000c2, 622 }, /* Acircumflex */ { 0x000000c3, 3295 }, /* Atilde */ { 0x000000c4, 826 }, /* Adiaeresis */ { 0x000000c5, 2036 }, /* Aring */ { 0x000000c6, 848 }, /* AE */ { 0x000000c7, 8539 }, /* Ccedilla */ { 0x000000c8, 11839 }, /* Egrave */ { 0x000000c9, 11563 }, /* Eacute */ { 0x000000ca, 11611 }, /* Ecircumflex */ { 0x000000cb, 11817 }, /* Ediaeresis */ { 0x000000cc, 17349 }, /* Igrave */ { 0x000000cd, 17227 }, /* Iacute */ { 0x000000ce, 17275 }, /* Icircumflex */ { 0x000000cf, 17309 }, /* Idiaeresis */ { 0x000000d0, 12179 }, /* ETH */ { 0x000000d1, 20299 }, /* Ntilde */ { 0x000000d2, 20671 }, /* Ograve */ { 0x000000d3, 20348 }, /* Oacute */ { 0x000000d4, 20412 }, /* Ocircumflex */ { 0x000000d5, 21467 }, /* Otilde */ { 0x000000d6, 20610 }, /* Odiaeresis */ { 0x000000d7, 19983 }, /* multiply */ { 0x000000d8, 21453 }, /* Oslash */ { 0x000000d9, 26128 }, /* Ugrave */ { 0x000000da, 26008 }, /* Uacute */ { 0x000000db, 26056 }, /* Ucircumflex */ { 0x000000dc, 26080 }, /* Udiaeresis */ { 0x000000dd, 32383 }, /* Yacute */ { 0x000000de, 25656 }, /* THORN */ { 0x000000df, 23977 }, /* ssharp */ { 0x000000e0, 861 }, /* agrave */ { 0x000000e1, 409 }, /* aacute */ { 0x000000e2, 634 }, /* acircumflex */ { 0x000000e3, 3302 }, /* atilde */ { 0x000000e4, 837 }, /* adiaeresis */ { 0x000000e5, 2042 }, /* aring */ { 0x000000e6, 851 }, /* ae */ { 0x000000e7, 8548 }, /* ccedilla */ { 0x000000e8, 11846 }, /* egrave */ { 0x000000e9, 11570 }, /* eacute */ { 0x000000ea, 11623 }, /* ecircumflex */ { 0x000000eb, 11828 }, /* ediaeresis */ { 0x000000ec, 17356 }, /* igrave */ { 0x000000ed, 17234 }, /* iacute */ { 0x000000ee, 17287 }, /* icircumflex */ { 0x000000ef, 17320 }, /* idiaeresis */ { 0x000000f0, 12187 }, /* eth */ { 0x000000f1, 20306 }, /* ntilde */ { 0x000000f2, 20678 }, /* ograve */ { 0x000000f3, 20355 }, /* oacute */ { 0x000000f4, 20424 }, /* ocircumflex */ { 0x000000f5, 21474 }, /* otilde */ { 0x000000f6, 20621 }, /* odiaeresis */ { 0x000000f7, 11357 }, /* division */ { 0x000000f8, 21460 }, /* oslash */ { 0x000000f9, 26135 }, /* ugrave */ { 0x000000fa, 26015 }, /* uacute */ { 0x000000fb, 26068 }, /* ucircumflex */ { 0x000000fc, 26091 }, /* udiaeresis */ { 0x000000fd, 32390 }, /* yacute */ { 0x000000fe, 25668 }, /* thorn */ { 0x000000ff, 32452 }, /* ydiaeresis */ { 0x000001a1, 918 }, /* Aogonek */ { 0x000001a2, 8383 }, /* breve */ { 0x000001a3, 19661 }, /* Lstroke */ { 0x000001a5, 19356 }, /* Lcaron */ { 0x000001a6, 22760 }, /* Sacute */ { 0x000001a9, 22774 }, /* Scaron */ { 0x000001aa, 22788 }, /* Scedilla */ { 0x000001ab, 24479 }, /* Tcaron */ { 0x000001ac, 32531 }, /* Zacute */ { 0x000001ae, 32545 }, /* Zcaron */ { 0x000001af, 32511 }, /* Zabovedot */ { 0x000001b1, 926 }, /* aogonek */ { 0x000001b2, 20664 }, /* ogonek */ { 0x000001b3, 19669 }, /* lstroke */ { 0x000001b5, 19363 }, /* lcaron */ { 0x000001b6, 22767 }, /* sacute */ { 0x000001b7, 8519 }, /* caron */ { 0x000001b9, 22781 }, /* scaron */ { 0x000001ba, 22797 }, /* scedilla */ { 0x000001bb, 24486 }, /* tcaron */ { 0x000001bc, 32538 }, /* zacute */ { 0x000001bd, 11398 }, /* doubleacute */ { 0x000001be, 32552 }, /* zcaron */ { 0x000001bf, 32521 }, /* zabovedot */ { 0x000001c0, 22429 }, /* Racute */ { 0x000001c3, 445 }, /* Abreve */ { 0x000001c5, 19291 }, /* Lacute */ { 0x000001c6, 8475 }, /* Cacute */ { 0x000001c8, 8525 }, /* Ccaron */ { 0x000001ca, 12150 }, /* Eogonek */ { 0x000001cc, 11597 }, /* Ecaron */ { 0x000001cf, 10447 }, /* Dcaron */ { 0x000001d0, 11516 }, /* Dstroke */ { 0x000001d1, 20097 }, /* Nacute */ { 0x000001d2, 20121 }, /* Ncaron */ { 0x000001d5, 20632 }, /* Odoubleacute */ { 0x000001d8, 22451 }, /* Rcaron */ { 0x000001d9, 26609 }, /* Uring */ { 0x000001db, 26102 }, /* Udoubleacute */ { 0x000001de, 24493 }, /* Tcedilla */ { 0x000001e0, 22436 }, /* racute */ { 0x000001e3, 452 }, /* abreve */ { 0x000001e5, 19298 }, /* lacute */ { 0x000001e6, 8482 }, /* cacute */ { 0x000001e8, 8532 }, /* ccaron */ { 0x000001ea, 12158 }, /* eogonek */ { 0x000001ec, 11604 }, /* ecaron */ { 0x000001ef, 10454 }, /* dcaron */ { 0x000001f0, 11524 }, /* dstroke */ { 0x000001f1, 20104 }, /* nacute */ { 0x000001f2, 20128 }, /* ncaron */ { 0x000001f5, 20645 }, /* odoubleacute */ { 0x000001f8, 22458 }, /* rcaron */ { 0x000001f9, 26615 }, /* uring */ { 0x000001fb, 26115 }, /* udoubleacute */ { 0x000001fe, 24502 }, /* tcedilla */ { 0x000001ff, 436 }, /* abovedot */ { 0x000002a1, 17171 }, /* Hstroke */ { 0x000002a6, 16200 }, /* Hcircumflex */ { 0x000002a9, 17217 }, /* Iabovedot */ { 0x000002ab, 12804 }, /* Gbreve */ { 0x000002ac, 18262 }, /* Jcircumflex */ { 0x000002b1, 17179 }, /* hstroke */ { 0x000002b6, 16212 }, /* hcircumflex */ { 0x000002b9, 17331 }, /* idotless */ { 0x000002bb, 12811 }, /* gbreve */ { 0x000002bc, 18274 }, /* jcircumflex */ { 0x000002c5, 8455 }, /* Cabovedot */ { 0x000002c6, 8557 }, /* Ccircumflex */ { 0x000002d5, 12784 }, /* Gabovedot */ { 0x000002d8, 12850 }, /* Gcircumflex */ { 0x000002dd, 26042 }, /* Ubreve */ { 0x000002de, 22818 }, /* Scircumflex */ { 0x000002e5, 8465 }, /* cabovedot */ { 0x000002e6, 8569 }, /* ccircumflex */ { 0x000002f5, 12794 }, /* gabovedot */ { 0x000002f8, 12862 }, /* gcircumflex */ { 0x000002fd, 26049 }, /* ubreve */ { 0x000002fe, 22830 }, /* scircumflex */ { 0x000003a2, 19252 }, /* kra */ { 0x000003a3, 22465 }, /* Rcedilla */ { 0x000003a5, 18244 }, /* Itilde */ { 0x000003a6, 19370 }, /* Lcedilla */ { 0x000003aa, 11954 }, /* Emacron */ { 0x000003ab, 12832 }, /* Gcedilla */ { 0x000003ac, 25945 }, /* Tslash */ { 0x000003b3, 22474 }, /* rcedilla */ { 0x000003b5, 18251 }, /* itilde */ { 0x000003b6, 19379 }, /* lcedilla */ { 0x000003ba, 11962 }, /* emacron */ { 0x000003bb, 12841 }, /* gcedilla */ { 0x000003bc, 25952 }, /* tslash */ { 0x000003bd, 12098 }, /* ENG */ { 0x000003bf, 12102 }, /* eng */ { 0x000003c0, 892 }, /* Amacron */ { 0x000003c7, 17482 }, /* Iogonek */ { 0x000003cc, 11543 }, /* Eabovedot */ { 0x000003cf, 17375 }, /* Imacron */ { 0x000003d1, 20135 }, /* Ncedilla */ { 0x000003d2, 20823 }, /* Omacron */ { 0x000003d3, 18923 }, /* Kcedilla */ { 0x000003d9, 26525 }, /* Uogonek */ { 0x000003dd, 26626 }, /* Utilde */ { 0x000003de, 26478 }, /* Umacron */ { 0x000003e0, 900 }, /* amacron */ { 0x000003e7, 17490 }, /* iogonek */ { 0x000003ec, 11553 }, /* eabovedot */ { 0x000003ef, 17383 }, /* imacron */ { 0x000003f1, 20144 }, /* ncedilla */ { 0x000003f2, 20831 }, /* omacron */ { 0x000003f3, 18932 }, /* kcedilla */ { 0x000003f9, 26533 }, /* uogonek */ { 0x000003fd, 26633 }, /* utilde */ { 0x000003fe, 26486 }, /* umacron */ { 0x0000047e, 21521 }, /* overline */ { 0x000004a1, 18387 }, /* kana_fullstop */ { 0x000004a2, 18621 }, /* kana_openingbracket */ { 0x000004a3, 18317 }, /* kana_closingbracket */ { 0x000004a4, 18337 }, /* kana_comma */ { 0x000004a5, 18348 }, /* kana_conjunctive */ { 0x000004a6, 18833 }, /* kana_WO */ { 0x000004a7, 18301 }, /* kana_a */ { 0x000004a8, 18448 }, /* kana_i */ { 0x000004a9, 18818 }, /* kana_u */ { 0x000004aa, 18372 }, /* kana_e */ { 0x000004ab, 18614 }, /* kana_o */ { 0x000004ac, 18849 }, /* kana_ya */ { 0x000004ad, 18881 }, /* kana_yu */ { 0x000004ae, 18865 }, /* kana_yo */ { 0x000004af, 18786 }, /* kana_tsu */ { 0x000004b0, 22287 }, /* prolongedsound */ { 0x000004b1, 18294 }, /* kana_A */ { 0x000004b2, 18441 }, /* kana_I */ { 0x000004b3, 18811 }, /* kana_U */ { 0x000004b4, 18365 }, /* kana_E */ { 0x000004b5, 18607 }, /* kana_O */ { 0x000004b6, 18455 }, /* kana_KA */ { 0x000004b7, 18471 }, /* kana_KI */ { 0x000004b8, 18487 }, /* kana_KU */ { 0x000004b9, 18463 }, /* kana_KE */ { 0x000004ba, 18479 }, /* kana_KO */ { 0x000004bb, 18681 }, /* kana_SA */ { 0x000004bc, 18697 }, /* kana_SHI */ { 0x000004bd, 18725 }, /* kana_SU */ { 0x000004be, 18689 }, /* kana_SE */ { 0x000004bf, 18717 }, /* kana_SO */ { 0x000004c0, 18745 }, /* kana_TA */ { 0x000004c1, 18308 }, /* kana_CHI */ { 0x000004c2, 18777 }, /* kana_TSU */ { 0x000004c3, 18753 }, /* kana_TE */ { 0x000004c4, 18769 }, /* kana_TO */ { 0x000004c5, 18567 }, /* kana_NA */ { 0x000004c6, 18583 }, /* kana_NI */ { 0x000004c7, 18599 }, /* kana_NU */ { 0x000004c8, 18575 }, /* kana_NE */ { 0x000004c9, 18591 }, /* kana_NO */ { 0x000004ca, 18401 }, /* kana_HA */ { 0x000004cb, 18417 }, /* kana_HI */ { 0x000004cc, 18379 }, /* kana_FU */ { 0x000004cd, 18409 }, /* kana_HE */ { 0x000004ce, 18425 }, /* kana_HO */ { 0x000004cf, 18505 }, /* kana_MA */ { 0x000004d0, 18521 }, /* kana_MI */ { 0x000004d1, 18552 }, /* kana_MU */ { 0x000004d2, 18513 }, /* kana_ME */ { 0x000004d3, 18544 }, /* kana_MO */ { 0x000004d4, 18841 }, /* kana_YA */ { 0x000004d5, 18873 }, /* kana_YU */ { 0x000004d6, 18857 }, /* kana_YO */ { 0x000004d7, 18641 }, /* kana_RA */ { 0x000004d8, 18657 }, /* kana_RI */ { 0x000004d9, 18673 }, /* kana_RU */ { 0x000004da, 18649 }, /* kana_RE */ { 0x000004db, 18665 }, /* kana_RO */ { 0x000004dc, 18825 }, /* kana_WA */ { 0x000004dd, 18560 }, /* kana_N */ { 0x000004de, 26676 }, /* voicedsound */ { 0x000004df, 22901 }, /* semivoicedsound */ { 0x000005ac, 1109 }, /* Arabic_comma */ { 0x000005bb, 1764 }, /* Arabic_semicolon */ { 0x000005bf, 1698 }, /* Arabic_question_mark */ { 0x000005c1, 1303 }, /* Arabic_hamza */ { 0x000005c2, 1599 }, /* Arabic_maddaonalef */ { 0x000005c3, 1354 }, /* Arabic_hamzaonalef */ { 0x000005c4, 1373 }, /* Arabic_hamzaonwaw */ { 0x000005c5, 1409 }, /* Arabic_hamzaunderalef */ { 0x000005c6, 1391 }, /* Arabic_hamzaonyeh */ { 0x000005c7, 1067 }, /* Arabic_alef */ { 0x000005c8, 1098 }, /* Arabic_beh */ { 0x000005c9, 1909 }, /* Arabic_tehmarbuta */ { 0x000005ca, 1898 }, /* Arabic_teh */ { 0x000005cb, 1939 }, /* Arabic_theh */ { 0x000005cc, 1481 }, /* Arabic_jeem */ { 0x000005cd, 1292 }, /* Arabic_hah */ { 0x000005ce, 1557 }, /* Arabic_khah */ { 0x000005cf, 1133 }, /* Arabic_dal */ { 0x000005d0, 1927 }, /* Arabic_thal */ { 0x000005d1, 1719 }, /* Arabic_ra */ { 0x000005d2, 2024 }, /* Arabic_zain */ { 0x000005d3, 1752 }, /* Arabic_seen */ { 0x000005d4, 1795 }, /* Arabic_sheen */ { 0x000005d5, 1741 }, /* Arabic_sad */ { 0x000005d6, 1122 }, /* Arabic_dad */ { 0x000005d7, 1859 }, /* Arabic_tah */ { 0x000005d8, 2013 }, /* Arabic_zah */ { 0x000005d9, 1056 }, /* Arabic_ain */ { 0x000005da, 1269 }, /* Arabic_ghain */ { 0x000005e0, 1870 }, /* Arabic_tatweel */ { 0x000005e1, 1231 }, /* Arabic_feh */ { 0x000005e2, 1687 }, /* Arabic_qaf */ { 0x000005e3, 1504 }, /* Arabic_kaf */ { 0x000005e4, 1569 }, /* Arabic_lam */ { 0x000005e5, 1618 }, /* Arabic_meem */ { 0x000005e6, 1630 }, /* Arabic_noon */ { 0x000005e7, 1282 }, /* Arabic_ha */ { 0x000005e8, 1974 }, /* Arabic_waw */ { 0x000005e9, 1079 }, /* Arabic_alefmaksura */ { 0x000005ea, 1985 }, /* Arabic_yeh */ { 0x000005eb, 1215 }, /* Arabic_fathatan */ { 0x000005ec, 1157 }, /* Arabic_dammatan */ { 0x000005ed, 1528 }, /* Arabic_kasratan */ { 0x000005ee, 1202 }, /* Arabic_fatha */ { 0x000005ef, 1144 }, /* Arabic_damma */ { 0x000005f0, 1515 }, /* Arabic_kasra */ { 0x000005f1, 1781 }, /* Arabic_shadda */ { 0x000005f2, 1808 }, /* Arabic_sukun */ { 0x000006a1, 22929 }, /* Serbian_dje */ { 0x000006a2, 19743 }, /* Macedonia_gje */ { 0x000006a3, 9550 }, /* Cyrillic_io */ { 0x000006a4, 26369 }, /* Ukrainian_ie */ { 0x000006a5, 19715 }, /* Macedonia_dse */ { 0x000006a6, 26344 }, /* Ukrainian_i */ { 0x000006a7, 26395 }, /* Ukrainian_yi */ { 0x000006a8, 9574 }, /* Cyrillic_je */ { 0x000006a9, 9713 }, /* Cyrillic_lje */ { 0x000006aa, 9739 }, /* Cyrillic_nje */ { 0x000006ab, 23048 }, /* Serbian_tshe */ { 0x000006ac, 19771 }, /* Macedonia_kje */ { 0x000006ad, 26306 }, /* Ukrainian_ghe_with_upturn */ { 0x000006ae, 8419 }, /* Byelorussian_shortu */ { 0x000006af, 9068 }, /* Cyrillic_dzhe */ { 0x000006b0, 20333 }, /* numerosign */ { 0x000006b1, 22917 }, /* Serbian_DJE */ { 0x000006b2, 19729 }, /* Macedonia_GJE */ { 0x000006b3, 9538 }, /* Cyrillic_IO */ { 0x000006b4, 26356 }, /* Ukrainian_IE */ { 0x000006b5, 19701 }, /* Macedonia_DSE */ { 0x000006b6, 26332 }, /* Ukrainian_I */ { 0x000006b7, 26382 }, /* Ukrainian_YI */ { 0x000006b8, 9562 }, /* Cyrillic_JE */ { 0x000006b9, 9700 }, /* Cyrillic_LJE */ { 0x000006ba, 9726 }, /* Cyrillic_NJE */ { 0x000006bb, 23035 }, /* Serbian_TSHE */ { 0x000006bc, 19757 }, /* Macedonia_KJE */ { 0x000006bd, 26280 }, /* Ukrainian_GHE_WITH_UPTURN */ { 0x000006be, 8399 }, /* Byelorussian_SHORTU */ { 0x000006bf, 9054 }, /* Cyrillic_DZHE */ { 0x000006c0, 10294 }, /* Cyrillic_yu */ { 0x000006c1, 8875 }, /* Cyrillic_a */ { 0x000006c2, 8898 }, /* Cyrillic_be */ { 0x000006c3, 10047 }, /* Cyrillic_tse */ { 0x000006c4, 9042 }, /* Cyrillic_de */ { 0x000006c5, 9526 }, /* Cyrillic_ie */ { 0x000006c6, 9116 }, /* Cyrillic_ef */ { 0x000006c7, 9305 }, /* Cyrillic_ghe */ { 0x000006c8, 9364 }, /* Cyrillic_ha */ { 0x000006c9, 9467 }, /* Cyrillic_i */ { 0x000006ca, 9958 }, /* Cyrillic_shorti */ { 0x000006cb, 9598 }, /* Cyrillic_ka */ { 0x000006cc, 9140 }, /* Cyrillic_el */ { 0x000006cd, 9164 }, /* Cyrillic_em */ { 0x000006ce, 9188 }, /* Cyrillic_en */ { 0x000006cf, 9763 }, /* Cyrillic_o */ { 0x000006d0, 9816 }, /* Cyrillic_pe */ { 0x000006d1, 10242 }, /* Cyrillic_ya */ { 0x000006d2, 9256 }, /* Cyrillic_er */ { 0x000006d3, 9280 }, /* Cyrillic_es */ { 0x000006d4, 10022 }, /* Cyrillic_te */ { 0x000006d5, 10071 }, /* Cyrillic_u */ { 0x000006d6, 10343 }, /* Cyrillic_zhe */ { 0x000006d7, 10218 }, /* Cyrillic_ve */ { 0x000006d8, 9992 }, /* Cyrillic_softsign */ { 0x000006d9, 10268 }, /* Cyrillic_yeru */ { 0x000006da, 10318 }, /* Cyrillic_ze */ { 0x000006db, 9871 }, /* Cyrillic_sha */ { 0x000006dc, 9093 }, /* Cyrillic_e */ { 0x000006dd, 9899 }, /* Cyrillic_shcha */ { 0x000006de, 8923 }, /* Cyrillic_che */ { 0x000006df, 9438 }, /* Cyrillic_hardsign */ { 0x000006e0, 10282 }, /* Cyrillic_YU */ { 0x000006e1, 8864 }, /* Cyrillic_A */ { 0x000006e2, 8886 }, /* Cyrillic_BE */ { 0x000006e3, 10034 }, /* Cyrillic_TSE */ { 0x000006e4, 9030 }, /* Cyrillic_DE */ { 0x000006e5, 9514 }, /* Cyrillic_IE */ { 0x000006e6, 9104 }, /* Cyrillic_EF */ { 0x000006e7, 9292 }, /* Cyrillic_GHE */ { 0x000006e8, 9352 }, /* Cyrillic_HA */ { 0x000006e9, 9456 }, /* Cyrillic_I */ { 0x000006ea, 9942 }, /* Cyrillic_SHORTI */ { 0x000006eb, 9586 }, /* Cyrillic_KA */ { 0x000006ec, 9128 }, /* Cyrillic_EL */ { 0x000006ed, 9152 }, /* Cyrillic_EM */ { 0x000006ee, 9176 }, /* Cyrillic_EN */ { 0x000006ef, 9752 }, /* Cyrillic_O */ { 0x000006f0, 9804 }, /* Cyrillic_PE */ { 0x000006f1, 10230 }, /* Cyrillic_YA */ { 0x000006f2, 9244 }, /* Cyrillic_ER */ { 0x000006f3, 9268 }, /* Cyrillic_ES */ { 0x000006f4, 10010 }, /* Cyrillic_TE */ { 0x000006f5, 10060 }, /* Cyrillic_U */ { 0x000006f6, 10330 }, /* Cyrillic_ZHE */ { 0x000006f7, 10206 }, /* Cyrillic_VE */ { 0x000006f8, 9974 }, /* Cyrillic_SOFTSIGN */ { 0x000006f9, 10254 }, /* Cyrillic_YERU */ { 0x000006fa, 10306 }, /* Cyrillic_ZE */ { 0x000006fb, 9858 }, /* Cyrillic_SHA */ { 0x000006fc, 9082 }, /* Cyrillic_E */ { 0x000006fd, 9884 }, /* Cyrillic_SHCHA */ { 0x000006fe, 8910 }, /* Cyrillic_CHE */ { 0x000006ff, 9420 }, /* Cyrillic_HARDSIGN */ { 0x000007a1, 13457 }, /* Greek_ALPHAaccent */ { 0x000007a2, 13587 }, /* Greek_EPSILONaccent */ { 0x000007a3, 13647 }, /* Greek_ETAaccent */ { 0x000007a4, 13762 }, /* Greek_IOTAaccent */ { 0x000007a5, 13841 }, /* Greek_IOTAdieresis */ { 0x000007a7, 14077 }, /* Greek_OMICRONaccent */ { 0x000007a8, 14304 }, /* Greek_UPSILONaccent */ { 0x000007a9, 14372 }, /* Greek_UPSILONdieresis */ { 0x000007ab, 14013 }, /* Greek_OMEGAaccent */ { 0x000007ae, 13412 }, /* Greek_accentdieresis */ { 0x000007af, 13725 }, /* Greek_horizbar */ { 0x000007b1, 13475 }, /* Greek_alphaaccent */ { 0x000007b2, 13607 }, /* Greek_epsilonaccent */ { 0x000007b3, 13663 }, /* Greek_etaaccent */ { 0x000007b4, 13779 }, /* Greek_iotaaccent */ { 0x000007b5, 13860 }, /* Greek_iotadieresis */ { 0x000007b6, 13796 }, /* Greek_iotaaccentdieresis */ { 0x000007b7, 14097 }, /* Greek_omicronaccent */ { 0x000007b8, 14324 }, /* Greek_upsilonaccent */ { 0x000007b9, 14394 }, /* Greek_upsilondieresis */ { 0x000007ba, 14344 }, /* Greek_upsilonaccentdieresis */ { 0x000007bb, 14031 }, /* Greek_omegaaccent */ { 0x000007c1, 13433 }, /* Greek_ALPHA */ { 0x000007c2, 13493 }, /* Greek_BETA */ { 0x000007c3, 13701 }, /* Greek_GAMMA */ { 0x000007c4, 13535 }, /* Greek_DELTA */ { 0x000007c5, 13559 }, /* Greek_EPSILON */ { 0x000007c6, 14434 }, /* Greek_ZETA */ { 0x000007c7, 13627 }, /* Greek_ETA */ { 0x000007c8, 14252 }, /* Greek_THETA */ { 0x000007c9, 13740 }, /* Greek_IOTA */ { 0x000007ca, 13879 }, /* Greek_KAPPA */ { 0x000007cb, 13929 }, /* Greek_LAMDA */ { 0x000007cc, 13953 }, /* Greek_MU */ { 0x000007cd, 13971 }, /* Greek_NU */ { 0x000007ce, 14416 }, /* Greek_XI */ { 0x000007cf, 14049 }, /* Greek_OMICRON */ { 0x000007d0, 14137 }, /* Greek_PI */ { 0x000007d1, 14175 }, /* Greek_RHO */ { 0x000007d2, 14195 }, /* Greek_SIGMA */ { 0x000007d4, 14232 }, /* Greek_TAU */ { 0x000007d5, 14276 }, /* Greek_UPSILON */ { 0x000007d6, 14117 }, /* Greek_PHI */ { 0x000007d7, 13515 }, /* Greek_CHI */ { 0x000007d8, 14155 }, /* Greek_PSI */ { 0x000007d9, 13989 }, /* Greek_OMEGA */ { 0x000007e1, 13445 }, /* Greek_alpha */ { 0x000007e2, 13504 }, /* Greek_beta */ { 0x000007e3, 13713 }, /* Greek_gamma */ { 0x000007e4, 13547 }, /* Greek_delta */ { 0x000007e5, 13573 }, /* Greek_epsilon */ { 0x000007e6, 14445 }, /* Greek_zeta */ { 0x000007e7, 13637 }, /* Greek_eta */ { 0x000007e8, 14264 }, /* Greek_theta */ { 0x000007e9, 13751 }, /* Greek_iota */ { 0x000007ea, 13891 }, /* Greek_kappa */ { 0x000007eb, 13941 }, /* Greek_lamda */ { 0x000007ec, 13962 }, /* Greek_mu */ { 0x000007ed, 13980 }, /* Greek_nu */ { 0x000007ee, 14425 }, /* Greek_xi */ { 0x000007ef, 14063 }, /* Greek_omicron */ { 0x000007f0, 14146 }, /* Greek_pi */ { 0x000007f1, 14185 }, /* Greek_rho */ { 0x000007f2, 14207 }, /* Greek_sigma */ { 0x000007f3, 13679 }, /* Greek_finalsmallsigma */ { 0x000007f4, 14242 }, /* Greek_tau */ { 0x000007f5, 14290 }, /* Greek_upsilon */ { 0x000007f6, 14127 }, /* Greek_phi */ { 0x000007f7, 13525 }, /* Greek_chi */ { 0x000007f8, 14165 }, /* Greek_psi */ { 0x000007f9, 14001 }, /* Greek_omega */ { 0x000008a1, 19500 }, /* leftradical */ { 0x000008a2, 25778 }, /* topleftradical */ { 0x000008a3, 16811 }, /* horizconnector */ { 0x000008a4, 25752 }, /* topintegral */ { 0x000008a5, 3422 }, /* botintegral */ { 0x000008a6, 26662 }, /* vertconnector */ { 0x000008a7, 25793 }, /* topleftsqbracket */ { 0x000008a8, 3448 }, /* botleftsqbracket */ { 0x000008a9, 25842 }, /* toprightsqbracket */ { 0x000008aa, 3497 }, /* botrightsqbracket */ { 0x000008ab, 25764 }, /* topleftparens */ { 0x000008ac, 3434 }, /* botleftparens */ { 0x000008ad, 25827 }, /* toprightparens */ { 0x000008ae, 3482 }, /* botrightparens */ { 0x000008af, 19450 }, /* leftmiddlecurlybrace */ { 0x000008b0, 22597 }, /* rightmiddlecurlybrace */ { 0x000008b1, 25810 }, /* topleftsummation */ { 0x000008b2, 3465 }, /* botleftsummation */ { 0x000008b3, 25883 }, /* topvertsummationconnector */ { 0x000008b4, 3538 }, /* botvertsummationconnector */ { 0x000008b5, 25860 }, /* toprightsummation */ { 0x000008b6, 3515 }, /* botrightsummation */ { 0x000008b7, 22619 }, /* rightmiddlesummation */ { 0x000008bc, 19561 }, /* lessthanequal */ { 0x000008bd, 20269 }, /* notequal */ { 0x000008be, 13395 }, /* greaterthanequal */ { 0x000008bf, 17457 }, /* integral */ { 0x000008c0, 25636 }, /* therefore */ { 0x000008c1, 26644 }, /* variation */ { 0x000008c2, 17419 }, /* infinity */ { 0x000008c5, 20091 }, /* nabla */ { 0x000008c8, 954 }, /* approximate */ { 0x000008c9, 23156 }, /* similarequal */ { 0x000008cd, 17340 }, /* ifonlyif */ { 0x000008ce, 17391 }, /* implies */ { 0x000008cf, 17299 }, /* identical */ { 0x000008d6, 22443 }, /* radical */ { 0x000008da, 17399 }, /* includedin */ { 0x000008db, 17410 }, /* includes */ { 0x000008dc, 17466 }, /* intersection */ { 0x000008dd, 26519 }, /* union */ { 0x000008de, 19601 }, /* logicaland */ { 0x000008df, 19612 }, /* logicalor */ { 0x000008ef, 21620 }, /* partialderivative */ { 0x000008f6, 12771 }, /* function */ { 0x000008fb, 19410 }, /* leftarrow */ { 0x000008fc, 26544 }, /* uparrow */ { 0x000008fd, 22554 }, /* rightarrow */ { 0x000008fe, 11447 }, /* downarrow */ { 0x000009df, 3410 }, /* blank */ { 0x000009e0, 23947 }, /* soliddiamond */ { 0x000009e1, 8603 }, /* checkerboard */ { 0x000009e2, 17187 }, /* ht */ { 0x000009e3, 12528 }, /* ff */ { 0x000009e4, 8809 }, /* cr */ { 0x000009e5, 19575 }, /* lf */ { 0x000009e8, 20219 }, /* nl */ { 0x000009e9, 26699 }, /* vt */ { 0x000009ea, 19646 }, /* lowrightcorner */ { 0x000009eb, 26573 }, /* uprightcorner */ { 0x000009ec, 26560 }, /* upleftcorner */ { 0x000009ed, 19632 }, /* lowleftcorner */ { 0x000009ee, 8812 }, /* crossinglines */ { 0x000009ef, 16826 }, /* horizlinescan1 */ { 0x000009f0, 16841 }, /* horizlinescan3 */ { 0x000009f1, 16856 }, /* horizlinescan5 */ { 0x000009f2, 16871 }, /* horizlinescan7 */ { 0x000009f3, 16886 }, /* horizlinescan9 */ { 0x000009f4, 19541 }, /* leftt */ { 0x000009f5, 22702 }, /* rightt */ { 0x000009f6, 3533 }, /* bott */ { 0x000009f7, 25878 }, /* topt */ { 0x000009f8, 26654 }, /* vertbar */ { 0x00000aa1, 12043 }, /* emspace */ { 0x00000aa2, 12142 }, /* enspace */ { 0x00000aa3, 11936 }, /* em3space */ { 0x00000aa4, 11945 }, /* em4space */ { 0x00000aa5, 11336 }, /* digitspace */ { 0x00000aa6, 22302 }, /* punctspace */ { 0x00000aa7, 25646 }, /* thinspace */ { 0x00000aa8, 14526 }, /* hairspace */ { 0x00000aa9, 11970 }, /* emdash */ { 0x00000aaa, 12055 }, /* endash */ { 0x00000aac, 23144 }, /* signifblank */ { 0x00000aae, 11927 }, /* ellipsis */ { 0x00000aaf, 11382 }, /* doubbaselinedot */ { 0x00000ab0, 20911 }, /* onethird */ { 0x00000ab1, 25994 }, /* twothirds */ { 0x00000ab2, 20849 }, /* onefifth */ { 0x00000ab3, 25959 }, /* twofifths */ { 0x00000ab4, 25687 }, /* threefifths */ { 0x00000ab5, 12722 }, /* fourfifths */ { 0x00000ab6, 20877 }, /* onesixth */ { 0x00000ab7, 12684 }, /* fivesixths */ { 0x00000ab8, 8506 }, /* careof */ { 0x00000abb, 12542 }, /* figdash */ { 0x00000abc, 19393 }, /* leftanglebracket */ { 0x00000abd, 11255 }, /* decimalpoint */ { 0x00000abe, 22536 }, /* rightanglebracket */ { 0x00000abf, 19825 }, /* marker */ { 0x00000ac3, 20839 }, /* oneeighth */ { 0x00000ac4, 25674 }, /* threeeighths */ { 0x00000ac5, 12672 }, /* fiveeighths */ { 0x00000ac6, 23061 }, /* seveneighths */ { 0x00000ac9, 25917 }, /* trademark */ { 0x00000aca, 23130 }, /* signaturemark */ { 0x00000acb, 25927 }, /* trademarkincircle */ { 0x00000acc, 19471 }, /* leftopentriangle */ { 0x00000acd, 22640 }, /* rightopentriangle */ { 0x00000ace, 12005 }, /* emopencircle */ { 0x00000acf, 12018 }, /* emopenrectangle */ { 0x00000ad0, 19521 }, /* leftsinglequotemark */ { 0x00000ad1, 22681 }, /* rightsinglequotemark */ { 0x00000ad2, 19430 }, /* leftdoublequotemark */ { 0x00000ad3, 22576 }, /* rightdoublequotemark */ { 0x00000ad4, 22224 }, /* prescription */ { 0x00000ad5, 21674 }, /* permille */ { 0x00000ad6, 19883 }, /* minutes */ { 0x00000ad7, 22868 }, /* seconds */ { 0x00000ad9, 19325 }, /* latincross */ { 0x00000ada, 16770 }, /* hexagram */ { 0x00000adb, 12570 }, /* filledrectbullet */ { 0x00000adc, 12550 }, /* filledlefttribullet */ { 0x00000add, 12587 }, /* filledrighttribullet */ { 0x00000ade, 11977 }, /* emfilledcircle */ { 0x00000adf, 11992 }, /* emfilledrect */ { 0x00000ae0, 12106 }, /* enopencircbullet */ { 0x00000ae1, 12123 }, /* enopensquarebullet */ { 0x00000ae2, 20938 }, /* openrectbullet */ { 0x00000ae3, 20980 }, /* opentribulletup */ { 0x00000ae4, 20962 }, /* opentribulletdown */ { 0x00000ae5, 20953 }, /* openstar */ { 0x00000ae6, 12062 }, /* enfilledcircbullet */ { 0x00000ae7, 12081 }, /* enfilledsqbullet */ { 0x00000ae8, 12628 }, /* filledtribulletup */ { 0x00000ae9, 12608 }, /* filledtribulletdown */ { 0x00000aea, 19488 }, /* leftpointer */ { 0x00000aeb, 22658 }, /* rightpointer */ { 0x00000aec, 8649 }, /* club */ { 0x00000aed, 11328 }, /* diamond */ { 0x00000aee, 16224 }, /* heart */ { 0x00000af0, 19812 }, /* maltesecross */ { 0x00000af1, 10440 }, /* dagger */ { 0x00000af2, 11410 }, /* doubledagger */ { 0x00000af3, 8616 }, /* checkmark */ { 0x00000af4, 3380 }, /* ballotcross */ { 0x00000af5, 20004 }, /* musicalsharp */ { 0x00000af6, 19992 }, /* musicalflat */ { 0x00000af7, 19801 }, /* malesymbol */ { 0x00000af8, 12515 }, /* femalesymbol */ { 0x00000af9, 24511 }, /* telephone */ { 0x00000afa, 24521 }, /* telephonerecorder */ { 0x00000afb, 21694 }, /* phonographcopyright */ { 0x00000afc, 8513 }, /* caret */ { 0x00000afd, 23185 }, /* singlelowquotemark */ { 0x00000afe, 11423 }, /* doublelowquotemark */ { 0x00000aff, 8857 }, /* cursor */ { 0x00000ba3, 19420 }, /* leftcaret */ { 0x00000ba6, 22565 }, /* rightcaret */ { 0x00000ba8, 11457 }, /* downcaret */ { 0x00000ba9, 26552 }, /* upcaret */ { 0x00000bc0, 21481 }, /* overbar */ { 0x00000bc2, 11486 }, /* downtack */ { 0x00000bc3, 26587 }, /* upshoe */ { 0x00000bc4, 11476 }, /* downstile */ { 0x00000bc6, 26494 }, /* underbar */ { 0x00000bca, 18286 }, /* jot */ { 0x00000bcc, 22317 }, /* quad */ { 0x00000bce, 26602 }, /* uptack */ { 0x00000bcf, 8626 }, /* circle */ { 0x00000bd3, 26594 }, /* upstile */ { 0x00000bd6, 11467 }, /* downshoe */ { 0x00000bd8, 22671 }, /* rightshoe */ { 0x00000bda, 19512 }, /* leftshoe */ { 0x00000bdc, 19547 }, /* lefttack */ { 0x00000bfc, 22709 }, /* righttack */ { 0x00000cdf, 16317 }, /* hebrew_doublelowline */ { 0x00000ce0, 16230 }, /* hebrew_aleph */ { 0x00000ce1, 16255 }, /* hebrew_bet */ { 0x00000ce2, 16436 }, /* hebrew_gimel */ { 0x00000ce3, 16290 }, /* hebrew_dalet */ { 0x00000ce4, 16463 }, /* hebrew_he */ { 0x00000ce5, 16675 }, /* hebrew_waw */ { 0x00000ce6, 16721 }, /* hebrew_zain */ { 0x00000ce7, 16278 }, /* hebrew_chet */ { 0x00000ce8, 16652 }, /* hebrew_tet */ { 0x00000ce9, 16686 }, /* hebrew_yod */ { 0x00000cea, 16338 }, /* hebrew_finalkaph */ { 0x00000ceb, 16484 }, /* hebrew_kaph */ { 0x00000cec, 16507 }, /* hebrew_lamed */ { 0x00000ced, 16355 }, /* hebrew_finalmem */ { 0x00000cee, 16520 }, /* hebrew_mem */ { 0x00000cef, 16371 }, /* hebrew_finalnun */ { 0x00000cf0, 16531 }, /* hebrew_nun */ { 0x00000cf1, 16576 }, /* hebrew_samech */ { 0x00000cf2, 16243 }, /* hebrew_ayin */ { 0x00000cf3, 16387 }, /* hebrew_finalpe */ { 0x00000cf4, 16542 }, /* hebrew_pe */ { 0x00000cf5, 16402 }, /* hebrew_finalzade */ { 0x00000cf6, 16697 }, /* hebrew_zade */ { 0x00000cf7, 16552 }, /* hebrew_qoph */ { 0x00000cf8, 16564 }, /* hebrew_resh */ { 0x00000cf9, 16604 }, /* hebrew_shin */ { 0x00000cfa, 16641 }, /* hebrew_taw */ { 0x00000da1, 24774 }, /* Thai_kokai */ { 0x00000da2, 24704 }, /* Thai_khokhai */ { 0x00000da3, 24730 }, /* Thai_khokhuat */ { 0x00000da4, 24744 }, /* Thai_khokhwai */ { 0x00000da5, 24717 }, /* Thai_khokhon */ { 0x00000da6, 24758 }, /* Thai_khorakhang */ { 0x00000da7, 25087 }, /* Thai_ngongu */ { 0x00000da8, 24580 }, /* Thai_chochan */ { 0x00000da9, 24607 }, /* Thai_choching */ { 0x00000daa, 24593 }, /* Thai_chochang */ { 0x00000dab, 25448 }, /* Thai_soso */ { 0x00000dac, 24621 }, /* Thai_chochoe */ { 0x00000dad, 25624 }, /* Thai_yoying */ { 0x00000dae, 24634 }, /* Thai_dochada */ { 0x00000daf, 25577 }, /* Thai_topatak */ { 0x00000db0, 25536 }, /* Thai_thothan */ { 0x00000db1, 25486 }, /* Thai_thonangmontho */ { 0x00000db2, 25505 }, /* Thai_thophuthao */ { 0x00000db3, 25113 }, /* Thai_nonen */ { 0x00000db4, 24647 }, /* Thai_dodek */ { 0x00000db5, 25590 }, /* Thai_totao */ { 0x00000db6, 25563 }, /* Thai_thothung */ { 0x00000db7, 25521 }, /* Thai_thothahan */ { 0x00000db8, 25549 }, /* Thai_thothong */ { 0x00000db9, 25124 }, /* Thai_nonu */ { 0x00000dba, 24566 }, /* Thai_bobaimai */ { 0x00000dbb, 25215 }, /* Thai_popla */ { 0x00000dbc, 25185 }, /* Thai_phophung */ { 0x00000dbd, 24658 }, /* Thai_fofa */ { 0x00000dbe, 25172 }, /* Thai_phophan */ { 0x00000dbf, 24668 }, /* Thai_fofan */ { 0x00000dc0, 25199 }, /* Thai_phosamphao */ { 0x00000dc1, 25077 }, /* Thai_moma */ { 0x00000dc2, 25613 }, /* Thai_yoyak */ { 0x00000dc3, 25226 }, /* Thai_rorua */ { 0x00000dc4, 25237 }, /* Thai_ru */ { 0x00000dc5, 24937 }, /* Thai_loling */ { 0x00000dc6, 24949 }, /* Thai_lu */ { 0x00000dc7, 25601 }, /* Thai_wowaen */ { 0x00000dc8, 25436 }, /* Thai_sosala */ { 0x00000dc9, 25424 }, /* Thai_sorusi */ { 0x00000dca, 25458 }, /* Thai_sosua */ { 0x00000dcb, 24679 }, /* Thai_hohip */ { 0x00000dcc, 24924 }, /* Thai_lochula */ { 0x00000dcd, 25134 }, /* Thai_oang */ { 0x00000dce, 24690 }, /* Thai_honokhuk */ { 0x00000dcf, 25144 }, /* Thai_paiyannoi */ { 0x00000dd0, 25245 }, /* Thai_saraa */ { 0x00000dd1, 24985 }, /* Thai_maihanakat */ { 0x00000dd2, 25256 }, /* Thai_saraaa */ { 0x00000dd3, 25319 }, /* Thai_saraam */ { 0x00000dd4, 25342 }, /* Thai_sarai */ { 0x00000dd5, 25353 }, /* Thai_saraii */ { 0x00000dd6, 25387 }, /* Thai_saraue */ { 0x00000dd7, 25399 }, /* Thai_sarauee */ { 0x00000dd8, 25376 }, /* Thai_sarau */ { 0x00000dd9, 25412 }, /* Thai_sarauu */ { 0x00000dda, 25159 }, /* Thai_phinthu */ { 0x00000dde, 25001 }, /* Thai_maihanakat_maitho */ { 0x00000ddf, 24556 }, /* Thai_baht */ { 0x00000de0, 25331 }, /* Thai_sarae */ { 0x00000de1, 25268 }, /* Thai_saraae */ { 0x00000de2, 25365 }, /* Thai_sarao */ { 0x00000de3, 25300 }, /* Thai_saraaimaimuan */ { 0x00000de4, 25280 }, /* Thai_saraaimaimalai */ { 0x00000de5, 24785 }, /* Thai_lakkhangyao */ { 0x00000de6, 25063 }, /* Thai_maiyamok */ { 0x00000de7, 25024 }, /* Thai_maitaikhu */ { 0x00000de8, 24974 }, /* Thai_maiek */ { 0x00000de9, 25039 }, /* Thai_maitho */ { 0x00000dea, 25051 }, /* Thai_maitri */ { 0x00000deb, 24957 }, /* Thai_maichattawa */ { 0x00000dec, 25469 }, /* Thai_thanthakhat */ { 0x00000ded, 25099 }, /* Thai_nikhahit */ { 0x00000df0, 24912 }, /* Thai_leksun */ { 0x00000df1, 24850 }, /* Thai_leknung */ { 0x00000df2, 24899 }, /* Thai_leksong */ { 0x00000df3, 24876 }, /* Thai_leksam */ { 0x00000df4, 24888 }, /* Thai_leksi */ { 0x00000df5, 24815 }, /* Thai_lekha */ { 0x00000df6, 24826 }, /* Thai_lekhok */ { 0x00000df7, 24802 }, /* Thai_lekchet */ { 0x00000df8, 24863 }, /* Thai_lekpaet */ { 0x00000df9, 24838 }, /* Thai_lekkao */ { 0x00000ea1, 15325 }, /* Hangul_Kiyeog */ { 0x00000ea2, 15870 }, /* Hangul_SsangKiyeog */ { 0x00000ea3, 15339 }, /* Hangul_KiyeogSios */ { 0x00000ea4, 15420 }, /* Hangul_Nieun */ { 0x00000ea5, 15451 }, /* Hangul_NieunJieuj */ { 0x00000ea6, 15433 }, /* Hangul_NieunHieuh */ { 0x00000ea7, 14632 }, /* Hangul_Dikeud */ { 0x00000ea8, 15833 }, /* Hangul_SsangDikeud */ { 0x00000ea9, 15605 }, /* Hangul_Rieul */ { 0x00000eaa, 15636 }, /* Hangul_RieulKiyeog */ { 0x00000eab, 15655 }, /* Hangul_RieulMieum */ { 0x00000eac, 15692 }, /* Hangul_RieulPieub */ { 0x00000ead, 15710 }, /* Hangul_RieulSios */ { 0x00000eae, 15727 }, /* Hangul_RieulTieut */ { 0x00000eaf, 15673 }, /* Hangul_RieulPhieuf */ { 0x00000eb0, 15618 }, /* Hangul_RieulHieuh */ { 0x00000eb1, 15382 }, /* Hangul_Mieum */ { 0x00000eb2, 15517 }, /* Hangul_Pieub */ { 0x00000eb3, 15889 }, /* Hangul_SsangPieub */ { 0x00000eb4, 15530 }, /* Hangul_PieubSios */ { 0x00000eb5, 15806 }, /* Hangul_Sios */ { 0x00000eb6, 15907 }, /* Hangul_SsangSios */ { 0x00000eb7, 14721 }, /* Hangul_Ieung */ { 0x00000eb8, 15298 }, /* Hangul_Jieuj */ { 0x00000eb9, 15852 }, /* Hangul_SsangJieuj */ { 0x00000eba, 14602 }, /* Hangul_Cieuc */ { 0x00000ebb, 15311 }, /* Hangul_Khieuq */ { 0x00000ebc, 16027 }, /* Hangul_Tieut */ { 0x00000ebd, 15503 }, /* Hangul_Phieuf */ { 0x00000ebe, 14699 }, /* Hangul_Hieuh */ { 0x00000ebf, 14543 }, /* Hangul_A */ { 0x00000ec0, 14552 }, /* Hangul_AE */ { 0x00000ec1, 16101 }, /* Hangul_YA */ { 0x00000ec2, 16111 }, /* Hangul_YAE */ { 0x00000ec3, 14666 }, /* Hangul_EO */ { 0x00000ec4, 14646 }, /* Hangul_E */ { 0x00000ec5, 16132 }, /* Hangul_YEO */ { 0x00000ec6, 16122 }, /* Hangul_YE */ { 0x00000ec7, 15469 }, /* Hangul_O */ { 0x00000ec8, 16049 }, /* Hangul_WA */ { 0x00000ec9, 16059 }, /* Hangul_WAE */ { 0x00000eca, 15478 }, /* Hangul_OE */ { 0x00000ecb, 16172 }, /* Hangul_YO */ { 0x00000ecc, 16040 }, /* Hangul_U */ { 0x00000ecd, 16080 }, /* Hangul_WEO */ { 0x00000ece, 16070 }, /* Hangul_WE */ { 0x00000ecf, 16091 }, /* Hangul_WI */ { 0x00000ed0, 16182 }, /* Hangul_YU */ { 0x00000ed1, 14676 }, /* Hangul_EU */ { 0x00000ed2, 16162 }, /* Hangul_YI */ { 0x00000ed3, 14712 }, /* Hangul_I */ { 0x00000ed4, 14826 }, /* Hangul_J_Kiyeog */ { 0x00000ed5, 15196 }, /* Hangul_J_SsangKiyeog */ { 0x00000ed6, 14842 }, /* Hangul_J_KiyeogSios */ { 0x00000ed7, 14904 }, /* Hangul_J_Nieun */ { 0x00000ed8, 14939 }, /* Hangul_J_NieunJieuj */ { 0x00000ed9, 14919 }, /* Hangul_J_NieunHieuh */ { 0x00000eda, 14749 }, /* Hangul_J_Dikeud */ { 0x00000edb, 15026 }, /* Hangul_J_Rieul */ { 0x00000edc, 15061 }, /* Hangul_J_RieulKiyeog */ { 0x00000edd, 15082 }, /* Hangul_J_RieulMieum */ { 0x00000ede, 15123 }, /* Hangul_J_RieulPieub */ { 0x00000edf, 15143 }, /* Hangul_J_RieulSios */ { 0x00000ee0, 15162 }, /* Hangul_J_RieulTieut */ { 0x00000ee1, 15102 }, /* Hangul_J_RieulPhieuf */ { 0x00000ee2, 15041 }, /* Hangul_J_RieulHieuh */ { 0x00000ee3, 14889 }, /* Hangul_J_Mieum */ { 0x00000ee4, 14992 }, /* Hangul_J_Pieub */ { 0x00000ee5, 15007 }, /* Hangul_J_PieubSios */ { 0x00000ee6, 15182 }, /* Hangul_J_Sios */ { 0x00000ee7, 15217 }, /* Hangul_J_SsangSios */ { 0x00000ee8, 14780 }, /* Hangul_J_Ieung */ { 0x00000ee9, 14795 }, /* Hangul_J_Jieuj */ { 0x00000eea, 14734 }, /* Hangul_J_Cieuc */ { 0x00000eeb, 14810 }, /* Hangul_J_Khieuq */ { 0x00000eec, 15236 }, /* Hangul_J_Tieut */ { 0x00000eed, 14976 }, /* Hangul_J_Phieuf */ { 0x00000eee, 14765 }, /* Hangul_J_Hieuh */ { 0x00000eef, 15745 }, /* Hangul_RieulYeorinHieuh */ { 0x00000ef0, 15937 }, /* Hangul_SunkyeongeumMieum */ { 0x00000ef1, 15988 }, /* Hangul_SunkyeongeumPieub */ { 0x00000ef2, 15488 }, /* Hangul_PanSios */ { 0x00000ef3, 15357 }, /* Hangul_KkogjiDalrinIeung */ { 0x00000ef4, 15962 }, /* Hangul_SunkyeongeumPhieuf */ { 0x00000ef5, 16143 }, /* Hangul_YeorinHieuh */ { 0x00000ef6, 14562 }, /* Hangul_AraeA */ { 0x00000ef7, 14575 }, /* Hangul_AraeAE */ { 0x00000ef8, 14959 }, /* Hangul_J_PanSios */ { 0x00000ef9, 14862 }, /* Hangul_J_KkogjiDalrinIeung */ { 0x00000efa, 15251 }, /* Hangul_J_YeorinHieuh */ { 0x00000eff, 18941 }, /* Korean_Won */ { 0x000013bc, 20658 }, /* OE */ { 0x000013bd, 20661 }, /* oe */ { 0x000013be, 32441 }, /* Ydiaeresis */ { 0x000020ac, 12205 }, /* EuroSign */ { 0x0000fd01, 125 }, /* 3270_Duplicate */ { 0x0000fd02, 195 }, /* 3270_FieldMark */ { 0x0000fd03, 343 }, /* 3270_Right2 */ { 0x0000fd04, 245 }, /* 3270_Left2 */ { 0x0000fd05, 33 }, /* 3270_BackTab */ { 0x0000fd06, 151 }, /* 3270_EraseEOF */ { 0x0000fd07, 165 }, /* 3270_EraseInput */ { 0x0000fd08, 332 }, /* 3270_Reset */ { 0x0000fd09, 310 }, /* 3270_Quit */ { 0x0000fd0a, 256 }, /* 3270_PA1 */ { 0x0000fd0b, 265 }, /* 3270_PA2 */ { 0x0000fd0c, 274 }, /* 3270_PA3 */ { 0x0000fd0d, 376 }, /* 3270_Test */ { 0x0000fd0e, 23 }, /* 3270_Attn */ { 0x0000fd0f, 74 }, /* 3270_CursorBlink */ { 0x0000fd10, 8 }, /* 3270_AltCursor */ { 0x0000fd11, 231 }, /* 3270_KeyClick */ { 0x0000fd12, 221 }, /* 3270_Jump */ { 0x0000fd13, 210 }, /* 3270_Ident */ { 0x0000fd14, 355 }, /* 3270_Rule */ { 0x0000fd15, 64 }, /* 3270_Copy */ { 0x0000fd16, 283 }, /* 3270_Play */ { 0x0000fd17, 365 }, /* 3270_Setup */ { 0x0000fd18, 320 }, /* 3270_Record */ { 0x0000fd19, 46 }, /* 3270_ChangeScreen */ { 0x0000fd1a, 109 }, /* 3270_DeleteWord */ { 0x0000fd1b, 181 }, /* 3270_ExSelect */ { 0x0000fd1c, 91 }, /* 3270_CursorSelect */ { 0x0000fd1d, 293 }, /* 3270_PrintScreen */ { 0x0000fd1e, 140 }, /* 3270_Enter */ { 0x0000fe01, 17925 }, /* ISO_Lock */ { 0x0000fe02, 17808 }, /* ISO_Level2_Latch */ { 0x0000fe03, 17858 }, /* ISO_Level3_Shift */ { 0x0000fe04, 17825 }, /* ISO_Level3_Latch */ { 0x0000fe05, 17842 }, /* ISO_Level3_Lock */ { 0x0000fe06, 17713 }, /* ISO_Group_Latch */ { 0x0000fe07, 17729 }, /* ISO_Group_Lock */ { 0x0000fe08, 17970 }, /* ISO_Next_Group */ { 0x0000fe09, 17985 }, /* ISO_Next_Group_Lock */ { 0x0000fe0a, 18094 }, /* ISO_Prev_Group */ { 0x0000fe0b, 18109 }, /* ISO_Prev_Group_Lock */ { 0x0000fe0c, 17676 }, /* ISO_First_Group */ { 0x0000fe0d, 17692 }, /* ISO_First_Group_Lock */ { 0x0000fe0e, 17760 }, /* ISO_Last_Group */ { 0x0000fe0f, 17775 }, /* ISO_Last_Group_Lock */ { 0x0000fe11, 17908 }, /* ISO_Level5_Shift */ { 0x0000fe12, 17875 }, /* ISO_Level5_Latch */ { 0x0000fe13, 17892 }, /* ISO_Level5_Lock */ { 0x0000fe20, 17795 }, /* ISO_Left_Tab */ { 0x0000fe21, 17953 }, /* ISO_Move_Line_Up */ { 0x0000fe22, 17934 }, /* ISO_Move_Line_Down */ { 0x0000fe23, 18027 }, /* ISO_Partial_Line_Up */ { 0x0000fe24, 18005 }, /* ISO_Partial_Line_Down */ { 0x0000fe25, 18047 }, /* ISO_Partial_Space_Left */ { 0x0000fe26, 18070 }, /* ISO_Partial_Space_Right */ { 0x0000fe27, 18203 }, /* ISO_Set_Margin_Left */ { 0x0000fe28, 18223 }, /* ISO_Set_Margin_Right */ { 0x0000fe29, 18154 }, /* ISO_Release_Margin_Left */ { 0x0000fe2a, 18178 }, /* ISO_Release_Margin_Right */ { 0x0000fe2b, 18129 }, /* ISO_Release_Both_Margins */ { 0x0000fe2c, 17614 }, /* ISO_Fast_Cursor_Left */ { 0x0000fe2d, 17635 }, /* ISO_Fast_Cursor_Right */ { 0x0000fe2e, 17657 }, /* ISO_Fast_Cursor_Up */ { 0x0000fe2f, 17593 }, /* ISO_Fast_Cursor_Down */ { 0x0000fe30, 17516 }, /* ISO_Continuous_Underline */ { 0x0000fe31, 17541 }, /* ISO_Discontinuous_Underline */ { 0x0000fe32, 17569 }, /* ISO_Emphasize */ { 0x0000fe33, 17498 }, /* ISO_Center_Object */ { 0x0000fe34, 17583 }, /* ISO_Enter */ { 0x0000fe50, 10940 }, /* dead_grave */ { 0x0000fe51, 10613 }, /* dead_acute */ { 0x0000fe52, 10836 }, /* dead_circumflex */ { 0x0000fe53, 11212 }, /* dead_tilde */ { 0x0000fe54, 11073 }, /* dead_macron */ { 0x0000fe55, 10782 }, /* dead_breve */ { 0x0000fe56, 10537 }, /* dead_abovedot */ { 0x0000fe57, 10877 }, /* dead_diaeresis */ { 0x0000fe58, 10575 }, /* dead_abovering */ { 0x0000fe59, 10892 }, /* dead_doubleacute */ { 0x0000fe5a, 10812 }, /* dead_caron */ { 0x0000fe5b, 10823 }, /* dead_cedilla */ { 0x0000fe5c, 11099 }, /* dead_ogonek */ { 0x0000fe5d, 11026 }, /* dead_iota */ { 0x0000fe5e, 11237 }, /* dead_voiced_sound */ { 0x0000fe5f, 11161 }, /* dead_semivoiced_sound */ { 0x0000fe60, 10697 }, /* dead_belowdot */ { 0x0000fe61, 10973 }, /* dead_hook */ { 0x0000fe62, 10983 }, /* dead_horn */ { 0x0000fe63, 11200 }, /* dead_stroke */ { 0x0000fe64, 10521 }, /* dead_abovecomma */ { 0x0000fe65, 10551 }, /* dead_abovereversedcomma */ { 0x0000fe66, 10909 }, /* dead_doublegrave */ { 0x0000fe67, 10728 }, /* dead_belowring */ { 0x0000fe68, 10711 }, /* dead_belowmacron */ { 0x0000fe69, 10640 }, /* dead_belowcircumflex */ { 0x0000fe6a, 10743 }, /* dead_belowtilde */ { 0x0000fe6b, 10624 }, /* dead_belowbreve */ { 0x0000fe6c, 10677 }, /* dead_belowdiaeresis */ { 0x0000fe6d, 11007 }, /* dead_invertedbreve */ { 0x0000fe6e, 10661 }, /* dead_belowcomma */ { 0x0000fe6f, 10852 }, /* dead_currency */ { 0x0000fe70, 583 }, /* AccessX_Enable */ { 0x0000fe71, 598 }, /* AccessX_Feedback_Enable */ { 0x0000fe72, 22499 }, /* RepeatKeys_Enable */ { 0x0000fe73, 23931 }, /* SlowKeys_Enable */ { 0x0000fe74, 3564 }, /* BounceKeys_Enable */ { 0x0000fe75, 23993 }, /* StickyKeys_Enable */ { 0x0000fe76, 19926 }, /* MouseKeys_Enable */ { 0x0000fe77, 19903 }, /* MouseKeys_Accel_Enable */ { 0x0000fe78, 21489 }, /* Overlay1_Enable */ { 0x0000fe79, 21505 }, /* Overlay2_Enable */ { 0x0000fe7a, 3309 }, /* AudibleBell_Enable */ { 0x0000fe80, 10514 }, /* dead_a */ { 0x0000fe81, 10507 }, /* dead_A */ { 0x0000fe82, 10933 }, /* dead_e */ { 0x0000fe83, 10926 }, /* dead_E */ { 0x0000fe84, 11000 }, /* dead_i */ { 0x0000fe85, 10993 }, /* dead_I */ { 0x0000fe86, 11092 }, /* dead_o */ { 0x0000fe87, 11085 }, /* dead_O */ { 0x0000fe88, 11230 }, /* dead_u */ { 0x0000fe89, 11223 }, /* dead_U */ { 0x0000fe8a, 11183 }, /* dead_small_schwa */ { 0x0000fe8b, 10793 }, /* dead_capital_schwa */ { 0x0000fe8c, 10951 }, /* dead_greek */ { 0x0000fe8d, 10962 }, /* dead_hamza */ { 0x0000fe90, 11060 }, /* dead_lowline */ { 0x0000fe91, 10590 }, /* dead_aboveverticalline */ { 0x0000fe92, 10759 }, /* dead_belowverticalline */ { 0x0000fe93, 11036 }, /* dead_longsolidusoverlay */ { 0x0000fea0, 8600 }, /* ch */ { 0x0000fea1, 8597 }, /* Ch */ { 0x0000fea2, 8594 }, /* CH */ { 0x0000fea3, 8451 }, /* c_h */ { 0x0000fea4, 8447 }, /* C_h */ { 0x0000fea5, 8443 }, /* C_H */ { 0x0000fed0, 12651 }, /* First_Virtual_Screen */ { 0x0000fed1, 22237 }, /* Prev_Virtual_Screen */ { 0x0000fed2, 20172 }, /* Next_Virtual_Screen */ { 0x0000fed4, 19305 }, /* Last_Virtual_Screen */ { 0x0000fed5, 24539 }, /* Terminate_Server */ { 0x0000fee0, 22155 }, /* Pointer_Left */ { 0x0000fee1, 22168 }, /* Pointer_Right */ { 0x0000fee2, 22182 }, /* Pointer_Up */ { 0x0000fee3, 22000 }, /* Pointer_Down */ { 0x0000fee4, 22193 }, /* Pointer_UpLeft */ { 0x0000fee5, 22208 }, /* Pointer_UpRight */ { 0x0000fee6, 22013 }, /* Pointer_DownLeft */ { 0x0000fee7, 22030 }, /* Pointer_DownRight */ { 0x0000fee8, 21828 }, /* Pointer_Button_Dflt */ { 0x0000fee9, 21748 }, /* Pointer_Button1 */ { 0x0000feea, 21764 }, /* Pointer_Button2 */ { 0x0000feeb, 21780 }, /* Pointer_Button3 */ { 0x0000feec, 21796 }, /* Pointer_Button4 */ { 0x0000feed, 21812 }, /* Pointer_Button5 */ { 0x0000feee, 21938 }, /* Pointer_DblClick_Dflt */ { 0x0000feef, 21848 }, /* Pointer_DblClick1 */ { 0x0000fef0, 21866 }, /* Pointer_DblClick2 */ { 0x0000fef1, 21884 }, /* Pointer_DblClick3 */ { 0x0000fef2, 21902 }, /* Pointer_DblClick4 */ { 0x0000fef3, 21920 }, /* Pointer_DblClick5 */ { 0x0000fef4, 22118 }, /* Pointer_Drag_Dflt */ { 0x0000fef5, 22048 }, /* Pointer_Drag1 */ { 0x0000fef6, 22062 }, /* Pointer_Drag2 */ { 0x0000fef7, 22076 }, /* Pointer_Drag3 */ { 0x0000fef8, 22090 }, /* Pointer_Drag4 */ { 0x0000fef9, 22136 }, /* Pointer_EnableKeys */ { 0x0000fefa, 21729 }, /* Pointer_Accelerate */ { 0x0000fefb, 21960 }, /* Pointer_DfltBtnNext */ { 0x0000fefc, 21980 }, /* Pointer_DfltBtnPrev */ { 0x0000fefd, 22104 }, /* Pointer_Drag5 */ { 0x0000ff08, 3362 }, /* BackSpace */ { 0x0000ff09, 24455 }, /* Tab */ { 0x0000ff0a, 19578 }, /* Linefeed */ { 0x0000ff0b, 8633 }, /* Clear */ { 0x0000ff0d, 22523 }, /* Return */ { 0x0000ff13, 21638 }, /* Pause */ { 0x0000ff14, 22856 }, /* Scroll_Lock */ { 0x0000ff15, 24436 }, /* Sys_Req */ { 0x0000ff1b, 12172 }, /* Escape */ { 0x0000ff20, 19955 }, /* Multi_key */ { 0x0000ff21, 18889 }, /* Kanji */ { 0x0000ff22, 19946 }, /* Muhenkan */ { 0x0000ff23, 16758 }, /* Henkan_Mode */ { 0x0000ff24, 22719 }, /* Romaji */ { 0x0000ff25, 16779 }, /* Hiragana */ { 0x0000ff26, 18914 }, /* Katakana */ { 0x0000ff27, 16788 }, /* Hiragana_Katakana */ { 0x0000ff28, 32568 }, /* Zenkaku */ { 0x0000ff29, 16192 }, /* Hankaku */ { 0x0000ff2a, 32576 }, /* Zenkaku_Hankaku */ { 0x0000ff2b, 25909 }, /* Touroku */ { 0x0000ff2c, 19842 }, /* Massyo */ { 0x0000ff2d, 18495 }, /* Kana_Lock */ { 0x0000ff2e, 18706 }, /* Kana_Shift */ { 0x0000ff2f, 11894 }, /* Eisu_Shift */ { 0x0000ff30, 11905 }, /* Eisu_toggle */ { 0x0000ff31, 14536 }, /* Hangul */ { 0x0000ff32, 15924 }, /* Hangul_Start */ { 0x0000ff33, 14655 }, /* Hangul_End */ { 0x0000ff34, 14686 }, /* Hangul_Hanja */ { 0x0000ff35, 15272 }, /* Hangul_Jamo */ { 0x0000ff36, 15769 }, /* Hangul_Romaja */ { 0x0000ff37, 8654 }, /* Codeinput */ { 0x0000ff38, 15284 }, /* Hangul_Jeonja */ { 0x0000ff39, 14589 }, /* Hangul_Banja */ { 0x0000ff3a, 15564 }, /* Hangul_PreHanja */ { 0x0000ff3b, 15547 }, /* Hangul_PostHanja */ { 0x0000ff3c, 23169 }, /* SingleCandidate */ { 0x0000ff3d, 19965 }, /* MultipleCandidate */ { 0x0000ff3e, 22257 }, /* PreviousCandidate */ { 0x0000ff3f, 15818 }, /* Hangul_Special */ { 0x0000ff50, 16806 }, /* Home */ { 0x0000ff51, 19388 }, /* Left */ { 0x0000ff52, 26541 }, /* Up */ { 0x0000ff53, 22530 }, /* Right */ { 0x0000ff54, 11442 }, /* Down */ { 0x0000ff55, 22281 }, /* Prior */ { 0x0000ff56, 20167 }, /* Next */ { 0x0000ff57, 12051 }, /* End */ { 0x0000ff58, 3404 }, /* Begin */ { 0x0000ff60, 22884 }, /* Select */ { 0x0000ff61, 22275 }, /* Print */ { 0x0000ff62, 12232 }, /* Execute */ { 0x0000ff63, 17428 }, /* Insert */ { 0x0000ff65, 26514 }, /* Undo */ { 0x0000ff66, 22483 }, /* Redo */ { 0x0000ff67, 19849 }, /* Menu */ { 0x0000ff68, 12646 }, /* Find */ { 0x0000ff69, 8489 }, /* Cancel */ { 0x0000ff6a, 16746 }, /* Help */ { 0x0000ff6b, 8377 }, /* Break */ { 0x0000ff7e, 19891 }, /* Mode_switch */ { 0x0000ff7f, 20313 }, /* Num_Lock */ { 0x0000ff80, 19218 }, /* KP_Space */ { 0x0000ff89, 19239 }, /* KP_Tab */ { 0x0000ff8d, 19075 }, /* KP_Enter */ { 0x0000ff91, 19093 }, /* KP_F1 */ { 0x0000ff92, 19099 }, /* KP_F2 */ { 0x0000ff93, 19105 }, /* KP_F3 */ { 0x0000ff94, 19111 }, /* KP_F4 */ { 0x0000ff95, 19117 }, /* KP_Home */ { 0x0000ff96, 19135 }, /* KP_Left */ { 0x0000ff97, 19246 }, /* KP_Up */ { 0x0000ff98, 19196 }, /* KP_Right */ { 0x0000ff99, 19060 }, /* KP_Down */ { 0x0000ff9a, 19187 }, /* KP_Prior */ { 0x0000ff9b, 19155 }, /* KP_Next */ { 0x0000ff9c, 19068 }, /* KP_End */ { 0x0000ff9d, 19020 }, /* KP_Begin */ { 0x0000ff9e, 19125 }, /* KP_Insert */ { 0x0000ff9f, 19040 }, /* KP_Delete */ { 0x0000ffaa, 19143 }, /* KP_Multiply */ { 0x0000ffab, 19002 }, /* KP_Add */ { 0x0000ffac, 19205 }, /* KP_Separator */ { 0x0000ffad, 19227 }, /* KP_Subtract */ { 0x0000ffae, 19029 }, /* KP_Decimal */ { 0x0000ffaf, 19050 }, /* KP_Divide */ { 0x0000ffb0, 18952 }, /* KP_0 */ { 0x0000ffb1, 18957 }, /* KP_1 */ { 0x0000ffb2, 18962 }, /* KP_2 */ { 0x0000ffb3, 18967 }, /* KP_3 */ { 0x0000ffb4, 18972 }, /* KP_4 */ { 0x0000ffb5, 18977 }, /* KP_5 */ { 0x0000ffb6, 18982 }, /* KP_6 */ { 0x0000ffb7, 18987 }, /* KP_7 */ { 0x0000ffb8, 18992 }, /* KP_8 */ { 0x0000ffb9, 18997 }, /* KP_9 */ { 0x0000ffbd, 19084 }, /* KP_Equal */ { 0x0000ffbe, 12274 }, /* F1 */ { 0x0000ffbf, 12317 }, /* F2 */ { 0x0000ffc0, 12360 }, /* F3 */ { 0x0000ffc1, 12387 }, /* F4 */ { 0x0000ffc2, 12390 }, /* F5 */ { 0x0000ffc3, 12393 }, /* F6 */ { 0x0000ffc4, 12396 }, /* F7 */ { 0x0000ffc5, 12399 }, /* F8 */ { 0x0000ffc6, 12402 }, /* F9 */ { 0x0000ffc7, 12277 }, /* F10 */ { 0x0000ffc8, 12281 }, /* F11 */ { 0x0000ffc9, 12285 }, /* F12 */ { 0x0000ffca, 12289 }, /* F13 */ { 0x0000ffcb, 12293 }, /* F14 */ { 0x0000ffcc, 12297 }, /* F15 */ { 0x0000ffcd, 12301 }, /* F16 */ { 0x0000ffce, 12305 }, /* F17 */ { 0x0000ffcf, 12309 }, /* F18 */ { 0x0000ffd0, 12313 }, /* F19 */ { 0x0000ffd1, 12320 }, /* F20 */ { 0x0000ffd2, 12324 }, /* F21 */ { 0x0000ffd3, 12328 }, /* F22 */ { 0x0000ffd4, 12332 }, /* F23 */ { 0x0000ffd5, 12336 }, /* F24 */ { 0x0000ffd6, 12340 }, /* F25 */ { 0x0000ffd7, 12344 }, /* F26 */ { 0x0000ffd8, 12348 }, /* F27 */ { 0x0000ffd9, 12352 }, /* F28 */ { 0x0000ffda, 12356 }, /* F29 */ { 0x0000ffdb, 12363 }, /* F30 */ { 0x0000ffdc, 12367 }, /* F31 */ { 0x0000ffdd, 12371 }, /* F32 */ { 0x0000ffde, 12375 }, /* F33 */ { 0x0000ffdf, 12379 }, /* F34 */ { 0x0000ffe0, 12383 }, /* F35 */ { 0x0000ffe1, 23103 }, /* Shift_L */ { 0x0000ffe2, 23122 }, /* Shift_R */ { 0x0000ffe3, 8779 }, /* Control_L */ { 0x0000ffe4, 8789 }, /* Control_R */ { 0x0000ffe5, 8496 }, /* Caps_Lock */ { 0x0000ffe6, 23111 }, /* Shift_Lock */ { 0x0000ffe7, 19854 }, /* Meta_L */ { 0x0000ffe8, 19861 }, /* Meta_R */ { 0x0000ffe9, 880 }, /* Alt_L */ { 0x0000ffea, 886 }, /* Alt_R */ { 0x0000ffeb, 24420 }, /* Super_L */ { 0x0000ffec, 24428 }, /* Super_R */ { 0x0000ffed, 17190 }, /* Hyper_L */ { 0x0000ffee, 17198 }, /* Hyper_R */ { 0x0000fff1, 3642 }, /* braille_dot_1 */ { 0x0000fff2, 3671 }, /* braille_dot_2 */ { 0x0000fff3, 3685 }, /* braille_dot_3 */ { 0x0000fff4, 3699 }, /* braille_dot_4 */ { 0x0000fff5, 3713 }, /* braille_dot_5 */ { 0x0000fff6, 3727 }, /* braille_dot_6 */ { 0x0000fff7, 3741 }, /* braille_dot_7 */ { 0x0000fff8, 3755 }, /* braille_dot_8 */ { 0x0000fff9, 3769 }, /* braille_dot_9 */ { 0x0000fffa, 3656 }, /* braille_dot_10 */ { 0x0000ffff, 11275 }, /* Delete */ { 0x00ffffff, 26688 }, /* VoidSymbol */ { 0x0100012c, 17261 }, /* Ibreve */ { 0x0100012d, 17268 }, /* ibreve */ { 0x01000174, 26720 }, /* Wcircumflex */ { 0x01000175, 26732 }, /* wcircumflex */ { 0x01000176, 32417 }, /* Ycircumflex */ { 0x01000177, 32429 }, /* ycircumflex */ { 0x0100018f, 22806 }, /* SCHWA */ { 0x0100019f, 20362 }, /* Obarred */ { 0x010001a0, 20697 }, /* Ohorn */ { 0x010001a1, 20703 }, /* ohorn */ { 0x010001af, 26154 }, /* Uhorn */ { 0x010001b0, 26160 }, /* uhorn */ { 0x010001b5, 32619 }, /* Zstroke */ { 0x010001b6, 32627 }, /* zstroke */ { 0x010001b7, 12262 }, /* EZH */ { 0x010001d1, 20398 }, /* Ocaron */ { 0x010001d2, 20405 }, /* ocaron */ { 0x010001e6, 12818 }, /* Gcaron */ { 0x010001e7, 12825 }, /* gcaron */ { 0x01000259, 22812 }, /* schwa */ { 0x01000275, 20370 }, /* obarred */ { 0x01000292, 12266 }, /* ezh */ { 0x01000300, 8715 }, /* combining_grave */ { 0x01000301, 8680 }, /* combining_acute */ { 0x01000303, 8746 }, /* combining_tilde */ { 0x01000309, 8731 }, /* combining_hook */ { 0x01000323, 8696 }, /* combining_belowdot */ { 0x01000492, 9318 }, /* Cyrillic_GHE_bar */ { 0x01000493, 9335 }, /* Cyrillic_ghe_bar */ { 0x01000496, 10356 }, /* Cyrillic_ZHE_descender */ { 0x01000497, 10379 }, /* Cyrillic_zhe_descender */ { 0x0100049a, 9610 }, /* Cyrillic_KA_descender */ { 0x0100049b, 9632 }, /* Cyrillic_ka_descender */ { 0x0100049c, 9654 }, /* Cyrillic_KA_vertstroke */ { 0x0100049d, 9677 }, /* Cyrillic_ka_vertstroke */ { 0x010004a2, 9200 }, /* Cyrillic_EN_descender */ { 0x010004a3, 9222 }, /* Cyrillic_en_descender */ { 0x010004ae, 10118 }, /* Cyrillic_U_straight */ { 0x010004af, 10138 }, /* Cyrillic_u_straight */ { 0x010004b0, 10158 }, /* Cyrillic_U_straight_bar */ { 0x010004b1, 10182 }, /* Cyrillic_u_straight_bar */ { 0x010004b2, 9376 }, /* Cyrillic_HA_descender */ { 0x010004b3, 9398 }, /* Cyrillic_ha_descender */ { 0x010004b6, 8936 }, /* Cyrillic_CHE_descender */ { 0x010004b7, 8959 }, /* Cyrillic_che_descender */ { 0x010004b8, 8982 }, /* Cyrillic_CHE_vertstroke */ { 0x010004b9, 9006 }, /* Cyrillic_che_vertstroke */ { 0x010004ba, 9914 }, /* Cyrillic_SHHA */ { 0x010004bb, 9928 }, /* Cyrillic_shha */ { 0x010004d8, 9828 }, /* Cyrillic_SCHWA */ { 0x010004d9, 9843 }, /* Cyrillic_schwa */ { 0x010004e2, 9478 }, /* Cyrillic_I_macron */ { 0x010004e3, 9496 }, /* Cyrillic_i_macron */ { 0x010004e8, 9774 }, /* Cyrillic_O_bar */ { 0x010004e9, 9789 }, /* Cyrillic_o_bar */ { 0x010004ee, 10082 }, /* Cyrillic_U_macron */ { 0x010004ef, 10100 }, /* Cyrillic_u_macron */ { 0x01000531, 2124 }, /* Armenian_AYB */ { 0x01000532, 2150 }, /* Armenian_BEN */ { 0x01000533, 2374 }, /* Armenian_GIM */ { 0x01000534, 2215 }, /* Armenian_DA */ { 0x01000535, 3164 }, /* Armenian_YECH */ { 0x01000536, 3210 }, /* Armenian_ZA */ { 0x01000537, 2265 }, /* Armenian_E */ { 0x01000538, 2100 }, /* Armenian_AT */ { 0x01000539, 2964 }, /* Armenian_TO */ { 0x0100053a, 3234 }, /* Armenian_ZHE */ { 0x0100053b, 2464 }, /* Armenian_INI */ { 0x0100053c, 2611 }, /* Armenian_LYUN */ { 0x0100053d, 2564 }, /* Armenian_KHE */ { 0x0100053e, 2988 }, /* Armenian_TSA */ { 0x0100053f, 2538 }, /* Armenian_KEN */ { 0x01000540, 2424 }, /* Armenian_HO */ { 0x01000541, 2239 }, /* Armenian_DZA */ { 0x01000542, 2346 }, /* Armenian_GHAT */ { 0x01000543, 2936 }, /* Armenian_TCHE */ { 0x01000544, 2639 }, /* Armenian_MEN */ { 0x01000545, 2400 }, /* Armenian_HI */ { 0x01000546, 2665 }, /* Armenian_NU */ { 0x01000547, 2894 }, /* Armenian_SHA */ { 0x01000548, 3112 }, /* Armenian_VO */ { 0x01000549, 2189 }, /* Armenian_CHA */ { 0x0100054a, 2727 }, /* Armenian_PE */ { 0x0100054b, 2490 }, /* Armenian_JE */ { 0x0100054c, 2797 }, /* Armenian_RA */ { 0x0100054d, 2845 }, /* Armenian_SE */ { 0x0100054e, 3086 }, /* Armenian_VEV */ { 0x0100054f, 3040 }, /* Armenian_TYUN */ { 0x01000550, 2821 }, /* Armenian_RE */ { 0x01000551, 3014 }, /* Armenian_TSO */ { 0x01000552, 3136 }, /* Armenian_VYUN */ { 0x01000553, 2751 }, /* Armenian_PYUR */ { 0x01000554, 2514 }, /* Armenian_KE */ { 0x01000555, 2689 }, /* Armenian_O */ { 0x01000556, 2303 }, /* Armenian_FE */ { 0x0100055a, 2080 }, /* Armenian_apostrophe */ { 0x0100055b, 2048 }, /* Armenian_accent */ { 0x0100055c, 2287 }, /* Armenian_exclam */ { 0x0100055d, 2869 }, /* Armenian_separation_mark */ { 0x0100055e, 2779 }, /* Armenian_question */ { 0x01000561, 2137 }, /* Armenian_ayb */ { 0x01000562, 2163 }, /* Armenian_ben */ { 0x01000563, 2387 }, /* Armenian_gim */ { 0x01000564, 2227 }, /* Armenian_da */ { 0x01000565, 3178 }, /* Armenian_yech */ { 0x01000566, 3222 }, /* Armenian_za */ { 0x01000567, 2276 }, /* Armenian_e */ { 0x01000568, 2112 }, /* Armenian_at */ { 0x01000569, 2976 }, /* Armenian_to */ { 0x0100056a, 3247 }, /* Armenian_zhe */ { 0x0100056b, 2477 }, /* Armenian_ini */ { 0x0100056c, 2625 }, /* Armenian_lyun */ { 0x0100056d, 2577 }, /* Armenian_khe */ { 0x0100056e, 3001 }, /* Armenian_tsa */ { 0x0100056f, 2551 }, /* Armenian_ken */ { 0x01000570, 2436 }, /* Armenian_ho */ { 0x01000571, 2252 }, /* Armenian_dza */ { 0x01000572, 2360 }, /* Armenian_ghat */ { 0x01000573, 2950 }, /* Armenian_tche */ { 0x01000574, 2652 }, /* Armenian_men */ { 0x01000575, 2412 }, /* Armenian_hi */ { 0x01000576, 2677 }, /* Armenian_nu */ { 0x01000577, 2907 }, /* Armenian_sha */ { 0x01000578, 3124 }, /* Armenian_vo */ { 0x01000579, 2202 }, /* Armenian_cha */ { 0x0100057a, 2739 }, /* Armenian_pe */ { 0x0100057b, 2502 }, /* Armenian_je */ { 0x0100057c, 2809 }, /* Armenian_ra */ { 0x0100057d, 2857 }, /* Armenian_se */ { 0x0100057e, 3099 }, /* Armenian_vev */ { 0x0100057f, 3054 }, /* Armenian_tyun */ { 0x01000580, 2833 }, /* Armenian_re */ { 0x01000581, 3027 }, /* Armenian_tso */ { 0x01000582, 3150 }, /* Armenian_vyun */ { 0x01000583, 2765 }, /* Armenian_pyur */ { 0x01000584, 2526 }, /* Armenian_ke */ { 0x01000585, 2700 }, /* Armenian_o */ { 0x01000586, 2315 }, /* Armenian_fe */ { 0x01000587, 2590 }, /* Armenian_ligature_ew */ { 0x01000589, 2327 }, /* Armenian_full_stop */ { 0x0100058a, 2448 }, /* Armenian_hyphen */ { 0x01000653, 1580 }, /* Arabic_madda_above */ { 0x01000654, 1316 }, /* Arabic_hamza_above */ { 0x01000655, 1335 }, /* Arabic_hamza_below */ { 0x01000660, 966 }, /* Arabic_0 */ { 0x01000661, 975 }, /* Arabic_1 */ { 0x01000662, 984 }, /* Arabic_2 */ { 0x01000663, 993 }, /* Arabic_3 */ { 0x01000664, 1002 }, /* Arabic_4 */ { 0x01000665, 1011 }, /* Arabic_5 */ { 0x01000666, 1020 }, /* Arabic_6 */ { 0x01000667, 1029 }, /* Arabic_7 */ { 0x01000668, 1038 }, /* Arabic_8 */ { 0x01000669, 1047 }, /* Arabic_9 */ { 0x0100066a, 1672 }, /* Arabic_percent */ { 0x01000670, 1821 }, /* Arabic_superscript_alef */ { 0x01000679, 1951 }, /* Arabic_tteh */ { 0x0100067e, 1661 }, /* Arabic_peh */ { 0x01000686, 1885 }, /* Arabic_tcheh */ { 0x01000688, 1173 }, /* Arabic_ddal */ { 0x01000691, 1729 }, /* Arabic_rreh */ { 0x01000698, 1493 }, /* Arabic_jeh */ { 0x010006a4, 1963 }, /* Arabic_veh */ { 0x010006a9, 1544 }, /* Arabic_keheh */ { 0x010006af, 1258 }, /* Arabic_gaf */ { 0x010006ba, 1642 }, /* Arabic_noon_ghunna */ { 0x010006be, 1442 }, /* Arabic_heh_doachashmee */ { 0x010006c1, 1465 }, /* Arabic_heh_goal */ { 0x010006cc, 12505 }, /* Farsi_yeh */ { 0x010006d2, 1996 }, /* Arabic_yeh_baree */ { 0x010006d4, 1242 }, /* Arabic_fullstop */ { 0x010006f0, 12425 }, /* Farsi_0 */ { 0x010006f1, 12433 }, /* Farsi_1 */ { 0x010006f2, 12441 }, /* Farsi_2 */ { 0x010006f3, 12449 }, /* Farsi_3 */ { 0x010006f4, 12457 }, /* Farsi_4 */ { 0x010006f5, 12465 }, /* Farsi_5 */ { 0x010006f6, 12473 }, /* Farsi_6 */ { 0x010006f7, 12481 }, /* Farsi_7 */ { 0x010006f8, 12489 }, /* Farsi_8 */ { 0x010006f9, 12497 }, /* Farsi_9 */ { 0x01000d82, 23641 }, /* Sinh_ng */ { 0x01000d83, 23435 }, /* Sinh_h2 */ { 0x01000d85, 23204 }, /* Sinh_a */ { 0x01000d86, 23211 }, /* Sinh_aa */ { 0x01000d87, 23228 }, /* Sinh_ae */ { 0x01000d88, 23245 }, /* Sinh_aee */ { 0x01000d89, 23451 }, /* Sinh_i */ { 0x01000d8a, 23466 }, /* Sinh_ii */ { 0x01000d8b, 23852 }, /* Sinh_u */ { 0x01000d8c, 23867 }, /* Sinh_uu */ { 0x01000d8d, 23751 }, /* Sinh_ri */ { 0x01000d8e, 23759 }, /* Sinh_rii */ { 0x01000d8f, 23560 }, /* Sinh_lu */ { 0x01000d90, 23577 }, /* Sinh_luu */ { 0x01000d91, 23378 }, /* Sinh_e */ { 0x01000d92, 23393 }, /* Sinh_ee */ { 0x01000d93, 23264 }, /* Sinh_ai */ { 0x01000d94, 23694 }, /* Sinh_o */ { 0x01000d95, 23709 }, /* Sinh_oo */ { 0x01000d96, 23289 }, /* Sinh_au */ { 0x01000d9a, 23510 }, /* Sinh_ka */ { 0x01000d9b, 23518 }, /* Sinh_kha */ { 0x01000d9c, 23418 }, /* Sinh_ga */ { 0x01000d9d, 23426 }, /* Sinh_gha */ { 0x01000d9e, 23649 }, /* Sinh_ng2 */ { 0x01000d9f, 23658 }, /* Sinh_nga */ { 0x01000da0, 23323 }, /* Sinh_ca */ { 0x01000da1, 23331 }, /* Sinh_cha */ { 0x01000da2, 23483 }, /* Sinh_ja */ { 0x01000da3, 23491 }, /* Sinh_jha */ { 0x01000da4, 23685 }, /* Sinh_nya */ { 0x01000da5, 23500 }, /* Sinh_jnya */ { 0x01000da6, 23667 }, /* Sinh_nja */ { 0x01000da7, 23833 }, /* Sinh_tta */ { 0x01000da8, 23842 }, /* Sinh_ttha */ { 0x01000da9, 23340 }, /* Sinh_dda */ { 0x01000daa, 23349 }, /* Sinh_ddha */ { 0x01000dab, 23676 }, /* Sinh_nna */ { 0x01000dac, 23621 }, /* Sinh_ndda */ { 0x01000dad, 23814 }, /* Sinh_tha */ { 0x01000dae, 23823 }, /* Sinh_thha */ { 0x01000daf, 23359 }, /* Sinh_dha */ { 0x01000db0, 23368 }, /* Sinh_dhha */ { 0x01000db1, 23613 }, /* Sinh_na */ { 0x01000db3, 23631 }, /* Sinh_ndha */ { 0x01000db4, 23726 }, /* Sinh_pa */ { 0x01000db5, 23734 }, /* Sinh_pha */ { 0x01000db6, 23306 }, /* Sinh_ba */ { 0x01000db7, 23314 }, /* Sinh_bha */ { 0x01000db8, 23596 }, /* Sinh_ma */ { 0x01000db9, 23604 }, /* Sinh_mba */ { 0x01000dba, 23892 }, /* Sinh_ya */ { 0x01000dbb, 23743 }, /* Sinh_ra */ { 0x01000dbd, 23543 }, /* Sinh_la */ { 0x01000dc0, 23884 }, /* Sinh_va */ { 0x01000dc1, 23795 }, /* Sinh_sha */ { 0x01000dc2, 23804 }, /* Sinh_ssha */ { 0x01000dc3, 23787 }, /* Sinh_sa */ { 0x01000dc4, 23443 }, /* Sinh_ha */ { 0x01000dc5, 23551 }, /* Sinh_lla */ { 0x01000dc6, 23410 }, /* Sinh_fa */ { 0x01000dca, 23281 }, /* Sinh_al */ { 0x01000dcf, 23219 }, /* Sinh_aa2 */ { 0x01000dd0, 23236 }, /* Sinh_ae2 */ { 0x01000dd1, 23254 }, /* Sinh_aee2 */ { 0x01000dd2, 23458 }, /* Sinh_i2 */ { 0x01000dd3, 23474 }, /* Sinh_ii2 */ { 0x01000dd4, 23859 }, /* Sinh_u2 */ { 0x01000dd6, 23875 }, /* Sinh_uu2 */ { 0x01000dd8, 23768 }, /* Sinh_ru2 */ { 0x01000dd9, 23385 }, /* Sinh_e2 */ { 0x01000dda, 23401 }, /* Sinh_ee2 */ { 0x01000ddb, 23272 }, /* Sinh_ai2 */ { 0x01000ddc, 23701 }, /* Sinh_o2 */ { 0x01000ddd, 23717 }, /* Sinh_oo2 */ { 0x01000dde, 23297 }, /* Sinh_au2 */ { 0x01000ddf, 23568 }, /* Sinh_lu2 */ { 0x01000df2, 23777 }, /* Sinh_ruu2 */ { 0x01000df3, 23586 }, /* Sinh_luu2 */ { 0x01000df4, 23527 }, /* Sinh_kunddaliya */ { 0x010010d0, 12874 }, /* Georgian_an */ { 0x010010d1, 12886 }, /* Georgian_ban */ { 0x010010d2, 12990 }, /* Georgian_gan */ { 0x010010d3, 12953 }, /* Georgian_don */ { 0x010010d4, 12966 }, /* Georgian_en */ { 0x010010d5, 13316 }, /* Georgian_vin */ { 0x010010d6, 13354 }, /* Georgian_zen */ { 0x010010d7, 13278 }, /* Georgian_tan */ { 0x010010d8, 13081 }, /* Georgian_in */ { 0x010010d9, 13120 }, /* Georgian_kan */ { 0x010010da, 13147 }, /* Georgian_las */ { 0x010010db, 13160 }, /* Georgian_man */ { 0x010010dc, 13173 }, /* Georgian_nar */ { 0x010010dd, 13186 }, /* Georgian_on */ { 0x010010de, 13198 }, /* Georgian_par */ { 0x010010df, 13367 }, /* Georgian_zhar */ { 0x010010e0, 13238 }, /* Georgian_rae */ { 0x010010e1, 13251 }, /* Georgian_san */ { 0x010010e2, 13291 }, /* Georgian_tar */ { 0x010010e3, 13304 }, /* Georgian_un */ { 0x010010e4, 13211 }, /* Georgian_phar */ { 0x010010e5, 13133 }, /* Georgian_khar */ { 0x010010e6, 13003 }, /* Georgian_ghan */ { 0x010010e7, 13225 }, /* Georgian_qar */ { 0x010010e8, 13264 }, /* Georgian_shin */ { 0x010010e9, 12926 }, /* Georgian_chin */ { 0x010010ea, 12899 }, /* Georgian_can */ { 0x010010eb, 13107 }, /* Georgian_jil */ { 0x010010ec, 12940 }, /* Georgian_cil */ { 0x010010ed, 12912 }, /* Georgian_char */ { 0x010010ee, 13341 }, /* Georgian_xan */ { 0x010010ef, 13093 }, /* Georgian_jhan */ { 0x010010f0, 13017 }, /* Georgian_hae */ { 0x010010f1, 13043 }, /* Georgian_he */ { 0x010010f2, 13055 }, /* Georgian_hie */ { 0x010010f3, 13329 }, /* Georgian_we */ { 0x010010f4, 13030 }, /* Georgian_har */ { 0x010010f5, 13068 }, /* Georgian_hoe */ { 0x010010f6, 12978 }, /* Georgian_fi */ { 0x01001e02, 3332 }, /* Babovedot */ { 0x01001e03, 3342 }, /* babovedot */ { 0x01001e0a, 10406 }, /* Dabovedot */ { 0x01001e0b, 10416 }, /* dabovedot */ { 0x01001e1e, 12405 }, /* Fabovedot */ { 0x01001e1f, 12415 }, /* fabovedot */ { 0x01001e36, 19336 }, /* Lbelowdot */ { 0x01001e37, 19346 }, /* lbelowdot */ { 0x01001e40, 19681 }, /* Mabovedot */ { 0x01001e41, 19691 }, /* mabovedot */ { 0x01001e56, 21534 }, /* Pabovedot */ { 0x01001e57, 21544 }, /* pabovedot */ { 0x01001e60, 22740 }, /* Sabovedot */ { 0x01001e61, 22750 }, /* sabovedot */ { 0x01001e6a, 24459 }, /* Tabovedot */ { 0x01001e6b, 24469 }, /* tabovedot */ { 0x01001e80, 26766 }, /* Wgrave */ { 0x01001e81, 26773 }, /* wgrave */ { 0x01001e82, 26706 }, /* Wacute */ { 0x01001e83, 26713 }, /* wacute */ { 0x01001e84, 26744 }, /* Wdiaeresis */ { 0x01001e85, 26755 }, /* wdiaeresis */ { 0x01001e8a, 26792 }, /* Xabovedot */ { 0x01001e8b, 26802 }, /* xabovedot */ { 0x01001ea0, 416 }, /* Abelowdot */ { 0x01001ea1, 426 }, /* abelowdot */ { 0x01001ea2, 868 }, /* Ahook */ { 0x01001ea3, 874 }, /* ahook */ { 0x01001ea4, 646 }, /* Acircumflexacute */ { 0x01001ea5, 663 }, /* acircumflexacute */ { 0x01001ea6, 720 }, /* Acircumflexgrave */ { 0x01001ea7, 737 }, /* acircumflexgrave */ { 0x01001ea8, 754 }, /* Acircumflexhook */ { 0x01001ea9, 770 }, /* acircumflexhook */ { 0x01001eaa, 786 }, /* Acircumflextilde */ { 0x01001eab, 803 }, /* acircumflextilde */ { 0x01001eac, 680 }, /* Acircumflexbelowdot */ { 0x01001ead, 700 }, /* acircumflexbelowdot */ { 0x01001eae, 459 }, /* Abreveacute */ { 0x01001eaf, 471 }, /* abreveacute */ { 0x01001eb0, 513 }, /* Abrevegrave */ { 0x01001eb1, 525 }, /* abrevegrave */ { 0x01001eb2, 537 }, /* Abrevehook */ { 0x01001eb3, 548 }, /* abrevehook */ { 0x01001eb4, 559 }, /* Abrevetilde */ { 0x01001eb5, 571 }, /* abrevetilde */ { 0x01001eb6, 483 }, /* Abrevebelowdot */ { 0x01001eb7, 498 }, /* abrevebelowdot */ { 0x01001eb8, 11577 }, /* Ebelowdot */ { 0x01001eb9, 11587 }, /* ebelowdot */ { 0x01001eba, 11853 }, /* Ehook */ { 0x01001ebb, 11859 }, /* ehook */ { 0x01001ebc, 12191 }, /* Etilde */ { 0x01001ebd, 12198 }, /* etilde */ { 0x01001ebe, 11635 }, /* Ecircumflexacute */ { 0x01001ebf, 11652 }, /* ecircumflexacute */ { 0x01001ec0, 11709 }, /* Ecircumflexgrave */ { 0x01001ec1, 11726 }, /* ecircumflexgrave */ { 0x01001ec2, 11743 }, /* Ecircumflexhook */ { 0x01001ec3, 11759 }, /* ecircumflexhook */ { 0x01001ec4, 11775 }, /* Ecircumflextilde */ { 0x01001ec5, 11792 }, /* ecircumflextilde */ { 0x01001ec6, 11669 }, /* Ecircumflexbelowdot */ { 0x01001ec7, 11689 }, /* ecircumflexbelowdot */ { 0x01001ec8, 17363 }, /* Ihook */ { 0x01001ec9, 17369 }, /* ihook */ { 0x01001eca, 17241 }, /* Ibelowdot */ { 0x01001ecb, 17251 }, /* ibelowdot */ { 0x01001ecc, 20378 }, /* Obelowdot */ { 0x01001ecd, 20388 }, /* obelowdot */ { 0x01001ece, 20685 }, /* Ohook */ { 0x01001ecf, 20691 }, /* ohook */ { 0x01001ed0, 20436 }, /* Ocircumflexacute */ { 0x01001ed1, 20453 }, /* ocircumflexacute */ { 0x01001ed2, 20510 }, /* Ocircumflexgrave */ { 0x01001ed3, 20527 }, /* ocircumflexgrave */ { 0x01001ed4, 20544 }, /* Ocircumflexhook */ { 0x01001ed5, 20560 }, /* ocircumflexhook */ { 0x01001ed6, 20576 }, /* Ocircumflextilde */ { 0x01001ed7, 20593 }, /* ocircumflextilde */ { 0x01001ed8, 20470 }, /* Ocircumflexbelowdot */ { 0x01001ed9, 20490 }, /* ocircumflexbelowdot */ { 0x01001eda, 20709 }, /* Ohornacute */ { 0x01001edb, 20720 }, /* ohornacute */ { 0x01001edc, 20759 }, /* Ohorngrave */ { 0x01001edd, 20770 }, /* ohorngrave */ { 0x01001ede, 20781 }, /* Ohornhook */ { 0x01001edf, 20791 }, /* ohornhook */ { 0x01001ee0, 20801 }, /* Ohorntilde */ { 0x01001ee1, 20812 }, /* ohorntilde */ { 0x01001ee2, 20731 }, /* Ohornbelowdot */ { 0x01001ee3, 20745 }, /* ohornbelowdot */ { 0x01001ee4, 26022 }, /* Ubelowdot */ { 0x01001ee5, 26032 }, /* ubelowdot */ { 0x01001ee6, 26142 }, /* Uhook */ { 0x01001ee7, 26148 }, /* uhook */ { 0x01001ee8, 26166 }, /* Uhornacute */ { 0x01001ee9, 26177 }, /* uhornacute */ { 0x01001eea, 26216 }, /* Uhorngrave */ { 0x01001eeb, 26227 }, /* uhorngrave */ { 0x01001eec, 26238 }, /* Uhornhook */ { 0x01001eed, 26248 }, /* uhornhook */ { 0x01001eee, 26258 }, /* Uhorntilde */ { 0x01001eef, 26269 }, /* uhorntilde */ { 0x01001ef0, 26188 }, /* Uhornbelowdot */ { 0x01001ef1, 26202 }, /* uhornbelowdot */ { 0x01001ef2, 32467 }, /* Ygrave */ { 0x01001ef3, 32474 }, /* ygrave */ { 0x01001ef4, 32397 }, /* Ybelowdot */ { 0x01001ef5, 32407 }, /* ybelowdot */ { 0x01001ef6, 32481 }, /* Yhook */ { 0x01001ef7, 32487 }, /* yhook */ { 0x01001ef8, 32493 }, /* Ytilde */ { 0x01001ef9, 32500 }, /* ytilde */ { 0x01002070, 32606 }, /* zerosuperior */ { 0x01002074, 12747 }, /* foursuperior */ { 0x01002075, 12709 }, /* fivesuperior */ { 0x01002076, 23913 }, /* sixsuperior */ { 0x01002077, 23089 }, /* sevensuperior */ { 0x01002078, 11880 }, /* eightsuperior */ { 0x01002079, 20206 }, /* ninesuperior */ { 0x01002080, 32592 }, /* zerosubscript */ { 0x01002081, 20886 }, /* onesubscript */ { 0x01002082, 25969 }, /* twosubscript */ { 0x01002083, 25713 }, /* threesubscript */ { 0x01002084, 12733 }, /* foursubscript */ { 0x01002085, 12695 }, /* fivesubscript */ { 0x01002086, 23900 }, /* sixsubscript */ { 0x01002087, 23074 }, /* sevensubscript */ { 0x01002088, 11865 }, /* eightsubscript */ { 0x01002089, 20192 }, /* ninesubscript */ { 0x010020a0, 11809 }, /* EcuSign */ { 0x010020a1, 8670 }, /* ColonSign */ { 0x010020a2, 8826 }, /* CruzeiroSign */ { 0x010020a3, 12531 }, /* FFrancSign */ { 0x010020a4, 19592 }, /* LiraSign */ { 0x010020a5, 19868 }, /* MillSign */ { 0x010020a6, 20111 }, /* NairaSign */ { 0x010020a7, 21683 }, /* PesetaSign */ { 0x010020a8, 22726 }, /* RupeeSign */ { 0x010020a9, 26780 }, /* WonSign */ { 0x010020aa, 20153 }, /* NewSheqelSign */ { 0x010020ab, 11373 }, /* DongSign */ { 0x01002202, 21603 }, /* partdifferential */ { 0x01002205, 12034 }, /* emptyset */ { 0x01002208, 11917 }, /* elementof */ { 0x01002209, 20256 }, /* notelementof */ { 0x0100220b, 8768 }, /* containsas */ { 0x0100221a, 23966 }, /* squareroot */ { 0x0100221b, 8839 }, /* cuberoot */ { 0x0100221c, 12760 }, /* fourthroot */ { 0x0100222c, 11347 }, /* dintegral */ { 0x0100222d, 25742 }, /* tintegral */ { 0x01002235, 3396 }, /* because */ { 0x01002247, 20244 }, /* notapproxeq */ { 0x01002248, 945 }, /* approxeq */ { 0x01002262, 20278 }, /* notidentical */ { 0x01002263, 24011 }, /* stricteq */ { 0x01002800, 3628 }, /* braille_blank */ { 0x01002801, 3783 }, /* braille_dots_1 */ { 0x01002802, 6151 }, /* braille_dots_2 */ { 0x01002803, 3798 }, /* braille_dots_12 */ { 0x01002804, 7303 }, /* braille_dots_3 */ { 0x01002805, 5014 }, /* braille_dots_13 */ { 0x01002806, 6166 }, /* braille_dots_23 */ { 0x01002807, 3814 }, /* braille_dots_123 */ { 0x01002808, 7863 }, /* braille_dots_4 */ { 0x01002809, 5606 }, /* braille_dots_14 */ { 0x0100280a, 6758 }, /* braille_dots_24 */ { 0x0100280b, 4438 }, /* braille_dots_124 */ { 0x0100280c, 7318 }, /* braille_dots_34 */ { 0x0100280d, 5030 }, /* braille_dots_134 */ { 0x0100280e, 6182 }, /* braille_dots_234 */ { 0x0100280f, 3831 }, /* braille_dots_1234 */ { 0x01002810, 8135 }, /* braille_dots_5 */ { 0x01002811, 5894 }, /* braille_dots_15 */ { 0x01002812, 7046 }, /* braille_dots_25 */ { 0x01002813, 4742 }, /* braille_dots_125 */ { 0x01002814, 7606 }, /* braille_dots_35 */ { 0x01002815, 5334 }, /* braille_dots_135 */ { 0x01002816, 6486 }, /* braille_dots_235 */ { 0x01002817, 4151 }, /* braille_dots_1235 */ { 0x01002818, 7878 }, /* braille_dots_45 */ { 0x01002819, 5622 }, /* braille_dots_145 */ { 0x0100281a, 6774 }, /* braille_dots_245 */ { 0x0100281b, 4455 }, /* braille_dots_1245 */ { 0x0100281c, 7334 }, /* braille_dots_345 */ { 0x0100281d, 5047 }, /* braille_dots_1345 */ { 0x0100281e, 6199 }, /* braille_dots_2345 */ { 0x0100281f, 3849 }, /* braille_dots_12345 */ { 0x01002820, 8267 }, /* braille_dots_6 */ { 0x01002821, 6034 }, /* braille_dots_16 */ { 0x01002822, 7186 }, /* braille_dots_26 */ { 0x01002823, 4890 }, /* braille_dots_126 */ { 0x01002824, 7746 }, /* braille_dots_36 */ { 0x01002825, 5482 }, /* braille_dots_136 */ { 0x01002826, 6634 }, /* braille_dots_236 */ { 0x01002827, 4307 }, /* braille_dots_1236 */ { 0x01002828, 8018 }, /* braille_dots_46 */ { 0x01002829, 5770 }, /* braille_dots_146 */ { 0x0100282a, 6922 }, /* braille_dots_246 */ { 0x0100282b, 4611 }, /* braille_dots_1246 */ { 0x0100282c, 7482 }, /* braille_dots_346 */ { 0x0100282d, 5203 }, /* braille_dots_1346 */ { 0x0100282e, 6355 }, /* braille_dots_2346 */ { 0x0100282f, 4013 }, /* braille_dots_12346 */ { 0x01002830, 8150 }, /* braille_dots_56 */ { 0x01002831, 5910 }, /* braille_dots_156 */ { 0x01002832, 7062 }, /* braille_dots_256 */ { 0x01002833, 4759 }, /* braille_dots_1256 */ { 0x01002834, 7622 }, /* braille_dots_356 */ { 0x01002835, 5351 }, /* braille_dots_1356 */ { 0x01002836, 6503 }, /* braille_dots_2356 */ { 0x01002837, 4169 }, /* braille_dots_12356 */ { 0x01002838, 7894 }, /* braille_dots_456 */ { 0x01002839, 5639 }, /* braille_dots_1456 */ { 0x0100283a, 6791 }, /* braille_dots_2456 */ { 0x0100283b, 4473 }, /* braille_dots_12456 */ { 0x0100283c, 7351 }, /* braille_dots_3456 */ { 0x0100283d, 5065 }, /* braille_dots_13456 */ { 0x0100283e, 6217 }, /* braille_dots_23456 */ { 0x0100283f, 3868 }, /* braille_dots_123456 */ { 0x01002840, 8331 }, /* braille_dots_7 */ { 0x01002841, 6102 }, /* braille_dots_17 */ { 0x01002842, 7254 }, /* braille_dots_27 */ { 0x01002843, 4962 }, /* braille_dots_127 */ { 0x01002844, 7814 }, /* braille_dots_37 */ { 0x01002845, 5554 }, /* braille_dots_137 */ { 0x01002846, 6706 }, /* braille_dots_237 */ { 0x01002847, 4383 }, /* braille_dots_1237 */ { 0x01002848, 8086 }, /* braille_dots_47 */ { 0x01002849, 5842 }, /* braille_dots_147 */ { 0x0100284a, 6994 }, /* braille_dots_247 */ { 0x0100284b, 4687 }, /* braille_dots_1247 */ { 0x0100284c, 7554 }, /* braille_dots_347 */ { 0x0100284d, 5279 }, /* braille_dots_1347 */ { 0x0100284e, 6431 }, /* braille_dots_2347 */ { 0x0100284f, 4093 }, /* braille_dots_12347 */ { 0x01002850, 8218 }, /* braille_dots_57 */ { 0x01002851, 5982 }, /* braille_dots_157 */ { 0x01002852, 7134 }, /* braille_dots_257 */ { 0x01002853, 4835 }, /* braille_dots_1257 */ { 0x01002854, 7694 }, /* braille_dots_357 */ { 0x01002855, 5427 }, /* braille_dots_1357 */ { 0x01002856, 6579 }, /* braille_dots_2357 */ { 0x01002857, 4249 }, /* braille_dots_12357 */ { 0x01002858, 7966 }, /* braille_dots_457 */ { 0x01002859, 5715 }, /* braille_dots_1457 */ { 0x0100285a, 6867 }, /* braille_dots_2457 */ { 0x0100285b, 4553 }, /* braille_dots_12457 */ { 0x0100285c, 7427 }, /* braille_dots_3457 */ { 0x0100285d, 5145 }, /* braille_dots_13457 */ { 0x0100285e, 6297 }, /* braille_dots_23457 */ { 0x0100285f, 3952 }, /* braille_dots_123457 */ { 0x01002860, 8282 }, /* braille_dots_67 */ { 0x01002861, 6050 }, /* braille_dots_167 */ { 0x01002862, 7202 }, /* braille_dots_267 */ { 0x01002863, 4907 }, /* braille_dots_1267 */ { 0x01002864, 7762 }, /* braille_dots_367 */ { 0x01002865, 5499 }, /* braille_dots_1367 */ { 0x01002866, 6651 }, /* braille_dots_2367 */ { 0x01002867, 4325 }, /* braille_dots_12367 */ { 0x01002868, 8034 }, /* braille_dots_467 */ { 0x01002869, 5787 }, /* braille_dots_1467 */ { 0x0100286a, 6939 }, /* braille_dots_2467 */ { 0x0100286b, 4629 }, /* braille_dots_12467 */ { 0x0100286c, 7499 }, /* braille_dots_3467 */ { 0x0100286d, 5221 }, /* braille_dots_13467 */ { 0x0100286e, 6373 }, /* braille_dots_23467 */ { 0x0100286f, 4032 }, /* braille_dots_123467 */ { 0x01002870, 8166 }, /* braille_dots_567 */ { 0x01002871, 5927 }, /* braille_dots_1567 */ { 0x01002872, 7079 }, /* braille_dots_2567 */ { 0x01002873, 4777 }, /* braille_dots_12567 */ { 0x01002874, 7639 }, /* braille_dots_3567 */ { 0x01002875, 5369 }, /* braille_dots_13567 */ { 0x01002876, 6521 }, /* braille_dots_23567 */ { 0x01002877, 4188 }, /* braille_dots_123567 */ { 0x01002878, 7911 }, /* braille_dots_4567 */ { 0x01002879, 5657 }, /* braille_dots_14567 */ { 0x0100287a, 6809 }, /* braille_dots_24567 */ { 0x0100287b, 4492 }, /* braille_dots_124567 */ { 0x0100287c, 7369 }, /* braille_dots_34567 */ { 0x0100287d, 5084 }, /* braille_dots_134567 */ { 0x0100287e, 6236 }, /* braille_dots_234567 */ { 0x0100287f, 3888 }, /* braille_dots_1234567 */ { 0x01002880, 8362 }, /* braille_dots_8 */ { 0x01002881, 6135 }, /* braille_dots_18 */ { 0x01002882, 7287 }, /* braille_dots_28 */ { 0x01002883, 4997 }, /* braille_dots_128 */ { 0x01002884, 7847 }, /* braille_dots_38 */ { 0x01002885, 5589 }, /* braille_dots_138 */ { 0x01002886, 6741 }, /* braille_dots_238 */ { 0x01002887, 4420 }, /* braille_dots_1238 */ { 0x01002888, 8119 }, /* braille_dots_48 */ { 0x01002889, 5877 }, /* braille_dots_148 */ { 0x0100288a, 7029 }, /* braille_dots_248 */ { 0x0100288b, 4724 }, /* braille_dots_1248 */ { 0x0100288c, 7589 }, /* braille_dots_348 */ { 0x0100288d, 5316 }, /* braille_dots_1348 */ { 0x0100288e, 6468 }, /* braille_dots_2348 */ { 0x0100288f, 4132 }, /* braille_dots_12348 */ { 0x01002890, 8251 }, /* braille_dots_58 */ { 0x01002891, 6017 }, /* braille_dots_158 */ { 0x01002892, 7169 }, /* braille_dots_258 */ { 0x01002893, 4872 }, /* braille_dots_1258 */ { 0x01002894, 7729 }, /* braille_dots_358 */ { 0x01002895, 5464 }, /* braille_dots_1358 */ { 0x01002896, 6616 }, /* braille_dots_2358 */ { 0x01002897, 4288 }, /* braille_dots_12358 */ { 0x01002898, 8001 }, /* braille_dots_458 */ { 0x01002899, 5752 }, /* braille_dots_1458 */ { 0x0100289a, 6904 }, /* braille_dots_2458 */ { 0x0100289b, 4592 }, /* braille_dots_12458 */ { 0x0100289c, 7464 }, /* braille_dots_3458 */ { 0x0100289d, 5184 }, /* braille_dots_13458 */ { 0x0100289e, 6336 }, /* braille_dots_23458 */ { 0x0100289f, 3993 }, /* braille_dots_123458 */ { 0x010028a0, 8315 }, /* braille_dots_68 */ { 0x010028a1, 6085 }, /* braille_dots_168 */ { 0x010028a2, 7237 }, /* braille_dots_268 */ { 0x010028a3, 4944 }, /* braille_dots_1268 */ { 0x010028a4, 7797 }, /* braille_dots_368 */ { 0x010028a5, 5536 }, /* braille_dots_1368 */ { 0x010028a6, 6688 }, /* braille_dots_2368 */ { 0x010028a7, 4364 }, /* braille_dots_12368 */ { 0x010028a8, 8069 }, /* braille_dots_468 */ { 0x010028a9, 5824 }, /* braille_dots_1468 */ { 0x010028aa, 6976 }, /* braille_dots_2468 */ { 0x010028ab, 4668 }, /* braille_dots_12468 */ { 0x010028ac, 7536 }, /* braille_dots_3468 */ { 0x010028ad, 5260 }, /* braille_dots_13468 */ { 0x010028ae, 6412 }, /* braille_dots_23468 */ { 0x010028af, 4073 }, /* braille_dots_123468 */ { 0x010028b0, 8201 }, /* braille_dots_568 */ { 0x010028b1, 5964 }, /* braille_dots_1568 */ { 0x010028b2, 7116 }, /* braille_dots_2568 */ { 0x010028b3, 4816 }, /* braille_dots_12568 */ { 0x010028b4, 7676 }, /* braille_dots_3568 */ { 0x010028b5, 5408 }, /* braille_dots_13568 */ { 0x010028b6, 6560 }, /* braille_dots_23568 */ { 0x010028b7, 4229 }, /* braille_dots_123568 */ { 0x010028b8, 7948 }, /* braille_dots_4568 */ { 0x010028b9, 5696 }, /* braille_dots_14568 */ { 0x010028ba, 6848 }, /* braille_dots_24568 */ { 0x010028bb, 4533 }, /* braille_dots_124568 */ { 0x010028bc, 7408 }, /* braille_dots_34568 */ { 0x010028bd, 5125 }, /* braille_dots_134568 */ { 0x010028be, 6277 }, /* braille_dots_234568 */ { 0x010028bf, 3931 }, /* braille_dots_1234568 */ { 0x010028c0, 8346 }, /* braille_dots_78 */ { 0x010028c1, 6118 }, /* braille_dots_178 */ { 0x010028c2, 7270 }, /* braille_dots_278 */ { 0x010028c3, 4979 }, /* braille_dots_1278 */ { 0x010028c4, 7830 }, /* braille_dots_378 */ { 0x010028c5, 5571 }, /* braille_dots_1378 */ { 0x010028c6, 6723 }, /* braille_dots_2378 */ { 0x010028c7, 4401 }, /* braille_dots_12378 */ { 0x010028c8, 8102 }, /* braille_dots_478 */ { 0x010028c9, 5859 }, /* braille_dots_1478 */ { 0x010028ca, 7011 }, /* braille_dots_2478 */ { 0x010028cb, 4705 }, /* braille_dots_12478 */ { 0x010028cc, 7571 }, /* braille_dots_3478 */ { 0x010028cd, 5297 }, /* braille_dots_13478 */ { 0x010028ce, 6449 }, /* braille_dots_23478 */ { 0x010028cf, 4112 }, /* braille_dots_123478 */ { 0x010028d0, 8234 }, /* braille_dots_578 */ { 0x010028d1, 5999 }, /* braille_dots_1578 */ { 0x010028d2, 7151 }, /* braille_dots_2578 */ { 0x010028d3, 4853 }, /* braille_dots_12578 */ { 0x010028d4, 7711 }, /* braille_dots_3578 */ { 0x010028d5, 5445 }, /* braille_dots_13578 */ { 0x010028d6, 6597 }, /* braille_dots_23578 */ { 0x010028d7, 4268 }, /* braille_dots_123578 */ { 0x010028d8, 7983 }, /* braille_dots_4578 */ { 0x010028d9, 5733 }, /* braille_dots_14578 */ { 0x010028da, 6885 }, /* braille_dots_24578 */ { 0x010028db, 4572 }, /* braille_dots_124578 */ { 0x010028dc, 7445 }, /* braille_dots_34578 */ { 0x010028dd, 5164 }, /* braille_dots_134578 */ { 0x010028de, 6316 }, /* braille_dots_234578 */ { 0x010028df, 3972 }, /* braille_dots_1234578 */ { 0x010028e0, 8298 }, /* braille_dots_678 */ { 0x010028e1, 6067 }, /* braille_dots_1678 */ { 0x010028e2, 7219 }, /* braille_dots_2678 */ { 0x010028e3, 4925 }, /* braille_dots_12678 */ { 0x010028e4, 7779 }, /* braille_dots_3678 */ { 0x010028e5, 5517 }, /* braille_dots_13678 */ { 0x010028e6, 6669 }, /* braille_dots_23678 */ { 0x010028e7, 4344 }, /* braille_dots_123678 */ { 0x010028e8, 8051 }, /* braille_dots_4678 */ { 0x010028e9, 5805 }, /* braille_dots_14678 */ { 0x010028ea, 6957 }, /* braille_dots_24678 */ { 0x010028eb, 4648 }, /* braille_dots_124678 */ { 0x010028ec, 7517 }, /* braille_dots_34678 */ { 0x010028ed, 5240 }, /* braille_dots_134678 */ { 0x010028ee, 6392 }, /* braille_dots_234678 */ { 0x010028ef, 4052 }, /* braille_dots_1234678 */ { 0x010028f0, 8183 }, /* braille_dots_5678 */ { 0x010028f1, 5945 }, /* braille_dots_15678 */ { 0x010028f2, 7097 }, /* braille_dots_25678 */ { 0x010028f3, 4796 }, /* braille_dots_125678 */ { 0x010028f4, 7657 }, /* braille_dots_35678 */ { 0x010028f5, 5388 }, /* braille_dots_135678 */ { 0x010028f6, 6540 }, /* braille_dots_235678 */ { 0x010028f7, 4208 }, /* braille_dots_1235678 */ { 0x010028f8, 7929 }, /* braille_dots_45678 */ { 0x010028f9, 5676 }, /* braille_dots_145678 */ { 0x010028fa, 6828 }, /* braille_dots_245678 */ { 0x010028fb, 4512 }, /* braille_dots_1245678 */ { 0x010028fc, 7388 }, /* braille_dots_345678 */ { 0x010028fd, 5104 }, /* braille_dots_1345678 */ { 0x010028fe, 6256 }, /* braille_dots_2345678 */ { 0x010028ff, 3909 }, /* braille_dots_12345678 */ { 0x100000a8, 17054 }, /* hpmute_acute */ { 0x100000a9, 17121 }, /* hpmute_grave */ { 0x100000aa, 17067 }, /* hpmute_asciicircum */ { 0x100000ab, 17104 }, /* hpmute_diaeresis */ { 0x100000ac, 17086 }, /* hpmute_asciitilde */ { 0x100000af, 17011 }, /* hplira */ { 0x100000be, 16957 }, /* hpguilder */ { 0x100000ee, 17158 }, /* hpYdiaeresis */ { 0x100000f6, 17018 }, /* hplongminus */ { 0x100000fc, 16911 }, /* hpblock */ { 0x1000fe22, 10496 }, /* Ddiaeresis */ { 0x1000fe27, 10426 }, /* Dacute_accent */ { 0x1000fe2c, 10461 }, /* Dcedilla_accent */ { 0x1000fe5e, 10477 }, /* Dcircumflex_accent */ { 0x1000fe60, 11304 }, /* Dgrave_accent */ { 0x1000fe7e, 11532 }, /* Dtilde */ { 0x1000feb0, 11503 }, /* Dring_accent */ { 0x1000ff00, 11495 }, /* DRemove */ { 0x1000ff48, 17030 }, /* hpModelock1 */ { 0x1000ff49, 17042 }, /* hpModelock2 */ { 0x1000ff6c, 17134 }, /* hpReset */ { 0x1000ff6d, 17142 }, /* hpSystem */ { 0x1000ff6e, 17151 }, /* hpUser */ { 0x1000ff6f, 16919 }, /* hpClearLine */ { 0x1000ff70, 16980 }, /* hpInsertLine */ { 0x1000ff71, 16944 }, /* hpDeleteLine */ { 0x1000ff72, 16967 }, /* hpInsertChar */ { 0x1000ff73, 16931 }, /* hpDeleteChar */ { 0x1000ff74, 16901 }, /* hpBackTab */ { 0x1000ff75, 16998 }, /* hpKP_BackTab */ { 0x1000ff76, 12240 }, /* Ext16bit_L */ { 0x1000ff77, 12251 }, /* Ext16bit_R */ { 0x1004ff02, 21113 }, /* osfCopy */ { 0x1004ff03, 21121 }, /* osfCut */ { 0x1004ff04, 21320 }, /* osfPaste */ { 0x1004ff07, 21057 }, /* osfBackTab */ { 0x1004ff08, 21044 }, /* osfBackSpace */ { 0x1004ff0b, 21104 }, /* osfClear */ { 0x1004ff1b, 21183 }, /* osfEscape */ { 0x1004ff31, 21033 }, /* osfAddMode */ { 0x1004ff32, 21354 }, /* osfPrimaryPaste */ { 0x1004ff33, 21370 }, /* osfQuickPaste */ { 0x1004ff40, 21285 }, /* osfPageLeft */ { 0x1004ff41, 21310 }, /* osfPageUp */ { 0x1004ff42, 21273 }, /* osfPageDown */ { 0x1004ff43, 21297 }, /* osfPageRight */ { 0x1004ff44, 21021 }, /* osfActivate */ { 0x1004ff45, 21237 }, /* osfMenuBar */ { 0x1004ff51, 21221 }, /* osfLeft */ { 0x1004ff52, 21447 }, /* osfUp */ { 0x1004ff53, 21407 }, /* osfRight */ { 0x1004ff54, 21153 }, /* osfDown */ { 0x1004ff57, 21172 }, /* osfEndLine */ { 0x1004ff58, 21081 }, /* osfBeginLine */ { 0x1004ff59, 21161 }, /* osfEndData */ { 0x1004ff5a, 21068 }, /* osfBeginData */ { 0x1004ff5b, 21342 }, /* osfPrevMenu */ { 0x1004ff5c, 21261 }, /* osfNextMenu */ { 0x1004ff5d, 21329 }, /* osfPrevField */ { 0x1004ff5e, 21248 }, /* osfNextField */ { 0x1004ff60, 21416 }, /* osfSelect */ { 0x1004ff63, 21211 }, /* osfInsert */ { 0x1004ff65, 21439 }, /* osfUndo */ { 0x1004ff67, 21229 }, /* osfMenu */ { 0x1004ff69, 21094 }, /* osfCancel */ { 0x1004ff6a, 21203 }, /* osfHelp */ { 0x1004ff71, 21426 }, /* osfSelectAll */ { 0x1004ff72, 21138 }, /* osfDeselectAll */ { 0x1004ff73, 21384 }, /* osfReselect */ { 0x1004ff74, 21193 }, /* osfExtend */ { 0x1004ff78, 21396 }, /* osfRestore */ { 0x1004ffff, 21128 }, /* osfDelete */ { 0x1005ff00, 24189 }, /* SunFA_Grave */ { 0x1005ff01, 24160 }, /* SunFA_Circum */ { 0x1005ff02, 24201 }, /* SunFA_Tilde */ { 0x1005ff03, 24134 }, /* SunFA_Acute */ { 0x1005ff04, 24173 }, /* SunFA_Diaeresis */ { 0x1005ff05, 24146 }, /* SunFA_Cedilla */ { 0x1005ff10, 24120 }, /* SunF36 */ { 0x1005ff11, 24127 }, /* SunF37 */ { 0x1005ff60, 24337 }, /* SunSys_Req */ { 0x1005ff70, 24320 }, /* SunProps */ { 0x1005ff71, 24221 }, /* SunFront */ { 0x1005ff72, 24105 }, /* SunCopy */ { 0x1005ff73, 24230 }, /* SunOpen */ { 0x1005ff74, 24260 }, /* SunPaste */ { 0x1005ff75, 24113 }, /* SunCut */ { 0x1005ff76, 24269 }, /* SunPowerSwitch */ { 0x1005ff77, 24041 }, /* SunAudioLowerVolume */ { 0x1005ff78, 24061 }, /* SunAudioMute */ { 0x1005ff79, 24074 }, /* SunAudioRaiseVolume */ { 0x1005ff7a, 24356 }, /* SunVideoDegauss */ { 0x1005ff7b, 24372 }, /* SunVideoLowerBrightness */ { 0x1005ff7c, 24396 }, /* SunVideoRaiseBrightness */ { 0x1005ff7d, 24284 }, /* SunPowerSwitchShift */ { 0x100810dc, 31611 }, /* XF86Sport */ { 0x100810f4, 27521 }, /* XF86BrightnessAuto */ { 0x100810f5, 28048 }, /* XF86DisplayOff */ { 0x10081160, 30851 }, /* XF86OK */ { 0x10081162, 28561 }, /* XF86GoTo */ { 0x10081166, 28678 }, /* XF86Info */ { 0x10081168, 32147 }, /* XF86VendorLogo */ { 0x1008116a, 30031 }, /* XF86MediaSelectProgramGuide */ { 0x1008116e, 29993 }, /* XF86MediaSelectHome */ { 0x10081170, 29838 }, /* XF86MediaLanguageMenu */ { 0x10081171, 30230 }, /* XF86MediaTitleMenu */ { 0x10081175, 27071 }, /* XF86AudioChannelMode */ { 0x10081177, 26978 }, /* XF86AspectRatio */ { 0x10081178, 30013 }, /* XF86MediaSelectPC */ { 0x10081179, 30170 }, /* XF86MediaSelectTV */ { 0x1008117a, 29935 }, /* XF86MediaSelectCable */ { 0x1008117b, 30188 }, /* XF86MediaSelectVCR */ { 0x1008117c, 30207 }, /* XF86MediaSelectVCRPlus */ { 0x1008117d, 30080 }, /* XF86MediaSelectSatellite */ { 0x10081180, 30105 }, /* XF86MediaSelectTape */ { 0x10081181, 30059 }, /* XF86MediaSelectRadio */ { 0x10081182, 30149 }, /* XF86MediaSelectTuner */ { 0x10081183, 29860 }, /* XF86MediaPlayer */ { 0x10081184, 30125 }, /* XF86MediaSelectTeletext */ { 0x10081185, 28139 }, /* XF86DVD */ { 0x10081186, 29910 }, /* XF86MediaSelectAuxiliary */ { 0x10081188, 27061 }, /* XF86Audio */ { 0x10081192, 27839 }, /* XF86ChannelUp */ { 0x10081193, 27823 }, /* XF86ChannelDown */ { 0x10081199, 29876 }, /* XF86MediaPlaySlow */ { 0x1008119b, 27490 }, /* XF86Break */ { 0x1008119d, 30573 }, /* XF86NumberEntryMode */ { 0x100811a0, 32172 }, /* XF86VideoPhone */ { 0x100811a4, 32365 }, /* XF86ZoomReset */ { 0x100811a6, 28147 }, /* XF86Editor */ { 0x100811a8, 28570 }, /* XF86GraphicsEditor */ { 0x100811a9, 31023 }, /* XF86Presentation */ { 0x100811aa, 28011 }, /* XF86Database */ { 0x100811ac, 32221 }, /* XF86Voicemail */ { 0x100811ad, 26893 }, /* XF86Addressbook */ { 0x100811af, 28063 }, /* XF86DisplayToggle */ { 0x100811b0, 31580 }, /* XF86SpellCheck */ { 0x100811b6, 27918 }, /* XF86ContextMenu */ { 0x100811b7, 29894 }, /* XF86MediaRepeat */ { 0x100811b8, 26831 }, /* XF8610ChannelsUp */ { 0x100811b9, 26812 }, /* XF8610ChannelsDown */ { 0x100811ba, 28667 }, /* XF86Images */ { 0x100811bc, 30550 }, /* XF86NotificationCenter */ { 0x100811bd, 30967 }, /* XF86PickupPhone */ { 0x100811be, 28599 }, /* XF86HangupPhone */ { 0x100811bf, 29262 }, /* XF86LinkPhone */ { 0x100811d0, 28266 }, /* XF86Fn */ { 0x100811d1, 28318 }, /* XF86Fn_Esc */ { 0x100811d2, 28338 }, /* XF86Fn_F1 */ { 0x100811d3, 28381 }, /* XF86Fn_F2 */ { 0x100811d4, 28391 }, /* XF86Fn_F3 */ { 0x100811d5, 28401 }, /* XF86Fn_F4 */ { 0x100811d6, 28411 }, /* XF86Fn_F5 */ { 0x100811d7, 28421 }, /* XF86Fn_F6 */ { 0x100811d8, 28431 }, /* XF86Fn_F7 */ { 0x100811d9, 28441 }, /* XF86Fn_F8 */ { 0x100811da, 28451 }, /* XF86Fn_F9 */ { 0x100811db, 28348 }, /* XF86Fn_F10 */ { 0x100811dc, 28359 }, /* XF86Fn_F11 */ { 0x100811dd, 28370 }, /* XF86Fn_F12 */ { 0x100811de, 28273 }, /* XF86Fn_1 */ { 0x100811df, 28282 }, /* XF86Fn_2 */ { 0x100811e0, 28300 }, /* XF86Fn_D */ { 0x100811e1, 28309 }, /* XF86Fn_E */ { 0x100811e2, 28329 }, /* XF86Fn_F */ { 0x100811e3, 28461 }, /* XF86Fn_S */ { 0x100811e4, 28291 }, /* XF86Fn_B */ { 0x100811e5, 28470 }, /* XF86FnRightShift */ { 0x10081200, 30593 }, /* XF86Numeric0 */ { 0x10081201, 30606 }, /* XF86Numeric1 */ { 0x10081202, 30647 }, /* XF86Numeric2 */ { 0x10081203, 30660 }, /* XF86Numeric3 */ { 0x10081204, 30673 }, /* XF86Numeric4 */ { 0x10081205, 30686 }, /* XF86Numeric5 */ { 0x10081206, 30699 }, /* XF86Numeric6 */ { 0x10081207, 30712 }, /* XF86Numeric7 */ { 0x10081208, 30725 }, /* XF86Numeric8 */ { 0x10081209, 30738 }, /* XF86Numeric9 */ { 0x1008120a, 30820 }, /* XF86NumericStar */ { 0x1008120b, 30803 }, /* XF86NumericPound */ { 0x1008120c, 30751 }, /* XF86NumericA */ { 0x1008120d, 30764 }, /* XF86NumericB */ { 0x1008120e, 30777 }, /* XF86NumericC */ { 0x1008120f, 30790 }, /* XF86NumericD */ { 0x10081210, 27721 }, /* XF86CameraFocus */ { 0x10081211, 32291 }, /* XF86WPSButton */ { 0x10081215, 27781 }, /* XF86CameraZoomIn */ { 0x10081216, 27798 }, /* XF86CameraZoomOut */ { 0x10081217, 27768 }, /* XF86CameraUp */ { 0x10081218, 27706 }, /* XF86CameraDown */ { 0x10081219, 27737 }, /* XF86CameraLeft */ { 0x1008121a, 27752 }, /* XF86CameraRight */ { 0x1008121b, 27025 }, /* XF86AttendantOn */ { 0x1008121c, 27008 }, /* XF86AttendantOff */ { 0x1008121d, 27041 }, /* XF86AttendantToggle */ { 0x1008121e, 29245 }, /* XF86LightsToggle */ { 0x10081230, 26909 }, /* XF86ALSToggle */ { 0x10081232, 31142 }, /* XF86RefreshRateToggle */ { 0x10081240, 27576 }, /* XF86Buttonconfig */ { 0x10081241, 31899 }, /* XF86Taskmanager */ { 0x10081242, 28698 }, /* XF86Journal */ { 0x10081243, 27953 }, /* XF86ControlPanel */ { 0x10081244, 26964 }, /* XF86AppSelect */ { 0x10081245, 31375 }, /* XF86Screensaver */ { 0x10081246, 32204 }, /* XF86VoiceCommand */ { 0x10081247, 26994 }, /* XF86Assistant */ { 0x10081249, 28168 }, /* XF86EmojiPicker */ { 0x1008124a, 28024 }, /* XF86Dictate */ { 0x1008124b, 27660 }, /* XF86CameraAccessEnable */ { 0x1008124c, 27636 }, /* XF86CameraAccessDisable */ { 0x1008124d, 27683 }, /* XF86CameraAccessToggle */ { 0x1008124e, 26859 }, /* XF86Accessibility */ { 0x1008124f, 28095 }, /* XF86DoNotDisturb */ { 0x10081250, 27558 }, /* XF86BrightnessMin */ { 0x10081251, 27540 }, /* XF86BrightnessMax */ { 0x10081260, 28853 }, /* XF86KbdInputAssistPrev */ { 0x10081261, 28802 }, /* XF86KbdInputAssistNext */ { 0x10081262, 28876 }, /* XF86KbdInputAssistPrevgroup */ { 0x10081263, 28825 }, /* XF86KbdInputAssistNextgroup */ { 0x10081264, 28752 }, /* XF86KbdInputAssistAccept */ { 0x10081265, 28777 }, /* XF86KbdInputAssistCancel */ { 0x10081266, 31210 }, /* XF86RightUp */ { 0x10081267, 31196 }, /* XF86RightDown */ { 0x10081268, 29220 }, /* XF86LeftUp */ { 0x10081269, 29207 }, /* XF86LeftDown */ { 0x1008126a, 31266 }, /* XF86RootMenu */ { 0x1008126b, 30249 }, /* XF86MediaTopMenu */ { 0x1008126c, 30619 }, /* XF86Numeric11 */ { 0x1008126d, 30633 }, /* XF86Numeric12 */ { 0x1008126e, 27112 }, /* XF86AudioDesc */ { 0x1008126f, 26848 }, /* XF863DMode */ { 0x10081270, 30533 }, /* XF86NextFavorite */ { 0x10081271, 31652 }, /* XF86StopRecord */ { 0x10081272, 30921 }, /* XF86PauseRecord */ { 0x10081273, 32196 }, /* XF86VOD */ { 0x10081274, 32078 }, /* XF86Unmute */ { 0x10081275, 28207 }, /* XF86FastReverse */ { 0x10081276, 31546 }, /* XF86SlowReverse */ { 0x10081277, 28002 }, /* XF86Data */ { 0x10081278, 30858 }, /* XF86OnScreenKeyboard */ { 0x10081279, 31075 }, /* XF86PrivacyScreenToggle */ { 0x1008127a, 31457 }, /* XF86SelectiveScreenshot */ { 0x1008127b, 30517 }, /* XF86NextElement */ { 0x1008127c, 31055 }, /* XF86PreviousElement */ { 0x1008127d, 27386 }, /* XF86AutopilotEngageToggle */ { 0x1008127e, 29821 }, /* XF86MarkWaypoint */ { 0x1008127f, 31562 }, /* XF86Sos */ { 0x10081280, 30460 }, /* XF86NavChart */ { 0x10081281, 28249 }, /* XF86FishingChart */ { 0x10081282, 31515 }, /* XF86SingleRangeRadar */ { 0x10081283, 28120 }, /* XF86DualRangeRadar */ { 0x10081284, 31105 }, /* XF86RadarOverlay */ { 0x10081285, 32035 }, /* XF86TraditionalSonar */ { 0x10081286, 27877 }, /* XF86ClearvuSonar */ { 0x10081287, 31499 }, /* XF86SidevuSonar */ { 0x10081288, 30473 }, /* XF86NavInfo */ { 0x10081290, 29321 }, /* XF86Macro1 */ { 0x10081291, 29452 }, /* XF86Macro2 */ { 0x10081292, 29583 }, /* XF86Macro3 */ { 0x10081293, 29606 }, /* XF86Macro4 */ { 0x10081294, 29617 }, /* XF86Macro5 */ { 0x10081295, 29628 }, /* XF86Macro6 */ { 0x10081296, 29639 }, /* XF86Macro7 */ { 0x10081297, 29650 }, /* XF86Macro8 */ { 0x10081298, 29661 }, /* XF86Macro9 */ { 0x10081299, 29332 }, /* XF86Macro10 */ { 0x1008129a, 29344 }, /* XF86Macro11 */ { 0x1008129b, 29356 }, /* XF86Macro12 */ { 0x1008129c, 29368 }, /* XF86Macro13 */ { 0x1008129d, 29380 }, /* XF86Macro14 */ { 0x1008129e, 29392 }, /* XF86Macro15 */ { 0x1008129f, 29404 }, /* XF86Macro16 */ { 0x100812a0, 29416 }, /* XF86Macro17 */ { 0x100812a1, 29428 }, /* XF86Macro18 */ { 0x100812a2, 29440 }, /* XF86Macro19 */ { 0x100812a3, 29463 }, /* XF86Macro20 */ { 0x100812a4, 29475 }, /* XF86Macro21 */ { 0x100812a5, 29487 }, /* XF86Macro22 */ { 0x100812a6, 29499 }, /* XF86Macro23 */ { 0x100812a7, 29511 }, /* XF86Macro24 */ { 0x100812a8, 29523 }, /* XF86Macro25 */ { 0x100812a9, 29535 }, /* XF86Macro26 */ { 0x100812aa, 29547 }, /* XF86Macro27 */ { 0x100812ab, 29559 }, /* XF86Macro28 */ { 0x100812ac, 29571 }, /* XF86Macro29 */ { 0x100812ad, 29594 }, /* XF86Macro30 */ { 0x100812b0, 29744 }, /* XF86MacroRecordStart */ { 0x100812b1, 29765 }, /* XF86MacroRecordStop */ { 0x100812b2, 29723 }, /* XF86MacroPresetCycle */ { 0x100812b3, 29672 }, /* XF86MacroPreset1 */ { 0x100812b4, 29689 }, /* XF86MacroPreset2 */ { 0x100812b5, 29706 }, /* XF86MacroPreset3 */ { 0x100812b8, 28904 }, /* XF86KbdLcdMenu1 */ { 0x100812b9, 28920 }, /* XF86KbdLcdMenu2 */ { 0x100812ba, 28936 }, /* XF86KbdLcdMenu3 */ { 0x100812bb, 28952 }, /* XF86KbdLcdMenu4 */ { 0x100812bc, 28968 }, /* XF86KbdLcdMenu5 */ { 0x100812bd, 30937 }, /* XF86PerformanceMode */ { 0x1008fe01, 31704 }, /* XF86Switch_VT_1 */ { 0x1008fe02, 31771 }, /* XF86Switch_VT_2 */ { 0x1008fe03, 31787 }, /* XF86Switch_VT_3 */ { 0x1008fe04, 31803 }, /* XF86Switch_VT_4 */ { 0x1008fe05, 31819 }, /* XF86Switch_VT_5 */ { 0x1008fe06, 31835 }, /* XF86Switch_VT_6 */ { 0x1008fe07, 31851 }, /* XF86Switch_VT_7 */ { 0x1008fe08, 31867 }, /* XF86Switch_VT_8 */ { 0x1008fe09, 31883 }, /* XF86Switch_VT_9 */ { 0x1008fe0a, 31720 }, /* XF86Switch_VT_10 */ { 0x1008fe0b, 31737 }, /* XF86Switch_VT_11 */ { 0x1008fe0c, 31754 }, /* XF86Switch_VT_12 */ { 0x1008fe20, 32067 }, /* XF86Ungrab */ { 0x1008fe21, 27863 }, /* XF86ClearGrab */ { 0x1008fe22, 30502 }, /* XF86Next_VMode */ { 0x1008fe23, 31040 }, /* XF86Prev_VMode */ { 0x1008fe24, 29303 }, /* XF86LogWindowTree */ { 0x1008fe25, 29276 }, /* XF86LogGrabInfo */ { 0x1008ff01, 30323 }, /* XF86ModeLock */ { 0x1008ff02, 30403 }, /* XF86MonBrightnessUp */ { 0x1008ff03, 30381 }, /* XF86MonBrightnessDown */ { 0x1008ff04, 28984 }, /* XF86KbdLightOnOff */ { 0x1008ff05, 28732 }, /* XF86KbdBrightnessUp */ { 0x1008ff06, 28710 }, /* XF86KbdBrightnessDown */ { 0x1008ff07, 30358 }, /* XF86MonBrightnessCycle */ { 0x1008ff10, 31621 }, /* XF86Standby */ { 0x1008ff11, 27143 }, /* XF86AudioLowerVolume */ { 0x1008ff12, 27196 }, /* XF86AudioMute */ { 0x1008ff13, 27283 }, /* XF86AudioRaiseVolume */ { 0x1008ff14, 27239 }, /* XF86AudioPlay */ { 0x1008ff15, 27372 }, /* XF86AudioStop */ { 0x1008ff16, 27269 }, /* XF86AudioPrev */ { 0x1008ff17, 27210 }, /* XF86AudioNext */ { 0x1008ff18, 28641 }, /* XF86HomePage */ { 0x1008ff19, 29785 }, /* XF86Mail */ { 0x1008ff1a, 31633 }, /* XF86Start */ { 0x1008ff1b, 31435 }, /* XF86Search */ { 0x1008ff1c, 27324 }, /* XF86AudioRecord */ { 0x1008ff1d, 27608 }, /* XF86Calculator */ { 0x1008ff1e, 30278 }, /* XF86Memo */ { 0x1008ff1f, 31950 }, /* XF86ToDoList */ { 0x1008ff20, 27623 }, /* XF86Calendar */ { 0x1008ff21, 30996 }, /* XF86PowerDown */ { 0x1008ff22, 27934 }, /* XF86ContrastAdjust */ { 0x1008ff23, 31253 }, /* XF86RockerUp */ { 0x1008ff24, 31222 }, /* XF86RockerDown */ { 0x1008ff25, 31237 }, /* XF86RockerEnter */ { 0x1008ff26, 27421 }, /* XF86Back */ { 0x1008ff27, 28487 }, /* XF86Forward */ { 0x1008ff28, 31643 }, /* XF86Stop */ { 0x1008ff29, 31130 }, /* XF86Refresh */ { 0x1008ff2a, 31010 }, /* XF86PowerOff */ { 0x1008ff2b, 32235 }, /* XF86WakeUp */ { 0x1008ff2c, 28158 }, /* XF86Eject */ { 0x1008ff2d, 31359 }, /* XF86ScreenSaver */ { 0x1008ff2e, 32314 }, /* XF86WWW */ { 0x1008ff2f, 31536 }, /* XF86Sleep */ { 0x1008ff30, 28223 }, /* XF86Favorites */ { 0x1008ff31, 27224 }, /* XF86AudioPause */ { 0x1008ff32, 27164 }, /* XF86AudioMedia */ { 0x1008ff33, 30433 }, /* XF86MyComputer */ { 0x1008ff34, 32132 }, /* XF86VendorHome */ { 0x1008ff35, 29231 }, /* XF86LightBulb */ { 0x1008ff36, 31490 }, /* XF86Shop */ { 0x1008ff37, 28629 }, /* XF86History */ { 0x1008ff38, 30888 }, /* XF86OpenURL */ { 0x1008ff39, 26877 }, /* XF86AddFavorite */ { 0x1008ff3a, 28654 }, /* XF86HotLinks */ { 0x1008ff3b, 27500 }, /* XF86BrightnessAdjust */ { 0x1008ff3c, 28237 }, /* XF86Finance */ { 0x1008ff3d, 27904 }, /* XF86Community */ { 0x1008ff3e, 27356 }, /* XF86AudioRewind */ { 0x1008ff3f, 27430 }, /* XF86BackForward */ { 0x1008ff40, 29015 }, /* XF86Launch0 */ { 0x1008ff41, 29027 }, /* XF86Launch1 */ { 0x1008ff42, 29039 }, /* XF86Launch2 */ { 0x1008ff43, 29051 }, /* XF86Launch3 */ { 0x1008ff44, 29063 }, /* XF86Launch4 */ { 0x1008ff45, 29075 }, /* XF86Launch5 */ { 0x1008ff46, 29087 }, /* XF86Launch6 */ { 0x1008ff47, 29099 }, /* XF86Launch7 */ { 0x1008ff48, 29111 }, /* XF86Launch8 */ { 0x1008ff49, 29123 }, /* XF86Launch9 */ { 0x1008ff4a, 29135 }, /* XF86LaunchA */ { 0x1008ff4b, 29147 }, /* XF86LaunchB */ { 0x1008ff4c, 29159 }, /* XF86LaunchC */ { 0x1008ff4d, 29171 }, /* XF86LaunchD */ { 0x1008ff4e, 29183 }, /* XF86LaunchE */ { 0x1008ff4f, 29195 }, /* XF86LaunchF */ { 0x1008ff50, 26923 }, /* XF86ApplicationLeft */ { 0x1008ff51, 26943 }, /* XF86ApplicationRight */ { 0x1008ff52, 27481 }, /* XF86Book */ { 0x1008ff53, 27816 }, /* XF86CD */ { 0x1008ff54, 27593 }, /* XF86Calculater */ { 0x1008ff55, 27853 }, /* XF86Clear */ { 0x1008ff56, 27894 }, /* XF86Close */ { 0x1008ff57, 27970 }, /* XF86Copy */ { 0x1008ff58, 27979 }, /* XF86Cut */ { 0x1008ff59, 28036 }, /* XF86Display */ { 0x1008ff5a, 28112 }, /* XF86DOS */ { 0x1008ff5b, 28081 }, /* XF86Documents */ { 0x1008ff5c, 28184 }, /* XF86Excel */ { 0x1008ff5d, 28194 }, /* XF86Explorer */ { 0x1008ff5e, 28545 }, /* XF86Game */ { 0x1008ff5f, 28554 }, /* XF86Go */ { 0x1008ff60, 28687 }, /* XF86iTouch */ { 0x1008ff61, 29292 }, /* XF86LogOff */ { 0x1008ff62, 29810 }, /* XF86Market */ { 0x1008ff63, 30266 }, /* XF86Meeting */ { 0x1008ff65, 30287 }, /* XF86MenuKB */ { 0x1008ff66, 30298 }, /* XF86MenuPB */ { 0x1008ff67, 30448 }, /* XF86MySites */ { 0x1008ff68, 30485 }, /* XF86New */ { 0x1008ff69, 30493 }, /* XF86News */ { 0x1008ff6a, 30836 }, /* XF86OfficeHome */ { 0x1008ff6b, 30879 }, /* XF86Open */ { 0x1008ff6c, 30900 }, /* XF86Option */ { 0x1008ff6d, 30911 }, /* XF86Paste */ { 0x1008ff6e, 30957 }, /* XF86Phone */ { 0x1008ff70, 31099 }, /* XF86Q */ { 0x1008ff72, 31175 }, /* XF86Reply */ { 0x1008ff73, 31164 }, /* XF86Reload */ { 0x1008ff74, 31279 }, /* XF86RotateWindows */ { 0x1008ff75, 31335 }, /* XF86RotationPB */ { 0x1008ff76, 31297 }, /* XF86RotationKB */ { 0x1008ff77, 31350 }, /* XF86Save */ { 0x1008ff78, 31422 }, /* XF86ScrollUp */ { 0x1008ff79, 31407 }, /* XF86ScrollDown */ { 0x1008ff7a, 31391 }, /* XF86ScrollClick */ { 0x1008ff7b, 31481 }, /* XF86Send */ { 0x1008ff7c, 31570 }, /* XF86Spell */ { 0x1008ff7d, 31595 }, /* XF86SplitScreen */ { 0x1008ff7e, 31680 }, /* XF86Support */ { 0x1008ff7f, 31915 }, /* XF86TaskPane */ { 0x1008ff80, 31928 }, /* XF86Terminal */ { 0x1008ff81, 31963 }, /* XF86Tools */ { 0x1008ff82, 32056 }, /* XF86Travel */ { 0x1008ff84, 32113 }, /* XF86UserPB */ { 0x1008ff85, 32089 }, /* XF86User1KB */ { 0x1008ff86, 32101 }, /* XF86User2KB */ { 0x1008ff87, 32162 }, /* XF86Video */ { 0x1008ff88, 32257 }, /* XF86WheelButton */ { 0x1008ff89, 32282 }, /* XF86Word */ { 0x1008ff8a, 32322 }, /* XF86Xfer */ { 0x1008ff8b, 32342 }, /* XF86ZoomIn */ { 0x1008ff8c, 32353 }, /* XF86ZoomOut */ { 0x1008ff8d, 27412 }, /* XF86Away */ { 0x1008ff8e, 30309 }, /* XF86Messenger */ { 0x1008ff8f, 32246 }, /* XF86WebCam */ { 0x1008ff90, 29794 }, /* XF86MailForward */ { 0x1008ff91, 30983 }, /* XF86Pictures */ { 0x1008ff92, 30423 }, /* XF86Music */ { 0x1008ff93, 27446 }, /* XF86Battery */ { 0x1008ff94, 27467 }, /* XF86Bluetooth */ { 0x1008ff95, 32273 }, /* XF86WLAN */ { 0x1008ff96, 32124 }, /* XF86UWB */ { 0x1008ff97, 27126 }, /* XF86AudioForward */ { 0x1008ff98, 27340 }, /* XF86AudioRepeat */ { 0x1008ff99, 27304 }, /* XF86AudioRandomPlay */ { 0x1008ff9a, 31667 }, /* XF86Subtitle */ { 0x1008ff9b, 27092 }, /* XF86AudioCycleTrack */ { 0x1008ff9c, 27987 }, /* XF86CycleAngle */ { 0x1008ff9d, 28499 }, /* XF86FrameBack */ { 0x1008ff9e, 28513 }, /* XF86FrameForward */ { 0x1008ff9f, 31941 }, /* XF86Time */ { 0x1008ffa0, 31446 }, /* XF86Select */ { 0x1008ffa1, 32187 }, /* XF86View */ { 0x1008ffa2, 31973 }, /* XF86TopMenu */ { 0x1008ffa3, 31122 }, /* XF86Red */ { 0x1008ffa4, 28589 }, /* XF86Green */ { 0x1008ffa5, 32331 }, /* XF86Yellow */ { 0x1008ffa6, 27458 }, /* XF86Blue */ { 0x1008ffa7, 31692 }, /* XF86Suspend */ { 0x1008ffa8, 28615 }, /* XF86Hibernate */ { 0x1008ffa9, 32016 }, /* XF86TouchpadToggle */ { 0x1008ffb0, 32001 }, /* XF86TouchpadOn */ { 0x1008ffb1, 31985 }, /* XF86TouchpadOff */ { 0x1008ffb2, 27179 }, /* XF86AudioMicMute */ { 0x1008ffb3, 29002 }, /* XF86Keyboard */ { 0x1008ffb4, 32305 }, /* XF86WWAN */ { 0x1008ffb5, 31185 }, /* XF86RFKill */ { 0x1008ffb6, 27253 }, /* XF86AudioPreset */ { 0x1008ffb7, 31312 }, /* XF86RotationLockToggle */ { 0x1008ffb8, 28530 }, /* XF86FullScreen */ }; #define UNICODE_KEYSYM 0xfffe #define DEPRECATED_KEYSYM 0xffff struct deprecated_keysym { xkb_keysym_t keysym; uint16_t offset; /* Explicit deprecated aliases start index & count */ uint8_t explicit_index; uint8_t explicit_count; }; static const struct deprecated_keysym deprecated_keysyms[] = { { 0x00000027, 934 , 0, 0 }, /* Reference: apostrophe. Deprecated: quoteright */ { 0x00000060, 13381 , 0, 0 }, /* Reference: grave. Deprecated: quoteleft */ { 0x000000ab, 14464 , 0, 0 }, /* Reference: guillemetleft. Deprecated: guillemotleft */ { 0x000000ba, 21008 , 0, 0 }, /* Reference: ordmasculine. Deprecated: masculine */ { 0x000000bb, 14478 , 0, 0 }, /* Reference: guillemetright. Deprecated: guillemotright */ { 0x000000d0, 12179 , 0, 0 }, /* Reference: ETH. Deprecated: Eth */ { 0x000000d8, 21453 , 0, 0 }, /* Reference: Oslash. Deprecated: Ooblique */ { 0x000000de, 25656 , 0, 0 }, /* Reference: THORN. Deprecated: Thorn */ { 0x000000f8, 21460 , 0, 0 }, /* Reference: oslash. Deprecated: ooblique */ { 0x000003a2, 19252 , 0, 0 }, /* Reference: kra. Deprecated: kappa */ { 0x000004a5, 18348 , 0, 0 }, /* Reference: kana_conjunctive. Deprecated: kana_middledot */ { 0x000004af, 18786 , 0, 0 }, /* Reference: kana_tsu. Deprecated: kana_tu */ { 0x000004c1, 18308 , 0, 0 }, /* Reference: kana_CHI. Deprecated: kana_TI */ { 0x000004c2, 18777 , 0, 0 }, /* Reference: kana_TSU. Deprecated: kana_TU */ { 0x000004cc, 18379 , 0, 0 }, /* Reference: kana_FU. Deprecated: kana_HU */ { 0x000005e7, 1282 , 0, 0 }, /* Reference: Arabic_ha. Deprecated: Arabic_heh */ { 0x000006a4, 26369 , 0, 0 }, /* Reference: Ukrainian_ie. Deprecated: Ukranian_je */ { 0x000006a6, 26344 , 0, 0 }, /* Reference: Ukrainian_i. Deprecated: Ukranian_i */ { 0x000006a7, 26395 , 0, 0 }, /* Reference: Ukrainian_yi. Deprecated: Ukranian_yi */ { 0x000006a8, 9574 , 0, 0 }, /* Reference: Cyrillic_je. Deprecated: Serbian_je */ { 0x000006a9, 9713 , 0, 0 }, /* Reference: Cyrillic_lje. Deprecated: Serbian_lje */ { 0x000006aa, 9739 , 0, 0 }, /* Reference: Cyrillic_nje. Deprecated: Serbian_nje */ { 0x000006af, 9068 , 0, 0 }, /* Reference: Cyrillic_dzhe. Deprecated: Serbian_dze */ { 0x000006b4, 26356 , 0, 0 }, /* Reference: Ukrainian_IE. Deprecated: Ukranian_JE */ { 0x000006b6, 26332 , 0, 0 }, /* Reference: Ukrainian_I. Deprecated: Ukranian_I */ { 0x000006b7, 26382 , 0, 0 }, /* Reference: Ukrainian_YI. Deprecated: Ukranian_YI */ { 0x000006b8, 9562 , 0, 0 }, /* Reference: Cyrillic_JE. Deprecated: Serbian_JE */ { 0x000006b9, 9700 , 0, 0 }, /* Reference: Cyrillic_LJE. Deprecated: Serbian_LJE */ { 0x000006ba, 9726 , 0, 0 }, /* Reference: Cyrillic_NJE. Deprecated: Serbian_NJE */ { 0x000006bf, 9054 , 0, 0 }, /* Reference: Cyrillic_DZHE. Deprecated: Serbian_DZE */ { 0x000007a5, 13841 , 0, 0 }, /* Reference: Greek_IOTAdieresis. Deprecated: Greek_IOTAdiaeresis */ { 0x000008a2, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: topleftradical */ { 0x000008a3, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: horizconnector */ { 0x000008a6, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: vertconnector */ { 0x00000aac, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: signifblank */ { 0x00000abc, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: leftanglebracket */ { 0x00000abd, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: decimalpoint */ { 0x00000abe, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: rightanglebracket */ { 0x00000aca, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: signaturemark */ { 0x00000acc, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: leftopentriangle */ { 0x00000acd, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: rightopentriangle */ { 0x00000ace, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: emopencircle */ { 0x00000acf, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: emopenrectangle */ { 0x00000adb, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: filledrectbullet */ { 0x00000adc, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: filledlefttribullet */ { 0x00000add, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: filledrighttribullet */ { 0x00000ade, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: emfilledcircle */ { 0x00000adf, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: emfilledrect */ { 0x00000ae0, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: enopencircbullet */ { 0x00000ae1, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: enopensquarebullet */ { 0x00000ae2, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: openrectbullet */ { 0x00000ae3, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: opentribulletup */ { 0x00000ae4, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: opentribulletdown */ { 0x00000ae5, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: openstar */ { 0x00000ae6, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: enfilledcircbullet */ { 0x00000ae7, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: enfilledsqbullet */ { 0x00000ae8, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: filledtribulletup */ { 0x00000ae9, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: filledtribulletdown */ { 0x00000aea, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: leftpointer */ { 0x00000aeb, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: rightpointer */ { 0x00000ba3, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: leftcaret */ { 0x00000ba6, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: rightcaret */ { 0x00000ba8, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: downcaret */ { 0x00000ba9, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: upcaret */ { 0x00000bc0, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: overbar */ { 0x00000bc3, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: upshoe */ { 0x00000bc6, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: underbar */ { 0x00000bd6, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: downshoe */ { 0x00000bd8, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: rightshoe */ { 0x00000bda, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: leftshoe */ { 0x00000ce1, 16255 , 0, 0 }, /* Reference: hebrew_bet. Deprecated: hebrew_beth */ { 0x00000ce2, 16436 , 0, 0 }, /* Reference: hebrew_gimel. Deprecated: hebrew_gimmel */ { 0x00000ce3, 16290 , 0, 0 }, /* Reference: hebrew_dalet. Deprecated: hebrew_daleth */ { 0x00000ce6, 16721 , 0, 0 }, /* Reference: hebrew_zain. Deprecated: hebrew_zayin */ { 0x00000ce7, 16278 , 0, 0 }, /* Reference: hebrew_chet. Deprecated: hebrew_het */ { 0x00000ce8, 16652 , 0, 0 }, /* Reference: hebrew_tet. Deprecated: hebrew_teth */ { 0x00000cf1, 16576 , 0, 0 }, /* Reference: hebrew_samech. Deprecated: hebrew_samekh */ { 0x00000cf5, 16402 , 0, 0 }, /* Reference: hebrew_finalzade. Deprecated: hebrew_finalzadi */ { 0x00000cf6, 16697 , 0, 0 }, /* Reference: hebrew_zade. Deprecated: hebrew_zadi */ { 0x00000cf7, 16552 , 0, 0 }, /* Reference: hebrew_qoph. Deprecated: hebrew_kuf */ { 0x00000cfa, 16641 , 0, 0 }, /* Reference: hebrew_taw. Deprecated: hebrew_taf */ { 0x00000dde, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: Thai_maihanakat_maitho */ { 0x00000eff, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: Korean_Won */ { 0x0000fe8a, 11150 , 0, 0 }, /* Reference: dead_schwa. Deprecated: dead_small_schwa */ { 0x0000fe8b, 11139 , 0, 0 }, /* Reference: dead_SCHWA. Deprecated: dead_capital_schwa */ { 0x0000ff20, 19955 , 0, 0 }, /* Reference: Multi_key. Deprecated: SunCompose */ { 0x0000ff37, 8654 , 0, 0 }, /* Reference: Codeinput. Deprecated: Kanji_Bangou, Hangul_Codeinput */ { 0x0000ff3c, 23169 , 0, 0 }, /* Reference: SingleCandidate. Deprecated: Hangul_SingleCandidate */ { 0x0000ff3d, 19965 , 0, 0 }, /* Reference: MultipleCandidate. Deprecated: Zen_Koho, Hangul_MultipleCandidate */ { 0x0000ff3e, 22257 , 0, 0 }, /* Reference: PreviousCandidate. Deprecated: Mae_Koho, Hangul_PreviousCandidate */ { 0x0000ff55, 22281 , 0, 0 }, /* Reference: Prior. Deprecated: Page_Up, SunPageUp */ { 0x0000ff56, 20167 , 0, 0 }, /* Reference: Next. Deprecated: Page_Down, SunPageDown */ { 0x0000ff61, 22275 , 0, 0 }, /* Reference: Print. Deprecated: SunPrint_Screen */ { 0x0000ff65, 26514 , 0, 0 }, /* Reference: Undo. Deprecated: SunUndo */ { 0x0000ff66, 22483 , 0, 0 }, /* Reference: Redo. Deprecated: SunAgain */ { 0x0000ff68, 12646 , 0, 0 }, /* Reference: Find. Deprecated: SunFind */ { 0x0000ff69, 8489 , 0, 0 }, /* Reference: Cancel. Deprecated: SunStop */ { 0x0000ff7e, 19891 , 0, 1 }, /* Reference: Mode_switch. Non deprecated aliases: script_switch, ISO_Group_Shift, kana_switch, Arabic_switch, Greek_switch, Hebrew_switch, Hangul_switch. Deprecated: SunAltGraph */ { 0x0000ff9a, 19187 , 0, 0 }, /* Reference: KP_Prior. Deprecated: KP_Page_Up */ { 0x0000ff9b, 19155 , 0, 0 }, /* Reference: KP_Next. Deprecated: KP_Page_Down */ { 0x0000ffc8, 12281 , 0, 0 }, /* Reference: F11. Deprecated: L1 */ { 0x0000ffc9, 12285 , 0, 0 }, /* Reference: F12. Deprecated: L2 */ { 0x0000ffca, 12289 , 0, 0 }, /* Reference: F13. Deprecated: L3 */ { 0x0000ffcb, 12293 , 0, 0 }, /* Reference: F14. Deprecated: L4 */ { 0x0000ffcc, 12297 , 0, 0 }, /* Reference: F15. Deprecated: L5 */ { 0x0000ffcd, 12301 , 0, 0 }, /* Reference: F16. Deprecated: L6 */ { 0x0000ffce, 12305 , 0, 0 }, /* Reference: F17. Deprecated: L7 */ { 0x0000ffcf, 12309 , 0, 0 }, /* Reference: F18. Deprecated: L8 */ { 0x0000ffd0, 12313 , 0, 0 }, /* Reference: F19. Deprecated: L9 */ { 0x0000ffd1, 12320 , 0, 0 }, /* Reference: F20. Deprecated: L10 */ { 0x0000ffd2, 12324 , 0, 0 }, /* Reference: F21. Deprecated: R1 */ { 0x0000ffd3, 12328 , 0, 0 }, /* Reference: F22. Deprecated: R2 */ { 0x0000ffd4, 12332 , 0, 0 }, /* Reference: F23. Deprecated: R3 */ { 0x0000ffd5, 12336 , 0, 0 }, /* Reference: F24. Deprecated: R4 */ { 0x0000ffd6, 12340 , 0, 0 }, /* Reference: F25. Deprecated: R5 */ { 0x0000ffd7, 12344 , 0, 0 }, /* Reference: F26. Deprecated: R6 */ { 0x0000ffd8, 12348 , 0, 0 }, /* Reference: F27. Deprecated: R7 */ { 0x0000ffd9, 12352 , 0, 0 }, /* Reference: F28. Deprecated: R8 */ { 0x0000ffda, 12356 , 0, 0 }, /* Reference: F29. Deprecated: R9 */ { 0x0000ffdb, 12363 , 0, 0 }, /* Reference: F30. Deprecated: R10 */ { 0x0000ffdc, 12367 , 0, 0 }, /* Reference: F31. Deprecated: R11 */ { 0x0000ffdd, 12371 , 0, 0 }, /* Reference: F32. Deprecated: R12 */ { 0x0000ffde, 12375 , 0, 0 }, /* Reference: F33. Deprecated: R13 */ { 0x0000ffdf, 12379 , 0, 0 }, /* Reference: F34. Deprecated: R14 */ { 0x0000ffe0, 12383 , 0, 0 }, /* Reference: F35. Deprecated: R15 */ { 0x0100055b, 2048 , 0, 0 }, /* Reference: Armenian_accent. Deprecated: Armenian_shesht */ { 0x0100055c, 2287 , 0, 0 }, /* Reference: Armenian_exclam. Deprecated: Armenian_amanak */ { 0x0100055d, 2869 , 0, 0 }, /* Reference: Armenian_separation_mark. Deprecated: Armenian_but */ { 0x0100055e, 2779 , 0, 0 }, /* Reference: Armenian_question. Deprecated: Armenian_paruyk */ { 0x01000589, 2327 , 0, 0 }, /* Reference: Armenian_full_stop. Deprecated: Armenian_verjaket */ { 0x0100058a, 2448 , 0, 0 }, /* Reference: Armenian_hyphen. Deprecated: Armenian_yentamna */ { 0x010006cc, 12505 , 0, 0 }, /* Reference: Farsi_yeh. Deprecated: Arabic_farsi_yeh */ { 0x01002247, UNICODE_KEYSYM , 0, 0 }, /* Deprecated: notapproxeq */ { 0x01002248, UNICODE_KEYSYM , 0, 0 }, /* Deprecated: approxeq */ { 0x100000a8, 17054 , 0, 0 }, /* Reference: hpmute_acute. Deprecated: mute_acute */ { 0x100000a9, 17121 , 0, 0 }, /* Reference: hpmute_grave. Deprecated: mute_grave */ { 0x100000aa, 17067 , 0, 0 }, /* Reference: hpmute_asciicircum. Deprecated: mute_asciicircum */ { 0x100000ab, 17104 , 0, 0 }, /* Reference: hpmute_diaeresis. Deprecated: mute_diaeresis */ { 0x100000ac, 17086 , 0, 0 }, /* Reference: hpmute_asciitilde. Deprecated: mute_asciitilde */ { 0x100000af, 17011 , 0, 0 }, /* Reference: hplira. Deprecated: lira */ { 0x100000be, 16957 , 0, 0 }, /* Reference: hpguilder. Deprecated: guilder */ { 0x100000ee, 17158 , 0, 0 }, /* Reference: hpYdiaeresis. Deprecated: hpIO, IO */ { 0x100000f6, 17018 , 0, 0 }, /* Reference: hplongminus. Deprecated: longminus */ { 0x100000fc, 16911 , 0, 0 }, /* Reference: hpblock. Deprecated: block */ { 0x1000ff6c, 17134 , 0, 0 }, /* Reference: hpReset. Deprecated: Reset */ { 0x1000ff6d, 17142 , 0, 0 }, /* Reference: hpSystem. Deprecated: System */ { 0x1000ff6e, 17151 , 0, 0 }, /* Reference: hpUser. Deprecated: User */ { 0x1000ff6f, 16919 , 0, 0 }, /* Reference: hpClearLine. Deprecated: ClearLine */ { 0x1000ff70, 16980 , 0, 0 }, /* Reference: hpInsertLine. Deprecated: InsertLine */ { 0x1000ff71, 16944 , 0, 0 }, /* Reference: hpDeleteLine. Deprecated: DeleteLine */ { 0x1000ff72, 16967 , 0, 0 }, /* Reference: hpInsertChar. Deprecated: InsertChar */ { 0x1000ff73, 16931 , 0, 0 }, /* Reference: hpDeleteChar. Deprecated: DeleteChar */ { 0x1000ff74, 16901 , 0, 0 }, /* Reference: hpBackTab. Deprecated: BackTab */ { 0x1000ff75, 16998 , 0, 0 }, /* Reference: hpKP_BackTab. Deprecated: KP_BackTab */ { 0x1000ff76, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: Ext16bit_L */ { 0x1000ff77, DEPRECATED_KEYSYM, 0, 0 }, /* Deprecated: Ext16bit_R */ { 0x100810f4, 30336 , 0, 0 }, /* Reference: XF86MonBrightnessAuto. Deprecated: XF86BrightnessAuto */ }; static const uint32_t explicit_deprecated_aliases[] = { 24029, }; xkbcommon-libxkbcommon-54ee7ac/src/messages-codes.h000066400000000000000000000223551510033435100225340ustar00rootroot00000000000000// NOTE: This file has been generated automatically by “update-message-registry.py”. // Do not edit manually! #pragma once #include "config.h" #include /* * Macro sorcery: PREPEND_MESSAGE_ID enables the log functions to format messages * with the message ID only if the ID is not 0 (XKB_LOG_MESSAGE_NO_ID). * This avoid checking the ID value at run time. * * The trick resides in CHECK_ID: * • CHECK_ID(0) expands to: * ‣ SECOND(MATCH0, WITH_ID, unused) * ‣ SECOND(unused,WITHOUT_ID, WITH_ID, unused) * ‣ WITHOUT_ID * • CHECK_ID(123) expands to: * ‣ SECOND(MATCH123, WITH_ID, unused) * ‣ WITH_ID */ #define EXPAND(...) __VA_ARGS__ /* needed for MSVC compatibility */ #define JOIN_EXPAND(a, b) a##b #define JOIN(a, b) JOIN_EXPAND(a, b) #define SECOND_EXPAND(a, b, ...) b #define SECOND(...) EXPAND(SECOND_EXPAND(__VA_ARGS__)) #define MATCH0 unused,WITHOUT_ID #define CHECK_ID(value) SECOND(JOIN(MATCH, value), WITH_ID, unused) #define FORMAT_MESSAGE_WITHOUT_ID(id, fmt) fmt #define FORMAT_MESSAGE_WITH_ID(id, fmt) "[XKB-%03d] " fmt, id #define PREPEND_MESSAGE_ID(id, fmt) JOIN(FORMAT_MESSAGE_, CHECK_ID(id))(id, fmt) /** * Set of verbosity levels */ enum xkb_log_verbosity { XKB_LOG_VERBOSITY_SILENT = -1, XKB_LOG_VERBOSITY_MINIMAL = 0, XKB_LOG_VERBOSITY_BRIEF = 1, XKB_LOG_VERBOSITY_DETAILED = 5, XKB_LOG_VERBOSITY_VERBOSE = 10, XKB_LOG_VERBOSITY_COMPREHENSIVE = 11, XKB_LOG_VERBOSITY_DEFAULT = XKB_LOG_VERBOSITY_MINIMAL, }; /** * Special case when no message identifier is defined. */ #define XKB_LOG_MESSAGE_NO_ID 0 /** * @name Codes of the log messages */ enum xkb_message_code { _XKB_LOG_MESSAGE_MIN_CODE = 34, /** Warn on malformed number literals */ XKB_ERROR_MALFORMED_NUMBER_LITERAL = 34, /** Conflicting “preserve” entries in a key type */ XKB_WARNING_CONFLICTING_KEY_TYPE_PRESERVE_ENTRIES = 43, /** The result of the operation is not mathematically correct */ XKB_ERROR_INTEGER_OVERFLOW = 52, /** Warn on unsupported modifier mask */ XKB_ERROR_UNSUPPORTED_MODIFIER_MASK = 60, /** Expected an array entry, but the index is missing */ XKB_ERROR_EXPECTED_ARRAY_ENTRY = 77, /** Invalid numeric keysym */ XKB_ERROR_INVALID_NUMERIC_KEYSYM = 82, /** Illegal keycode alias with the name of a real key */ XKB_WARNING_ILLEGAL_KEYCODE_ALIAS = 101, /** Warn on unrecognized keysyms */ XKB_WARNING_UNRECOGNIZED_KEYSYM = 107, /** A virtual modifier is used before being declared */ XKB_ERROR_UNDECLARED_VIRTUAL_MODIFIER = 123, /** A buffer has an insufficient size */ XKB_ERROR_INSUFFICIENT_BUFFER_SIZE = 134, /** The type of the statement is not allowed in the context */ XKB_ERROR_WRONG_STATEMENT_TYPE = 150, /** The given path is invalid */ XKB_ERROR_INVALID_PATH = 161, /** Geometry sections are not supported */ XKB_WARNING_UNSUPPORTED_GEOMETRY_SECTION = 172, /** Warn if no key type can be inferred */ XKB_WARNING_CANNOT_INFER_KEY_TYPE = 183, /** Invalid escape sequence in a string */ XKB_WARNING_INVALID_ESCAPE_SEQUENCE = 193, /** The result of a key type “preserve” entry must be a subset of its input modifiers. */ XKB_WARNING_ILLEGAL_KEY_TYPE_PRESERVE_RESULT = 195, /** Syntax error in the include statement */ XKB_ERROR_INVALID_INCLUDE_STATEMENT = 203, /** A modmap entry is invalid */ XKB_ERROR_INVALID_MODMAP_ENTRY = 206, /** Warn when a group index is not supported */ XKB_ERROR_UNSUPPORTED_GROUP_INDEX = 237, /** The name of a key type level is defined multiple times. */ XKB_WARNING_CONFLICTING_KEY_TYPE_LEVEL_NAMES = 239, /** Invalid statement setting default values */ XKB_ERROR_INVALID_SET_DEFAULT_STATEMENT = 254, /** Conflicting “map” entries in type definition */ XKB_WARNING_CONFLICTING_KEY_TYPE_MAP_ENTRY = 266, /** Warn if using an undefined key type */ XKB_WARNING_UNDEFINED_KEY_TYPE = 286, /** A keysym has been deprecated: consider using an alternative keysym */ XKB_WARNING_DEPRECATED_KEYSYM = 301, /** A keysym name has been deprecated: use the corresponding canonical name instead */ XKB_WARNING_DEPRECATED_KEYSYM_NAME = 302, /** Warn if a group name was defined for group other than the first one */ XKB_WARNING_NON_BASE_GROUP_NAME = 305, /** Warn when a shift level is not supported */ XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL = 312, /** Could not find a file used in an include statement */ XKB_ERROR_INCLUDED_FILE_NOT_FOUND = 338, /** Use of an operator that is unknown and thus unsupported */ XKB_ERROR_UNKNOWN_OPERATOR = 345, /** Use of a legacy X11 action that is not supported */ XKB_WARNING_UNSUPPORTED_LEGACY_ACTION = 362, /** An entry is duplicated and will be ignored */ XKB_WARNING_DUPLICATE_ENTRY = 378, /** Included files form cycle */ XKB_ERROR_RECURSIVE_INCLUDE = 386, /** Conflicting definitions of a key type */ XKB_WARNING_CONFLICTING_KEY_TYPE_DEFINITIONS = 407, /** A global defaults statement is in a wrong scope and should be moved */ XKB_ERROR_GLOBAL_DEFAULTS_WRONG_SCOPE = 428, /** Missing default section in included file */ XKB_WARNING_MISSING_DEFAULT_SECTION = 433, /** Warn if there are conflicting keysyms while merging keys */ XKB_WARNING_CONFLICTING_KEY_SYMBOL = 461, /** The operation is invalid in the context */ XKB_ERROR_INVALID_OPERATION = 478, /** Warn on numeric keysym (other than 0-9) */ XKB_WARNING_NUMERIC_KEYSYM = 489, /** TODO: add description */ XKB_WARNING_EXTRA_SYMBOLS_IGNORED = 516, /** Conflicting definitions of a key name or alias */ XKB_WARNING_CONFLICTING_KEY_NAME = 523, /** Invalid file encoding */ XKB_ERROR_INVALID_FILE_ENCODING = 542, /** Cannot allocate memory */ XKB_ERROR_ALLOCATION_ERROR = 550, /** Unknown or unsupported action field */ XKB_ERROR_INVALID_ACTION_FIELD = 563, /** Warn when a field has not the expected type */ XKB_ERROR_WRONG_FIELD_TYPE = 578, /** Cannot resolve a given (Rules, Model, Layout, Variant, Options) configuration */ XKB_ERROR_CANNOT_RESOLVE_RMLVO = 595, /** Invalid Unicode escape sequence */ XKB_WARNING_INVALID_UNICODE_ESCAPE_SEQUENCE = 607, /** Invalid _real_ modifier */ XKB_ERROR_INVALID_REAL_MODIFIER = 623, /** Cannot set default value to a an unknown field */ XKB_ERROR_UNKNOWN_DEFAULT_FIELD = 639, /** Warn on unknown escape sequence in string literal */ XKB_WARNING_UNKNOWN_CHAR_ESCAPE_SEQUENCE = 645, /** The target file of an include statement could not be processed */ XKB_ERROR_INVALID_INCLUDED_FILE = 661, /** Invalid locale for Compose */ XKB_ERROR_INVALID_COMPOSE_LOCALE = 679, /** The Compose file syntax is invalid and the entry cannot be parsed */ XKB_ERROR_INVALID_COMPOSE_SYNTAX = 685, /** A level has a different number of keysyms and actions */ XKB_ERROR_INCOMPATIBLE_ACTIONS_AND_KEYSYMS_COUNT = 693, /** Warn if a key defines multiple groups at once */ XKB_WARNING_MULTIPLE_GROUPS_AT_ONCE = 700, /** A legacy X11 symbol field is not supported */ XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD = 711, /** The keymap has features unsupported in the target format */ XKB_ERROR_INCOMPATIBLE_KEYMAP_TEXT_FORMAT = 742, /** Cannot expand `%%i`: missing layout or variant in MLVO rule fields */ XKB_ERROR_RULES_INVALID_LAYOUT_INDEX_PERCENT_EXPANSION = 762, /** The XKB syntax is invalid and the file cannot be parsed */ XKB_ERROR_INVALID_XKB_SYNTAX = 769, /** Reference to an undefined keycode */ XKB_WARNING_UNDEFINED_KEYCODE = 770, /** An expression has not the expected type */ XKB_ERROR_INVALID_EXPRESSION_TYPE = 784, /** A value is invalid and will be ignored */ XKB_ERROR_INVALID_VALUE = 796, /** Warn if there are conflicting modmap definitions */ XKB_WARNING_CONFLICTING_MODMAP = 800, /** A field is unknown and will be ignored */ XKB_ERROR_UNKNOWN_FIELD = 812, /** Keymap compilation failed */ XKB_ERROR_KEYMAP_COMPILATION_FAILED = 822, /** Unknown action type */ XKB_ERROR_UNKNOWN_ACTION_TYPE = 844, /** Warn if there are conflicting actions while merging keys */ XKB_WARNING_CONFLICTING_KEY_ACTION = 883, /** Warn if there are conflicting key types while merging groups */ XKB_WARNING_CONFLICTING_KEY_TYPE_MERGING_GROUPS = 893, /** Conflicting symbols entry for a key */ XKB_ERROR_CONFLICTING_KEY_SYMBOLS_ENTRY = 901, /** Missing group index in a group name entry */ XKB_WARNING_MISSING_SYMBOLS_GROUP_NAME_INDEX = 903, /** Warn if there are conflicting fields while merging keys */ XKB_WARNING_CONFLICTING_KEY_FIELDS = 935, /** An identifier is used but is not built-in */ XKB_ERROR_INVALID_IDENTIFIER = 949, /** Warn if using a symbol not defined in the keymap */ XKB_WARNING_UNRESOLVED_KEYMAP_SYMBOL = 965, /** The rules syntax is invalid and the file cannot be parsed */ XKB_ERROR_INVALID_RULES_SYNTAX = 967, /** Some modifiers used in a key type “map” or “preserve” entry are not declared */ XKB_WARNING_UNDECLARED_MODIFIERS_IN_KEY_TYPE = 971, _XKB_LOG_MESSAGE_MAX_CODE = 971 }; typedef uint32_t xkb_message_code_t; xkbcommon-libxkbcommon-54ee7ac/src/messages-codes.h.jinja000066400000000000000000000037651510033435100236320ustar00rootroot00000000000000// NOTE: This file has been generated automatically by “{{script}}”. // Do not edit manually! #pragma once #include "config.h" #include /* * Macro sorcery: PREPEND_MESSAGE_ID enables the log functions to format messages * with the message ID only if the ID is not 0 (XKB_LOG_MESSAGE_NO_ID). * This avoid checking the ID value at run time. * * The trick resides in CHECK_ID: * • CHECK_ID(0) expands to: * ‣ SECOND(MATCH0, WITH_ID, unused) * ‣ SECOND(unused,WITHOUT_ID, WITH_ID, unused) * ‣ WITHOUT_ID * • CHECK_ID(123) expands to: * ‣ SECOND(MATCH123, WITH_ID, unused) * ‣ WITH_ID */ #define EXPAND(...) __VA_ARGS__ /* needed for MSVC compatibility */ #define JOIN_EXPAND(a, b) a##b #define JOIN(a, b) JOIN_EXPAND(a, b) #define SECOND_EXPAND(a, b, ...) b #define SECOND(...) EXPAND(SECOND_EXPAND(__VA_ARGS__)) #define MATCH0 unused,WITHOUT_ID #define CHECK_ID(value) SECOND(JOIN(MATCH, value), WITH_ID, unused) #define FORMAT_MESSAGE_WITHOUT_ID(id, fmt) fmt #define FORMAT_MESSAGE_WITH_ID(id, fmt) "[XKB-%03d] " fmt, id #define PREPEND_MESSAGE_ID(id, fmt) JOIN(FORMAT_MESSAGE_, CHECK_ID(id))(id, fmt) /** * Set of verbosity levels */ enum xkb_log_verbosity { XKB_LOG_VERBOSITY_SILENT = -1, XKB_LOG_VERBOSITY_MINIMAL = 0, XKB_LOG_VERBOSITY_BRIEF = 1, XKB_LOG_VERBOSITY_DETAILED = 5, XKB_LOG_VERBOSITY_VERBOSE = 10, XKB_LOG_VERBOSITY_COMPREHENSIVE = 11, XKB_LOG_VERBOSITY_DEFAULT = XKB_LOG_VERBOSITY_MINIMAL, }; /** * Special case when no message identifier is defined. */ #define XKB_LOG_MESSAGE_NO_ID 0 /** * @name Codes of the log messages */ enum xkb_message_code { _XKB_LOG_MESSAGE_MIN_CODE = {{ entries[0].code }}, {% for entry in entries %} /** {{ entry.description }} */ {{ entry.message_code_constant }} = {{ entry.code }}, {% endfor %} _XKB_LOG_MESSAGE_MAX_CODE = {{ entries[-1].code }} }; typedef uint32_t xkb_message_code_t; xkbcommon-libxkbcommon-54ee7ac/src/registry.c000066400000000000000000001172231510033435100214740ustar00rootroot00000000000000/* * Copyright © 2020 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include #include #include "xkbcommon/xkbregistry.h" #include "messages-codes.h" #include "utils.h" #include "util-list.h" #include "util-mem.h" struct rxkb_object; /** * All our objects are refcounted and are linked to iterate through them. * Abstract those bits away into a shared parent class so we can generate * most of the functions through macros. */ struct rxkb_object { struct rxkb_object *parent; uint32_t refcount; struct list link; }; struct rxkb_iso639_code { struct rxkb_object base; char *code; }; struct rxkb_iso3166_code { struct rxkb_object base; char *code; }; enum context_state { CONTEXT_NEW, CONTEXT_PARSED, CONTEXT_FAILED, }; struct rxkb_context { struct rxkb_object base; enum context_state context_state; bool load_extra_rules_files; bool use_secure_getenv; struct list models; /* list of struct rxkb_models */ struct list layouts; /* list of struct rxkb_layouts */ struct list option_groups; /* list of struct rxkb_option_group */ darray(char *) includes; ATTR_PRINTF(3, 0) void (*log_fn)(struct rxkb_context *ctx, enum rxkb_log_level level, const char *fmt, va_list args); enum rxkb_log_level log_level; void *userdata; }; struct rxkb_model { struct rxkb_object base; char *name; char *vendor; char *description; enum rxkb_popularity popularity; }; struct rxkb_layout { struct rxkb_object base; char *name; char *brief; char *description; char *variant; enum rxkb_popularity popularity; struct list iso639s; /* list of struct rxkb_iso639_code */ struct list iso3166s; /* list of struct rxkb_iso3166_code */ }; struct rxkb_option_group { struct rxkb_object base; bool allow_multiple; struct list options; /* list of struct rxkb_options */ char *name; char *description; enum rxkb_popularity popularity; }; struct rxkb_option { struct rxkb_object base; char *name; char *brief; char *description; enum rxkb_popularity popularity; bool layout_specific; }; static bool parse(struct rxkb_context *ctx, const char *path, enum rxkb_popularity popularity); ATTR_PRINTF(3, 4) static void rxkb_log(struct rxkb_context *ctx, enum rxkb_log_level level, const char *fmt, ...) { va_list args; if (ctx->log_level < level) return; va_start(args, fmt); ctx->log_fn(ctx, level, fmt, args); va_end(args); } /* * The format is not part of the argument list in order to avoid the * "ISO C99 requires rest arguments to be used" warning when only the * format is supplied without arguments. Not supplying it would still * result in an error, though. */ #define rxkb_log_with_code(ctx, level, msg_id, fmt, ...) \ rxkb_log(ctx, level, PREPEND_MESSAGE_ID(msg_id, fmt), ##__VA_ARGS__) #define log_dbg(ctx, ...) \ rxkb_log((ctx), RXKB_LOG_LEVEL_DEBUG, __VA_ARGS__) #define log_info(ctx, id, ...) \ rxkb_log_with_code((ctx), RXKB_LOG_LEVEL_INFO, id, __VA_ARGS__) #define log_warn(ctx, id, ...) \ rxkb_log_with_code((ctx), RXKB_LOG_LEVEL_WARNING, id, __VA_ARGS__) #define log_err(ctx, id, ...) \ rxkb_log_with_code((ctx), RXKB_LOG_LEVEL_ERROR, id, __VA_ARGS__) #define log_wsgo(ctx, id, ...) \ rxkb_log_with_code((ctx), RXKB_LOG_LEVEL_CRITICAL, id, __VA_ARGS__) #define DECLARE_REF_UNREF_FOR_TYPE(type_) \ struct type_ * type_##_ref(struct type_ *object) { \ rxkb_object_ref(&object->base); \ return object; \ } \ struct type_ * type_##_unref(struct type_ *object) { \ if (!object) return NULL; \ assert(object->base.refcount >= 1); \ if (--object->base.refcount == 0) {\ type_##_destroy(object); \ list_remove(&object->base.link);\ free(object); \ } \ return NULL;\ } #define DECLARE_CREATE_FOR_TYPE(type_) \ static inline struct type_ * type_##_create(struct rxkb_object *parent) { \ struct type_ *t = calloc(1, sizeof *t); \ if (t) \ rxkb_object_init(&t->base, parent); \ return t; \ } #define DECLARE_TYPED_GETTER_FOR_TYPE(type_, field_, rtype_) \ rtype_ type_##_get_##field_(struct type_ *object) { \ return object->field_; \ } #define DECLARE_GETTER_FOR_TYPE(type_, field_) \ DECLARE_TYPED_GETTER_FOR_TYPE(type_, field_, const char*) #define DECLARE_FIRST_NEXT_FOR_TYPE(type_, parent_type_, parent_field_) \ struct type_ * type_##_first(struct parent_type_ *parent) { \ struct type_ *o = NULL; \ if (!list_empty(&parent->parent_field_)) \ o = list_first_entry(&parent->parent_field_, o, base.link); \ return o; \ } \ struct type_ * \ type_##_next(struct type_ *o) \ { \ struct parent_type_ *parent; \ struct type_ *next; \ parent = container_of(o->base.parent, struct parent_type_, base); \ next = list_first_entry(&o->base.link, o, base.link); \ if (list_is_last(&parent->parent_field_, &o->base.link)) \ return NULL; \ return next; \ } static void rxkb_object_init(struct rxkb_object *object, struct rxkb_object *parent) { object->refcount = 1; object->parent = parent; list_init(&object->link); } static void * rxkb_object_ref(struct rxkb_object *object) { assert(object->refcount >= 1); ++object->refcount; return object; } static void rxkb_iso639_code_destroy(struct rxkb_iso639_code *code) { free(code->code); } struct rxkb_iso639_code * rxkb_layout_get_iso639_first(struct rxkb_layout *layout) { struct rxkb_iso639_code *code = NULL; if (!list_empty(&layout->iso639s)) code = list_first_entry(&layout->iso639s, code, base.link); return code; } struct rxkb_iso639_code * rxkb_iso639_code_next(struct rxkb_iso639_code *code) { struct rxkb_iso639_code *next = NULL; struct rxkb_layout *layout; layout = container_of(code->base.parent, struct rxkb_layout, base); if (list_is_last(&layout->iso639s, &code->base.link)) return NULL; next = list_first_entry(&code->base.link, code, base.link); return next; } DECLARE_REF_UNREF_FOR_TYPE(rxkb_iso639_code); DECLARE_CREATE_FOR_TYPE(rxkb_iso639_code); DECLARE_GETTER_FOR_TYPE(rxkb_iso639_code, code); static void rxkb_iso3166_code_destroy(struct rxkb_iso3166_code *code) { free(code->code); } struct rxkb_iso3166_code * rxkb_layout_get_iso3166_first(struct rxkb_layout *layout) { struct rxkb_iso3166_code *code = NULL; if (!list_empty(&layout->iso3166s)) code = list_first_entry(&layout->iso3166s, code, base.link); return code; } struct rxkb_iso3166_code * rxkb_iso3166_code_next(struct rxkb_iso3166_code *code) { struct rxkb_iso3166_code *next = NULL; struct rxkb_layout *layout; layout = container_of(code->base.parent, struct rxkb_layout, base); if (list_is_last(&layout->iso3166s, &code->base.link)) return NULL; next = list_first_entry(&code->base.link, code, base.link); return next; } DECLARE_REF_UNREF_FOR_TYPE(rxkb_iso3166_code); DECLARE_CREATE_FOR_TYPE(rxkb_iso3166_code); DECLARE_GETTER_FOR_TYPE(rxkb_iso3166_code, code); static void rxkb_option_destroy(struct rxkb_option *o) { free(o->name); free(o->brief); free(o->description); } DECLARE_REF_UNREF_FOR_TYPE(rxkb_option); DECLARE_CREATE_FOR_TYPE(rxkb_option); DECLARE_GETTER_FOR_TYPE(rxkb_option, name); DECLARE_GETTER_FOR_TYPE(rxkb_option, brief); DECLARE_GETTER_FOR_TYPE(rxkb_option, description); DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_option, popularity, enum rxkb_popularity); bool rxkb_option_is_layout_specific(struct rxkb_option *object) { return object->layout_specific; } DECLARE_FIRST_NEXT_FOR_TYPE(rxkb_option, rxkb_option_group, options); static void rxkb_layout_destroy(struct rxkb_layout *l) { struct rxkb_iso639_code *iso639, *tmp_639; struct rxkb_iso3166_code *iso3166, *tmp_3166; free(l->name); free(l->brief); free(l->description); free(l->variant); list_for_each_safe(iso639, tmp_639, &l->iso639s, base.link) { rxkb_iso639_code_unref(iso639); } list_for_each_safe(iso3166, tmp_3166, &l->iso3166s, base.link) { rxkb_iso3166_code_unref(iso3166); } } DECLARE_REF_UNREF_FOR_TYPE(rxkb_layout); DECLARE_CREATE_FOR_TYPE(rxkb_layout); DECLARE_GETTER_FOR_TYPE(rxkb_layout, name); DECLARE_GETTER_FOR_TYPE(rxkb_layout, brief); DECLARE_GETTER_FOR_TYPE(rxkb_layout, description); DECLARE_GETTER_FOR_TYPE(rxkb_layout, variant); DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_layout, popularity, enum rxkb_popularity); DECLARE_FIRST_NEXT_FOR_TYPE(rxkb_layout, rxkb_context, layouts); static void rxkb_model_destroy(struct rxkb_model *m) { free(m->name); free(m->vendor); free(m->description); } DECLARE_REF_UNREF_FOR_TYPE(rxkb_model); DECLARE_CREATE_FOR_TYPE(rxkb_model); DECLARE_GETTER_FOR_TYPE(rxkb_model, name); DECLARE_GETTER_FOR_TYPE(rxkb_model, vendor); DECLARE_GETTER_FOR_TYPE(rxkb_model, description); DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_model, popularity, enum rxkb_popularity); DECLARE_FIRST_NEXT_FOR_TYPE(rxkb_model, rxkb_context, models); static void rxkb_option_group_destroy(struct rxkb_option_group *og) { struct rxkb_option *o, *otmp; free(og->name); free(og->description); list_for_each_safe(o, otmp, &og->options, base.link) { rxkb_option_unref(o); } } bool rxkb_option_group_allows_multiple(struct rxkb_option_group *g) { return g->allow_multiple; } DECLARE_REF_UNREF_FOR_TYPE(rxkb_option_group); DECLARE_CREATE_FOR_TYPE(rxkb_option_group); DECLARE_GETTER_FOR_TYPE(rxkb_option_group, name); DECLARE_GETTER_FOR_TYPE(rxkb_option_group, description); DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_option_group, popularity, enum rxkb_popularity); DECLARE_FIRST_NEXT_FOR_TYPE(rxkb_option_group, rxkb_context, option_groups); static void rxkb_context_destroy(struct rxkb_context *ctx) { struct rxkb_model *m, *mtmp; struct rxkb_layout *l, *ltmp; struct rxkb_option_group *og, *ogtmp; char **path; list_for_each_safe(m, mtmp, &ctx->models, base.link) rxkb_model_unref(m); assert(list_empty(&ctx->models)); list_for_each_safe(l, ltmp, &ctx->layouts, base.link) rxkb_layout_unref(l); assert(list_empty(&ctx->layouts)); list_for_each_safe(og, ogtmp, &ctx->option_groups, base.link) rxkb_option_group_unref(og); assert(list_empty(&ctx->option_groups)); darray_foreach(path, ctx->includes) free(*path); darray_free(ctx->includes); assert(darray_empty(ctx->includes)); } DECLARE_REF_UNREF_FOR_TYPE(rxkb_context); DECLARE_CREATE_FOR_TYPE(rxkb_context); DECLARE_TYPED_GETTER_FOR_TYPE(rxkb_context, log_level, enum rxkb_log_level); static char * rxkb_context_getenv(struct rxkb_context *ctx, const char *name) { if (ctx->use_secure_getenv) { return secure_getenv(name); } else { return getenv(name); } } void rxkb_context_set_log_level(struct rxkb_context *ctx, enum rxkb_log_level level) { ctx->log_level = level; } static const char * log_level_to_prefix(enum rxkb_log_level level) { switch (level) { case RXKB_LOG_LEVEL_DEBUG: return "xkbregistry: DEBUG: "; case RXKB_LOG_LEVEL_INFO: return "xkbregistry: INFO: "; case RXKB_LOG_LEVEL_WARNING: return "xkbregistry: WARNING: "; case RXKB_LOG_LEVEL_ERROR: return "xkbregistry: ERROR: "; case RXKB_LOG_LEVEL_CRITICAL: return "xkbregistry: CRITICAL: "; default: return NULL; } } ATTR_PRINTF(3, 0) static void default_log_fn(struct rxkb_context *ctx, enum rxkb_log_level level, const char *fmt, va_list args) { const char *prefix = log_level_to_prefix(level); if (prefix) fprintf(stderr, "%s", prefix); vfprintf(stderr, fmt, args); } static enum rxkb_log_level log_level(const char *level) { char *endptr; enum rxkb_log_level lvl; errno = 0; lvl = strtol(level, &endptr, 10); if (errno == 0 && (endptr[0] == '\0' || is_space(endptr[0]))) return lvl; if (istreq_prefix("crit", level)) return RXKB_LOG_LEVEL_CRITICAL; if (istreq_prefix("err", level)) return RXKB_LOG_LEVEL_ERROR; if (istreq_prefix("warn", level)) return RXKB_LOG_LEVEL_WARNING; if (istreq_prefix("info", level)) return RXKB_LOG_LEVEL_INFO; if (istreq_prefix("debug", level) || istreq_prefix("dbg", level)) return RXKB_LOG_LEVEL_DEBUG; return RXKB_LOG_LEVEL_ERROR; } struct rxkb_context * rxkb_context_new(enum rxkb_context_flags flags) { struct rxkb_context *ctx = rxkb_context_create(NULL); const char *env; if (!ctx) return NULL; ctx->context_state = CONTEXT_NEW; ctx->load_extra_rules_files = flags & RXKB_CONTEXT_LOAD_EXOTIC_RULES; ctx->use_secure_getenv = !(flags & RXKB_CONTEXT_NO_SECURE_GETENV); ctx->log_fn = default_log_fn; ctx->log_level = RXKB_LOG_LEVEL_ERROR; /* Environment overwrites defaults. */ env = rxkb_context_getenv(ctx, "RXKB_LOG_LEVEL"); if (env) rxkb_context_set_log_level(ctx, log_level(env)); list_init(&ctx->models); list_init(&ctx->layouts); list_init(&ctx->option_groups); if (!(flags & RXKB_CONTEXT_NO_DEFAULT_INCLUDES) && !rxkb_context_include_path_append_default(ctx)) { rxkb_context_unref(ctx); return NULL; } return ctx; } void rxkb_context_set_log_fn(struct rxkb_context *ctx, void (*log_fn)(struct rxkb_context *ctx, enum rxkb_log_level level, const char *fmt, va_list args)) { ctx->log_fn = (log_fn ? log_fn : default_log_fn); } bool rxkb_context_include_path_append(struct rxkb_context *ctx, const char *path) { int err = 0; if (ctx->context_state != CONTEXT_NEW) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "include paths can only be appended to a new context\n"); goto error; } struct stat stat_buf; err = stat(path, &stat_buf); if (err != 0) { err = errno; goto error; } if (!S_ISDIR(stat_buf.st_mode)) { err = ENOTDIR; goto error; } if (!check_eaccess(path, R_OK | X_OK)) { err = EACCES; goto error; } /* * Pre-filter for the 99.9% case - if we can’t assemble the default ruleset * path, complain here instead of during parsing later. The niche cases * where this is the wrong behaviour aren’t worth worrying about. */ char rules[PATH_MAX]; if (!snprintf_safe(rules, sizeof(rules), "%s/rules/%s.xml", path, DEFAULT_XKB_RULES)) { log_err(ctx, XKB_ERROR_INVALID_PATH, "Path is too long: expected max length of %zu, " "got: %s/rules/%s.xml\n", sizeof(rules), path, DEFAULT_XKB_RULES); goto error; } char * const tmp = strdup(path); if (!tmp) { err = ENOMEM; goto error; } darray_append(ctx->includes, tmp); /* Use “info” log level to facilate bug reporting. */ log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "Include path added: %s\n", tmp); return true; error: /* * This error is not fatal because some valid paths may still be defined. * Use “info” log level to facilate bug reporting. */ log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "Include path failed: \"%s\" (%s)\n", path, strerror(err)); return false; } bool rxkb_context_include_path_append_default(struct rxkb_context *ctx) { char user_path[PATH_MAX]; bool ret = false; if (ctx->context_state != CONTEXT_NEW) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "include paths can only be appended to a new context\n"); return false; } const char * const home = rxkb_context_getenv(ctx, "HOME"); const char * const xdg = rxkb_context_getenv(ctx, "XDG_CONFIG_HOME"); /* Accept empty string, which may be unintentional and should be reported */ if (xdg != NULL) { if (snprintf_safe(user_path, sizeof(user_path), "%s/xkb", xdg)) ret |= rxkb_context_include_path_append(ctx, user_path); } else if (home != NULL) { /* XDG_CONFIG_HOME fallback is $HOME/.config/ */ if (snprintf_safe(user_path, sizeof(user_path), "%s/.config/xkb", home)) ret |= rxkb_context_include_path_append(ctx, user_path); } if (home != NULL) { if (snprintf_safe(user_path, sizeof(user_path), "%s/.xkb", home)) ret |= rxkb_context_include_path_append(ctx, user_path); } const char * const extra = rxkb_context_getenv(ctx, "XKB_CONFIG_EXTRA_PATH"); /* * Only use default if path is undefined, but accept empty string, which may * be unintentional and should be reported. */ ret |= rxkb_context_include_path_append( ctx, ((extra != NULL) ? extra : DFLT_XKB_CONFIG_EXTRA_PATH) ); /* Canonical XKB root */ const char * const root = rxkb_context_getenv(ctx, "XKB_CONFIG_ROOT"); /* * Only use default if path is undefined, but accept empty string, which may * be unintentional and should be reported. */ const bool has_root = rxkb_context_include_path_append( ctx, ((root != NULL) ? root: DFLT_XKB_CONFIG_ROOT) ); ret |= has_root; /* * Fallback for misconfigured setups. * Some setups use the assumption that the canonical XKB root is always the * legacy X11 one, but this is no longer true since xkeyboard-config 2.45, * where the X11 path is now a mere symlink to a dedicated xkeyboard-config * data directory. * This fallback can still be skipped if deliberately using an empty string * for the canonical XKB root hereinabove. */ if (!has_root && (root == NULL || root[0] != '\0')) { log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "Root include path failed; fallback to \"%s\". " "The setup is probably misconfigured. " "Please ensure that \"%s\" is available in the environment.\n", DFLT_XKB_LEGACY_ROOT, ((root == NULL) ? DFLT_XKB_CONFIG_ROOT : root)); ret |= rxkb_context_include_path_append(ctx, DFLT_XKB_LEGACY_ROOT); } return ret; } bool rxkb_context_parse_default_ruleset(struct rxkb_context *ctx) { return rxkb_context_parse(ctx, DEFAULT_XKB_RULES); } bool rxkb_context_parse(struct rxkb_context *ctx, const char *ruleset) { char **path; bool success = false; if (ctx->context_state != CONTEXT_NEW) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "parse must only be called on a new context\n"); return false; } darray_foreach_reverse(path, ctx->includes) { char rules[PATH_MAX]; if (snprintf_safe(rules, sizeof(rules), "%s/rules/%s.xml", *path, ruleset)) { log_dbg(ctx, "Parsing %s\n", rules); if (parse(ctx, rules, RXKB_POPULARITY_STANDARD)) success = true; } if (ctx->load_extra_rules_files && snprintf_safe(rules, sizeof(rules), "%s/rules/%s.extras.xml", *path, ruleset)) { log_dbg(ctx, "Parsing %s\n", rules); if (parse(ctx, rules, RXKB_POPULARITY_EXOTIC)) success = true; } } ctx->context_state = success ? CONTEXT_PARSED : CONTEXT_FAILED; return success; } void rxkb_context_set_user_data(struct rxkb_context *ctx, void *userdata) { ctx->userdata = userdata; } void * rxkb_context_get_user_data(struct rxkb_context *ctx) { return ctx->userdata; } static inline bool is_node(xmlNode *node, const char *name) { return node->type == XML_ELEMENT_NODE && xmlStrEqual(node->name, (const xmlChar*)name); } /* return a copy of the text content from the first text node of this node */ static char * extract_text(xmlNode *node) { xmlNode *n; for (n = node->children; n; n = n->next) { if (n->type == XML_TEXT_NODE) return (char *)xmlStrdup(n->content); } return NULL; } /* Data from “configItem” node */ struct config_item { char *name; char *description; char *brief; char *vendor; enum rxkb_popularity popularity; bool layout_specific; }; #define config_item_new(popularity_) { \ .name = NULL, \ .description = NULL, \ .brief = NULL, \ .vendor = NULL, \ .popularity = (popularity_), \ .layout_specific = false \ } static void config_item_free(struct config_item *config) { free(config->name); free(config->description); free(config->brief); free(config->vendor); } static bool parse_config_item(struct rxkb_context *ctx, xmlNode *parent, struct config_item *config) { xmlNode *node = NULL; xmlNode *ci = NULL; for (ci = parent->children; ci; ci = ci->next) { if (is_node(ci, "configItem")) { /* Process attributes */ xmlChar *raw_popularity = xmlGetProp(ci, (const xmlChar*)"popularity"); if (raw_popularity) { if (xmlStrEqual(raw_popularity, (const xmlChar*)"standard")) config->popularity = RXKB_POPULARITY_STANDARD; else if (xmlStrEqual(raw_popularity, (const xmlChar*)"exotic")) config->popularity = RXKB_POPULARITY_EXOTIC; else log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "xml:%u: invalid popularity attribute: expected " "'standard' or 'exotic', got: '%s'\n", ci->line, raw_popularity); } xmlFree(raw_popularity); /* Note: this is only useful for options */ xmlChar *raw_layout_specific = xmlGetProp(ci, (const xmlChar*)"layout-specific"); if (raw_layout_specific && xmlStrEqual(raw_layout_specific, (const xmlChar*)"true")) config->layout_specific = true; xmlFree(raw_layout_specific); /* Process children */ for (node = ci->children; node; node = node->next) { if (is_node(node, "name")) config->name = extract_text(node); else if (is_node(node, "description")) config->description = extract_text(node); else if (is_node(node, "shortDescription")) config->brief = extract_text(node); else if (is_node(node, "vendor")) config->vendor = extract_text(node); /* Note: the DTD allows for vendor + brief but models only use * vendor and everything else only uses shortDescription */ } if (!config->name || !strlen(config->name)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "xml:%u: missing required element 'name'\n", ci->line); config_item_free(config); return false; } return true; /* only one configItem allowed in the dtd */ } } return false; } static void parse_model(struct rxkb_context *ctx, xmlNode *model, enum rxkb_popularity popularity) { struct config_item config = config_item_new(popularity); if (parse_config_item(ctx, model, &config)) { struct rxkb_model *m; list_for_each(m, &ctx->models, base.link) { if (streq(m->name, config.name)) { config_item_free(&config); return; } } /* new model */ m = rxkb_model_create(&ctx->base); m->name = steal(&config.name); m->description = steal(&config.description); m->vendor = steal(&config.vendor); m->popularity = config.popularity; list_append(&ctx->models, &m->base.link); } } static void parse_model_list(struct rxkb_context *ctx, xmlNode *model_list, enum rxkb_popularity popularity) { xmlNode *node = NULL; for (node = model_list->children; node; node = node->next) { if (is_node(node, "model")) parse_model(ctx, node, popularity); } } static void parse_language_list(xmlNode *language_list, struct rxkb_layout *layout) { xmlNode *node = NULL; struct rxkb_iso639_code *code; for (node = language_list->children; node; node = node->next) { if (is_node(node, "iso639Id")) { char *str = extract_text(node); struct rxkb_object *parent; if (!str || strlen(str) != 3) { free(str); continue; } parent = &layout->base; code = rxkb_iso639_code_create(parent); code->code = str; list_append(&layout->iso639s, &code->base.link); } } } static void parse_country_list(xmlNode *country_list, struct rxkb_layout *layout) { xmlNode *node = NULL; struct rxkb_iso3166_code *code; for (node = country_list->children; node; node = node->next) { if (is_node(node, "iso3166Id")) { char *str = extract_text(node); struct rxkb_object *parent; if (!str || strlen(str) != 2) { free(str); continue; } parent = &layout->base; code = rxkb_iso3166_code_create(parent); code->code = str; list_append(&layout->iso3166s, &code->base.link); } } } static void parse_variant(struct rxkb_context *ctx, struct rxkb_layout *l, xmlNode *variant, enum rxkb_popularity popularity) { xmlNode *ci; struct config_item config = config_item_new(popularity); if (parse_config_item(ctx, variant, &config)) { struct rxkb_layout *v; bool exists = false; list_for_each(v, &ctx->layouts, base.link) { if (streq_null(v->variant, config.name) && streq(v->name, l->name)) { exists = true; break; } } if (!exists) { v = rxkb_layout_create(&ctx->base); list_init(&v->iso639s); list_init(&v->iso3166s); v->name = strdup(l->name); v->variant = steal(&config.name); v->description = steal(&config.description); // if variant omits brief, inherit from parent layout. v->brief = config.brief == NULL ? strdup_safe(l->brief) : steal(&config.brief); v->popularity = config.popularity; list_append(&ctx->layouts, &v->base.link); for (ci = variant->children; ci; ci = ci->next) { xmlNode *node; if (!is_node(ci, "configItem")) continue; bool found_language_list = false; bool found_country_list = false; for (node = ci->children; node; node = node->next) { if (is_node(node, "languageList")) { parse_language_list(node, v); found_language_list = true; } if (is_node(node, "countryList")) { parse_country_list(node, v); found_country_list = true; } } if (!found_language_list) { // inherit from parent layout struct rxkb_iso639_code* x; list_for_each(x, &l->iso639s, base.link) { struct rxkb_iso639_code* code = rxkb_iso639_code_create(&v->base); code->code = strdup(x->code); list_append(&v->iso639s, &code->base.link); } } if (!found_country_list) { // inherit from parent layout struct rxkb_iso3166_code* x; list_for_each(x, &l->iso3166s, base.link) { struct rxkb_iso3166_code* code = rxkb_iso3166_code_create(&v->base); code->code = strdup(x->code); list_append(&v->iso3166s, &code->base.link); } } } } else { config_item_free(&config); } } } static void parse_variant_list(struct rxkb_context *ctx, struct rxkb_layout *l, xmlNode *variant_list, enum rxkb_popularity popularity) { xmlNode *node = NULL; for (node = variant_list->children; node; node = node->next) { if (is_node(node, "variant")) parse_variant(ctx, l, node, popularity); } } static void parse_layout(struct rxkb_context *ctx, xmlNode *layout, enum rxkb_popularity popularity) { struct config_item config = config_item_new(popularity); struct rxkb_layout *l; xmlNode *node = NULL; bool exists = false; if (!parse_config_item(ctx, layout, &config)) return; list_for_each(l, &ctx->layouts, base.link) { if (streq(l->name, config.name) && l->variant == NULL) { exists = true; break; } } if (!exists) { l = rxkb_layout_create(&ctx->base); list_init(&l->iso639s); list_init(&l->iso3166s); l->name = steal(&config.name); l->variant = NULL; l->description = steal(&config.description); l->brief = steal(&config.brief); l->popularity = config.popularity; list_append(&ctx->layouts, &l->base.link); } else { config_item_free(&config); } for (node = layout->children; node; node = node->next) { if (is_node(node, "variantList")) { parse_variant_list(ctx, l, node, popularity); } if (!exists && is_node(node, "configItem")) { xmlNode *ll; for (ll = node->children; ll; ll = ll->next) { if (is_node(ll, "languageList")) parse_language_list(ll, l); if (is_node(ll, "countryList")) parse_country_list(ll, l); } } } } static void parse_layout_list(struct rxkb_context *ctx, xmlNode *layout_list, enum rxkb_popularity popularity) { xmlNode *node = NULL; for (node = layout_list->children; node; node = node->next) { if (is_node(node, "layout")) parse_layout(ctx, node, popularity); } } static void parse_option(struct rxkb_context *ctx, struct rxkb_option_group *group, xmlNode *option, enum rxkb_popularity popularity) { struct config_item config = config_item_new(popularity); if (parse_config_item(ctx, option, &config)) { struct rxkb_option *o; list_for_each(o, &group->options, base.link) { if (streq(o->name, config.name)) { config_item_free(&config); return; } } o = rxkb_option_create(&group->base); o->name = steal(&config.name); o->description = steal(&config.description); o->popularity = config.popularity; o->layout_specific = config.layout_specific; list_append(&group->options, &o->base.link); } } static void parse_group(struct rxkb_context *ctx, xmlNode *group, enum rxkb_popularity popularity) { struct config_item config = config_item_new(popularity); struct rxkb_option_group *g; xmlNode *node = NULL; xmlChar *multiple; bool exists = false; if (!parse_config_item(ctx, group, &config)) return; list_for_each(g, &ctx->option_groups, base.link) { if (streq(g->name, config.name)) { exists = true; break; } } if (!exists) { g = rxkb_option_group_create(&ctx->base); g->name = steal(&config.name); g->description = steal(&config.description); g->popularity = config.popularity; multiple = xmlGetProp(group, (const xmlChar*)"allowMultipleSelection"); if (multiple && xmlStrEqual(multiple, (const xmlChar*)"true")) g->allow_multiple = true; xmlFree(multiple); list_init(&g->options); list_append(&ctx->option_groups, &g->base.link); } else { config_item_free(&config); } for (node = group->children; node; node = node->next) { if (is_node(node, "option")) parse_option(ctx, g, node, popularity); } } static void parse_option_list(struct rxkb_context *ctx, xmlNode *option_list, enum rxkb_popularity popularity) { xmlNode *node = NULL; for (node = option_list->children; node; node = node->next) { if (is_node(node, "group")) parse_group(ctx, node, popularity); } } static void parse_rules_xml(struct rxkb_context *ctx, xmlNode *root, enum rxkb_popularity popularity) { xmlNode *node = NULL; for (node = root->children; node; node = node->next) { if (is_node(node, "modelList")) parse_model_list(ctx, node, popularity); else if (is_node(node, "layoutList")) parse_layout_list(ctx, node, popularity); else if (is_node(node, "optionList")) parse_option_list(ctx, node, popularity); } } static void ATTR_PRINTF(2, 0) xml_error_func(void *ctx, const char *msg, ...) { static char buf[PATH_MAX]; static int slen = 0; va_list args; int rc; /* libxml2 prints IO errors from bad includes paths by * calling the error function once per word. So we get to * re-assemble the message here and print it when we get * the line break. My enthusiasm about this is indescribable. */ va_start(args, msg); rc = vsnprintf(&buf[slen], sizeof(buf) - slen, msg, args); va_end(args); /* This shouldn't really happen */ if (rc < 0) { log_err(ctx, XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "+++ out of cheese error. redo from start +++\n"); slen = 0; memset(buf, 0, sizeof(buf)); return; } slen += rc; if (slen >= (int)sizeof(buf)) { /* truncated, let's flush this */ buf[sizeof(buf) - 1] = '\n'; slen = sizeof(buf); } /* We're assuming here that the last character is \n. */ if (buf[slen - 1] == '\n') { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "%s", buf); memset(buf, 0, sizeof(buf)); slen = 0; } } #ifdef HAVE_XML_CTXT_SET_ERRORHANDLER static void xml_structured_error_func(void *userData, const xmlError * error) { xmlFormatError(error, xml_error_func, userData); } #endif #ifdef XML_PARSE_NO_XXE #define _XML_OPTIONS (XML_PARSE_NONET | XML_PARSE_NOENT | XML_PARSE_NO_XXE) #else #define _XML_OPTIONS (XML_PARSE_NONET) #endif static bool validate(struct rxkb_context *ctx, xmlDoc *doc) { bool success = false; /* This is a modified version of the xkeyboard-config xkb.dtd: * • xkeyboard-config requires modelList, layoutList and optionList, * but we allow for any of those to be missing. * • xkeyboard-config sets default value of “popularity” to “standard”, * but we set this value depending if we are currently parsing an * “extras” rule file. */ const char dtdstr[] = "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n" "\n"; #ifdef HAVE_XML_CTXT_PARSE_DTD /* Use safer function with context if available, and set * the contextual error handler. */ xmlParserCtxtPtr xmlCtxt = xmlNewParserCtxt(); if (!xmlCtxt) return false; xmlCtxtSetErrorHandler(xmlCtxt, xml_structured_error_func, ctx); xmlCtxtSetOptions(xmlCtxt, _XML_OPTIONS | XML_PARSE_DTDLOAD); xmlParserInputPtr pinput = xmlNewInputFromMemory(NULL, dtdstr, ARRAY_SIZE(dtdstr) - 1, XML_INPUT_BUF_STATIC); if (!pinput) goto dtd_error; xmlDtd *dtd = xmlCtxtParseDtd(xmlCtxt, pinput, NULL, NULL); #else /* Note: do not use xmlParserInputBufferCreateStatic, it generates random * DTD validity errors for unknown reasons */ xmlParserInputBufferPtr buf = xmlParserInputBufferCreateMem(dtdstr, ARRAY_SIZE(dtdstr) - 1, XML_CHAR_ENCODING_NONE); if (!buf) goto dtd_error; xmlDtd *dtd = xmlIOParseDTD(NULL, buf, XML_CHAR_ENCODING_UTF8); #endif if (!dtd) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Failed to load DTD\n"); goto dtd_error; } #ifdef HAVE_XML_CTXT_PARSE_DTD success = xmlCtxtValidateDtd(xmlCtxt, doc, dtd); #else xmlValidCtxt *dtdvalid = xmlNewValidCtxt(); success = xmlValidateDtd(dtdvalid, doc, dtd); if (dtdvalid) xmlFreeValidCtxt(dtdvalid); #endif xmlFreeDtd(dtd); dtd_error: #ifdef HAVE_XML_CTXT_PARSE_DTD xmlFreeParserCtxt(xmlCtxt); #endif return success; } static bool parse(struct rxkb_context *ctx, const char *path, enum rxkb_popularity popularity) { bool success = false; xmlDoc *doc = NULL; xmlNode *root = NULL; if (!check_eaccess(path, R_OK)) return false; LIBXML_TEST_VERSION xmlParserCtxtPtr xmlCtxt = xmlNewParserCtxt(); if (!xmlCtxt) return false; #ifdef XML_PARSE_NO_XXE #define _XML_OPTIONS (XML_PARSE_NONET | XML_PARSE_NOENT | XML_PARSE_NO_XXE) #else #define _XML_OPTIONS (XML_PARSE_NONET) #endif xmlCtxtUseOptions(xmlCtxt, _XML_OPTIONS); #ifdef HAVE_XML_CTXT_SET_ERRORHANDLER /* Prefer contextual handler whenever possible. It takes precedence over * the global generic handler. */ xmlCtxtSetErrorHandler(xmlCtxt, xml_structured_error_func, ctx); #endif #ifndef HAVE_XML_CTXT_PARSE_DTD /* This is needed for the DTD validation */ xmlSetGenericErrorFunc(ctx, xml_error_func); #endif doc = xmlCtxtReadFile(xmlCtxt, path, NULL, 0); if (!doc) goto parse_error; if (!validate(ctx, doc)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "XML error: failed to validate document at %s\n", path); goto validate_error; } root = xmlDocGetRootElement(doc); parse_rules_xml(ctx, root, popularity); success = true; validate_error: xmlFreeDoc(doc); parse_error: #ifndef HAVE_XML_CTXT_PARSE_DTD /* * Reset the default libxml2 error handler to default, because this handler * is global and may be used on an invalid rxkb_context, e.g. *after* the * following sequence: * * rxkb_context_new(); * rxkb_context_parse(); * rxkb_context_unref(); */ xmlSetGenericErrorFunc(NULL, NULL); #endif #ifdef HAVE_XML_CTXT_SET_ERRORHANDLER xmlCtxtSetErrorHandler(xmlCtxt, NULL, NULL); #endif xmlFreeParserCtxt(xmlCtxt); return success; } xkbcommon-libxkbcommon-54ee7ac/src/rmlvo.c000066400000000000000000000153721510033435100207650ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "context.h" #include "keymap.h" #include "messages-codes.h" #include "rmlvo.h" #include "darray.h" #include "utils.h" #include "xkbcomp/rules.h" struct xkb_rmlvo_builder* xkb_rmlvo_builder_new(struct xkb_context *context, const char *rules, const char *model, enum xkb_rmlvo_builder_flags flags) { struct xkb_rmlvo_builder * const builder = calloc(1, sizeof(*builder)); if (!builder) goto error; builder->refcnt = 1; builder->ctx = xkb_context_ref(context); builder->rules = strdup_safe(rules); if (!builder->rules && rules) goto error; builder->model = strdup_safe(model); if (!builder->model && model) goto error; darray_init(builder->layouts); darray_init(builder->options); return builder; error: log_err(context, XKB_ERROR_ALLOCATION_ERROR, "Cannot allocate a RMLVO builder.\n"); xkb_rmlvo_builder_unref(builder); return NULL; } bool xkb_rmlvo_builder_append_layout(struct xkb_rmlvo_builder *rmlvo, const char *layout, const char *variant, const char* const* options, size_t options_len) { const xkb_layout_index_t idx = (xkb_layout_index_t) darray_size(rmlvo->layouts); if (idx >= XKB_MAX_GROUPS) { log_err(rmlvo->ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Maximum layout count reached: %"PRIu32"; " "cannot add layout \"%s(%s)\" to the RMLVO builder.\n", XKB_ERROR_UNSUPPORTED_GROUP_INDEX, layout, (variant) ? variant : ""); return false; } /* Append layout entry */ const struct xkb_rmlvo_builder_layout new = { .layout = strdup_safe(layout), .variant = strdup_safe(variant) }; if (!new.layout || (!new.variant && variant)) { free(new.layout); free(new.variant); log_err(rmlvo->ctx, XKB_ERROR_ALLOCATION_ERROR, "Cannot allocate layout \"%s(%s)\" to the RMLVO builder.\n", layout, (variant) ? variant : ""); return false; } darray_append(rmlvo->layouts, new); if (!options) options_len = 0; /* Append layout-specific options entries */ for (size_t k = 0; k < options_len; k++) { const struct xkb_rmlvo_builder_option option = { .option = strdup_safe(options[k]), .layout = idx }; if (!option.option) { log_err(rmlvo->ctx, XKB_ERROR_ALLOCATION_ERROR, "Cannot allocate option \"%s\" of layout \"%s(%s)\" " "to the RMLVO builder.\n", options[k], layout, (variant) ? variant : ""); return false; } darray_append(rmlvo->options, option); } return true; } bool xkb_rmlvo_builder_append_option(struct xkb_rmlvo_builder *rmlvo, const char *option) { if (!option) return false; /* Check for previous entry */ const struct xkb_rmlvo_builder_option *prev; darray_foreach(prev, rmlvo->options) { if (prev->layout == XKB_LAYOUT_INVALID && strcmp(prev->option, option) == 0) return true; } /* Append new entry */ const struct xkb_rmlvo_builder_option new = { .option = strdup_safe(option), .layout = XKB_LAYOUT_INVALID }; if (!new.option) { log_err(rmlvo->ctx, XKB_ERROR_ALLOCATION_ERROR, "Cannot allocate option \"%s\" to the RMLVO builder.\n", option); return false; } darray_append(rmlvo->options, new); return true; } struct xkb_rmlvo_builder * xkb_rmlvo_builder_ref(struct xkb_rmlvo_builder *rmlvo) { assert(rmlvo->refcnt > 0); rmlvo->refcnt++; return rmlvo; } void xkb_rmlvo_builder_unref(struct xkb_rmlvo_builder *rmlvo) { assert(!rmlvo || rmlvo->refcnt > 0); if (!rmlvo || --rmlvo->refcnt > 0) return; free(rmlvo->rules); free(rmlvo->model); const struct xkb_rmlvo_builder_layout *layout; darray_foreach(layout, rmlvo->layouts) { free(layout->layout); free(layout->variant); } darray_free(rmlvo->layouts); const struct xkb_rmlvo_builder_option *option; darray_foreach(option, rmlvo->options) free(option->option); darray_free(rmlvo->options); xkb_context_unref(rmlvo->ctx); free(rmlvo); } /* NOTE: the converse function, `xkb_rules_names_to_rmlvo_builder`, is currently * only used in tests */ bool xkb_rmlvo_builder_to_rules_names(const struct xkb_rmlvo_builder *builder, struct xkb_rule_names *rmlvo, char *buf, size_t buf_size) { rmlvo->rules = builder->rules; rmlvo->model = builder->model; char *start = buf; rmlvo->layout = start; darray_size_t k; const struct xkb_rmlvo_builder_layout *layout; darray_enumerate(k, layout, builder->layouts) { int count = snprintf(start, buf_size, "%s%s", (k > 0 ? "," : ""), layout->layout); if (count < 0 || (size_t) count >= buf_size) return false; buf_size -= count; start += count; } if (buf_size <= 1) return false; *start = '\0'; start++; buf_size--; rmlvo->variant = start; darray_enumerate(k, layout, builder->layouts) { int count = snprintf(start, buf_size, "%s%s", (k > 0 ? "," : ""), (layout->variant ? layout->variant : "")); if (count < 0 || (size_t) count >= buf_size) return false; buf_size -= count; start += count; } if (buf_size <= 1) return false; *start = '\0'; start++; buf_size--; rmlvo->options = start; const struct xkb_rmlvo_builder_option *option; darray_enumerate(k, option, builder->options) { int count = snprintf(start, buf_size, "%s%s", (k > 0 ? "," : ""), option->option); if (count < 0 || (size_t) count >= buf_size) return false; buf_size -= count; start += count; if (option->layout != XKB_LAYOUT_INVALID) { count = snprintf(start, buf_size, "%c%"PRIu32, OPTIONS_GROUP_SPECIFIER_PREFIX, option->layout); if (count < 0 || (size_t) count >= buf_size) return false; buf_size -= count; start += count; } } if (buf_size == 0) return false; *start = '\0'; return true; } xkbcommon-libxkbcommon-54ee7ac/src/rmlvo.h000066400000000000000000000020601510033435100207600ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "darray.h" enum RMLVO { RMLVO_RULES = (1 << 0), RMLVO_MODEL = (1 << 1), RMLVO_LAYOUT = (1 << 2), RMLVO_VARIANT = (1 << 3), RMLVO_OPTIONS = (1 << 4) }; struct xkb_rmlvo_builder_layout { char *layout; char *variant; }; typedef darray(struct xkb_rmlvo_builder_layout) xkb_rmlvo_builder_layouts; struct xkb_rmlvo_builder_option { char *option; xkb_layout_index_t layout; }; typedef darray(struct xkb_rmlvo_builder_option) xkb_rmlvo_builder_options; struct xkb_rmlvo_builder { char *rules; char *model; xkb_rmlvo_builder_layouts layouts; xkb_rmlvo_builder_options options; int refcnt; struct xkb_context *ctx; }; bool xkb_rmlvo_builder_to_rules_names(const struct xkb_rmlvo_builder *builder, struct xkb_rule_names *rmlvo, char *buf, size_t buf_size); xkbcommon-libxkbcommon-54ee7ac/src/scanner-utils.c000066400000000000000000000026531510033435100224130ustar00rootroot00000000000000/* * Copyright © 2025 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include "scanner-utils.h" struct scanner_loc scanner_token_location(struct scanner *s) { /* * The following article and accompying code compares some algorithms: * https://lemire.me/blog/2017/02/14/how-fast-can-you-count-lines/ * https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2017/02/14/newlines.c * This is the fastest portable one for me, and it's simple. * * To avoid rescanning on each call, cache the previously found position * and start from that on the next call. This is effective as long as the * tokens go forward. */ size_t line, column; size_t line_pos = 0; if (s->cached_pos > s->token_pos) { s->cached_pos = 0; s->cached_loc.line = s->cached_loc.column = 1; } line = s->cached_loc.line; const char *ptr = s->s + s->cached_pos; const char *last = s->s + s->token_pos; while ((ptr = memchr(ptr, '\n', last - ptr))) { line++; ptr++; line_pos = ptr - s->s; } if (line == s->cached_loc.line) { column = s->cached_loc.column + (s->token_pos - s->cached_pos); } else { column = s->token_pos - line_pos + 1; } struct scanner_loc loc = {.line = line, .column = column}; s->cached_pos = s->token_pos; s->cached_loc = loc; return loc; } xkbcommon-libxkbcommon-54ee7ac/src/scanner-utils.h000066400000000000000000000234371510033435100224230ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include #include #include #include "context.h" #include "darray.h" #include "messages-codes.h" #include "utils.h" #include "utils-numbers.h" #include "utf8.h" /* Point to some substring in the file; used to avoid copying. */ struct sval { const char *start; size_t len; }; typedef darray(struct sval) darray_sval; static inline bool svaleq(struct sval s1, struct sval s2) { return s1.len == s2.len && memcmp(s1.start, s2.start, s1.len) == 0; } static inline bool isvaleq(struct sval s1, struct sval s2) { return s1.len == s2.len && istrncmp(s1.start, s2.start, s1.len) == 0; } static inline bool svaleq_prefix(struct sval s1, struct sval s2) { return s1.len <= s2.len && memcmp(s1.start, s2.start, s1.len) == 0; } #define SVAL(start, len) (struct sval){(start), len} #define SVAL_LIT(literal) SVAL(literal, sizeof(literal) - 1) #define SVAL_INIT(literal) { literal, sizeof(literal) - 1 } /* A line:column location in the input string (1-based). */ struct scanner_loc { size_t line, column; }; struct scanner { const char *s; size_t pos; size_t len; /* * Internal buffer. * Since this is used to handle paths that are possibly absolute, in theory * we should size it to PATH_MAX. However it is very unlikely to reach such * long paths in our context. */ char buf[1024]; size_t buf_pos; /* The position of the start of the current token. */ size_t token_pos; /* Cached values used by scanner_token_location. */ size_t cached_pos; struct scanner_loc cached_loc; const char *file_name; struct xkb_context *ctx; void *priv; }; /* Compute the line:column location for the current token (slow). */ struct scanner_loc scanner_token_location(struct scanner *s); #define scanner_log_with_code(scanner, level, verbosity, log_msg_id, fmt, ...) do { \ struct scanner_loc loc = scanner_token_location((scanner)); \ xkb_log_with_code((scanner)->ctx, (level), verbosity, log_msg_id, \ "%s:%zu:%zu: " fmt "\n", \ (scanner)->file_name, \ loc.line, \ loc.column, ##__VA_ARGS__); \ } while(0) #define scanner_err(scanner, id, fmt, ...) \ scanner_log_with_code(scanner, XKB_LOG_LEVEL_ERROR, \ XKB_LOG_VERBOSITY_MINIMAL, id, fmt, ##__VA_ARGS__) #define scanner_warn(scanner, id, fmt, ...) \ scanner_log_with_code(scanner, XKB_LOG_LEVEL_WARNING, \ XKB_LOG_VERBOSITY_MINIMAL, id, fmt, ##__VA_ARGS__) #define scanner_vrb(scanner, verbosity, id, fmt, ...) \ scanner_log_with_code(scanner, XKB_LOG_LEVEL_WARNING, verbosity, id, \ fmt, ##__VA_ARGS__) static inline void scanner_init(struct scanner *s, struct xkb_context *ctx, const char *string, size_t len, const char *file_name, void *priv) { s->s = string; s->len = len; s->pos = 0; s->token_pos = 0; s->cached_pos = 0; s->cached_loc.line = s->cached_loc.column = 1; s->file_name = file_name; s->ctx = ctx; s->priv = priv; } static inline char scanner_peek(struct scanner *s) { if (unlikely(s->pos >= s->len)) return '\0'; return s->s[s->pos]; } static inline bool scanner_eof(struct scanner *s) { return s->pos >= s->len; } static inline bool scanner_eol(struct scanner *s) { return scanner_peek(s) == '\n'; } static inline void scanner_skip_to_eol(struct scanner *s) { const char *nl = memchr(s->s + s->pos, '\n', s->len - s->pos); const size_t new_pos = nl ? (size_t) (nl - s->s) : s->len; s->pos = new_pos; } static inline char scanner_next(struct scanner *s) { if (unlikely(scanner_eof(s))) return '\0'; return s->s[s->pos++]; } static inline bool scanner_chr(struct scanner *s, char ch) { if (likely(scanner_peek(s) != ch)) return false; s->pos++; return true; } static inline bool scanner_str(struct scanner *s, const char *string, size_t len) { if (s->len - s->pos < len) return false; if (memcmp(s->s + s->pos, string, len) != 0) return false; s->pos += len; return true; } #define scanner_lit(s, literal) scanner_str(s, literal, sizeof(literal) - 1) static inline bool scanner_buf_append(struct scanner *s, char ch) { if (s->buf_pos + 1 >= sizeof(s->buf)) return false; s->buf[s->buf_pos++] = ch; return true; } static inline bool scanner_buf_appends(struct scanner *s, const char *str) { int ret; ret = snprintf(s->buf + s->buf_pos, sizeof(s->buf) - s->buf_pos, "%s", str); if (ret < 0 || (size_t) ret >= sizeof(s->buf) - s->buf_pos) return false; s->buf_pos += ret; return true; } static inline bool scanner_buf_appends_code_point(struct scanner *s, uint32_t c) { /* Up to 4 bytes + NULL */ if (s->buf_pos + 5 <= sizeof(s->buf)) { int count = utf32_to_utf8(c, s->buf + s->buf_pos); if (count == 0) { /* Handle encoding failure with U+FFFD REPLACEMENT CHARACTER */ count = utf32_to_utf8(0xfffd, s->buf + s->buf_pos); } if (count == 0) return false; /* `count` counts the NULL byte */ s->buf_pos += count - 1; return true; } else { return false; } } static inline bool scanner_oct(struct scanner *s, uint8_t *out) { uint8_t i = 0; uint8_t c = 0; for (; scanner_peek(s) >= '0' && scanner_peek(s) <= '7' && i < 4; i++) { /* Test overflow */ if (c < 040) { c = c * 8 + scanner_next(s) - '0'; } else { /* Consume valid digit, but mark result as invalid */ scanner_next(s); *out = c; return false; } } *out = c; return i > 0; } static inline bool scanner_hex(struct scanner *s, uint8_t *out) { uint8_t i; for (i = 0, *out = 0; is_xdigit(scanner_peek(s)) && i < 2; i++) { const char c = scanner_next(s); const char offset = (char) (c >= '0' && c <= '9' ? '0' : c >= 'a' && c <= 'f' ? 'a' - 10 : 'A' - 10); *out = *out * 16 + c - offset; } return i > 0; } static inline int scanner_dec_int64(struct scanner *s, int64_t *out) { uint64_t val = 0; const int count = parse_dec_to_uint64_t(s->s + s->pos, s->len - s->pos, &val); if (count > 0) { /* * NOTE: Since the sign is handled as a token, we parse only *positive* * values here. So that means that *we cannot parse INT64_MIN*, * because abs(INT64_MIN) > INT64_MAX. But we use 64-bit integers * only to avoid under/overflow in expressions: we do not use * 64-bit integers in the keymap, only up to 32 bits. So we expect * to parse only 32 bits integers in realistic keymap files and * the limitation should not be an issue. */ if (val > INT64_MAX) return -1; s->pos += count; *out = (int64_t) val; } return count; } static inline int scanner_hex_int64(struct scanner *s, int64_t *out) { uint64_t val = 0; const int count = parse_hex_to_uint64_t(s->s + s->pos, s->len - s->pos, &val); if (count > 0) { /* See comment in `scanner_dec_int64()` above */ if (val > INT64_MAX) return -1; s->pos += count; *out = (int64_t) val; } return count; } /** Parser for the {NNNN} part of a Unicode escape sequences */ static inline bool scanner_unicode_code_point(struct scanner *s, uint32_t *out) { if (!scanner_chr(s, '{')) return false; uint32_t cp = 0; const int count = parse_hex_to_uint32_t(s->s + s->pos, s->len - s->pos, &cp); if (count > 0) s->pos += count; /* Try to consume everything within the string until the next `}` */ const size_t last_valid = s->pos; while (!scanner_eof(s) && !scanner_eol(s) && scanner_peek(s) != '"' && scanner_peek(s) != '}') { scanner_next(s); } if (scanner_chr(s, '}')) { /* End of the escape sequence; code point may be invalid */ *out = cp; return (count > 0 && s->pos == last_valid + 1 && cp <= 0x10ffff); } /* No closing `}` within the string: rollback to last valid position */ s->pos = last_valid; return false; } /* Basic detection of wrong character encoding based on the first bytes */ static inline bool scanner_check_supported_char_encoding(struct scanner *scanner) { /* Skip UTF-8 encoded BOM (U+FEFF) * See: https://www.unicode.org/faq/utf_bom.html#bom5 */ if (scanner_str(scanner, "\xef\xbb\xbf", 3) || scanner->len < 2) { /* Assume UTF-8 encoding or trivial short input */ return true; } /* Early detection of wrong file encoding, e.g. UTF-16 or UTF-32 */ if (scanner->s[0] == '\0' || scanner->s[1] == '\0') { scanner_err(scanner, XKB_ERROR_INVALID_FILE_ENCODING, "unexpected NULL character."); return false; } /* Enforce the first character to be ASCII. See the note before the use of this function, that explains the relevant parts of the grammars of rules, keymap components and Compose. */ if (!is_ascii(scanner->s[0])) { scanner_err(scanner, XKB_ERROR_INVALID_FILE_ENCODING, "unexpected non-ASCII character."); return false; } return true; } xkbcommon-libxkbcommon-54ee7ac/src/state.c000066400000000000000000002027751510033435100207530ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT * * Author: Daniel Stone */ /* * This is a bastardised version of xkbActions.c from the X server which * does not support, for the moment: * - AccessX sticky/debounce/etc (will come later) * - pointer keys (may come later) * - key redirects (unlikely) * - messages (very unlikely) */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "keymap.h" #include "keysym.h" #include "utf8.h" struct xkb_filter { union xkb_action action; const struct xkb_key *key; uint32_t priv; bool (*func)(struct xkb_state *state, struct xkb_filter *filter, const struct xkb_key *key, enum xkb_key_direction direction); int refcnt; }; struct state_components { /* These may be negative, because of -1 group actions. */ int32_t base_group; /**< depressed */ int32_t latched_group; int32_t locked_group; xkb_layout_index_t group; /**< effective */ xkb_mod_mask_t base_mods; /**< depressed */ xkb_mod_mask_t latched_mods; xkb_mod_mask_t locked_mods; xkb_mod_mask_t mods; /**< effective */ xkb_led_mask_t leds; }; struct xkb_state { /* * Before updating the state, we keep a copy of just this struct. This * allows us to report which components of the state have changed. */ struct state_components components; /* * At each event, we accumulate all the needed modifications to the base * modifiers, and apply them at the end. These keep track of this state. */ xkb_mod_mask_t set_mods; xkb_mod_mask_t clear_mods; /* * We mustn't clear a base modifier if there's another depressed key * which affects it, e.g. given this sequence * < Left Shift down, Right Shift down, Left Shift Up > * the modifier should still be set. This keeps the count. */ int16_t mod_key_count[XKB_MAX_MODS]; int refcnt; darray(struct xkb_filter) filters; struct xkb_keymap *keymap; }; static const struct xkb_key_type_entry * get_entry_for_mods(const struct xkb_key_type *type, xkb_mod_mask_t mods) { for (darray_size_t i = 0; i < type->num_entries; i++) if (entry_is_active(&type->entries[i]) && type->entries[i].mods.mask == mods) return &type->entries[i]; return NULL; } static const struct xkb_key_type_entry * get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key, xkb_layout_index_t group) { const struct xkb_key_type* const type = key->groups[group].type; xkb_mod_mask_t active_mods = state->components.mods & type->mods.mask; return get_entry_for_mods(type, active_mods); } static inline xkb_level_index_t state_key_get_level(struct xkb_state *state, const struct xkb_key *key, xkb_layout_index_t layout) { if (layout >= key->num_groups) return XKB_LEVEL_INVALID; /* If we don't find an explicit match the default is 0. */ const struct xkb_key_type_entry* const entry = get_entry_for_key_state(state, key, layout); return (entry) ? entry->level : 0; } /** * Returns the level to use for the given key and state, or * XKB_LEVEL_INVALID. */ xkb_level_index_t xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc, xkb_layout_index_t layout) { const struct xkb_key* const key = XkbKey(state->keymap, kc); return (key) ? state_key_get_level(state, key, layout) : XKB_LEVEL_INVALID; } static inline xkb_layout_index_t state_key_get_layout(struct xkb_state *state, const struct xkb_key *key) { static_assert(XKB_MAX_GROUPS < INT32_MAX, "Max groups don't fit"); return XkbWrapGroupIntoRange((int32_t) state->components.group, key->num_groups, key->out_of_range_group_action, key->out_of_range_group_number); } /** * Returns the layout to use for the given key and state, taking * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID. */ xkb_layout_index_t xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc) { const struct xkb_key* const key = XkbKey(state->keymap, kc); if (!key) return XKB_LAYOUT_INVALID; return state_key_get_layout(state, key); } /* Empty action used for empty levels */ static const union xkb_action dummy_action = { .type = ACTION_TYPE_NONE }; static xkb_action_count_t xkb_key_get_actions(struct xkb_state *state, const struct xkb_key *key, const union xkb_action **actions) { const xkb_layout_index_t layout = state_key_get_layout(state, key); const xkb_level_index_t level = state_key_get_level(state, key, layout); if (level == XKB_LEVEL_INVALID) goto err; const xkb_action_count_t count = xkb_keymap_key_get_actions_by_level(state->keymap, key, layout, level, actions); if (!count) goto err; return count; err: /* Use a dummy action if no corresponding level was found or if it is empty. * This is required e.g. to handle latches properly. */ *actions = &dummy_action; return 1; } static struct xkb_filter * xkb_filter_new(struct xkb_state *state) { struct xkb_filter *filter = NULL, *iter; darray_foreach(iter, state->filters) { if (iter->func) continue; /* Use available slot */ filter = iter; break; } if (!filter) { /* No available slot: resize the filters array */ darray_resize0(state->filters, darray_size(state->filters) + 1); filter = &darray_item(state->filters, darray_size(state->filters) -1); } filter->refcnt = 1; return filter; } /***====================================================================***/ enum xkb_filter_result { /* * The event is consumed by the filters. * * An event is always processed by all filters, but any filter can * prevent it from being processed further by consuming it. */ XKB_FILTER_CONSUME, /* * The event may continue to be processed as far as this filter is * concerned. */ XKB_FILTER_CONTINUE, }; /* Modify a group component, depending on the ACTION_ABSOLUTE_SWITCH flag */ #define apply_group_delta(filter_, state_, component_) \ if ((filter_)->action.group.flags & ACTION_ABSOLUTE_SWITCH) \ (state_)->components.component_ = (filter_)->action.group.group; \ else \ (state_)->components.component_ += (filter_)->action.group.group static void xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter) { static_assert(sizeof(state->components.base_group) == sizeof(filter->priv), "Max groups don't fit"); filter->priv = state->components.base_group; apply_group_delta(filter, state, base_group); } static bool xkb_filter_group_set_func(struct xkb_state *state, struct xkb_filter *filter, const struct xkb_key *key, enum xkb_key_direction direction) { if (key != filter->key) { filter->action.group.flags &= ~ACTION_LOCK_CLEAR; return XKB_FILTER_CONTINUE; } if (direction == XKB_KEY_DOWN) { filter->refcnt++; return XKB_FILTER_CONSUME; } else if (--filter->refcnt > 0) { return XKB_FILTER_CONSUME; } static_assert(sizeof(state->components.base_group) == sizeof(filter->priv), "Max groups don't fit"); state->components.base_group = (int32_t) filter->priv; if (filter->action.group.flags & ACTION_LOCK_CLEAR) state->components.locked_group = 0; filter->func = NULL; return XKB_FILTER_CONTINUE; } static void xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter) { if (filter->action.group.flags & ACTION_LOCK_ON_RELEASE) { /* * Lock on key release: do nothing on key press. * * This is a keymap format v2 extension. */ return; } else { /* Lock on key press */ apply_group_delta(filter, state, locked_group); } } static bool xkb_filter_group_lock_func(struct xkb_state *state, struct xkb_filter *filter, const struct xkb_key *key, enum xkb_key_direction direction) { if (key != filter->key) { if ((filter->action.group.flags & ACTION_LOCK_ON_RELEASE) && direction == XKB_KEY_DOWN) { /* * Another key has been pressed after the locking key: * cancel group lock on release. * * This is a keymap v2 extension. */ filter->action.group.flags &= ~ACTION_LOCK_ON_RELEASE; } return XKB_FILTER_CONTINUE; } if (direction == XKB_KEY_DOWN) { filter->refcnt++; return XKB_FILTER_CONSUME; } if (--filter->refcnt > 0) return XKB_FILTER_CONSUME; if (filter->action.group.flags & ACTION_LOCK_ON_RELEASE) { /* * Lock on key release * * This is a keymap v2 extension. */ apply_group_delta(filter, state, locked_group); } else { /* Lock on key press: do nothing on key release. */ } filter->func = NULL; return XKB_FILTER_CONTINUE; } static bool xkb_action_breaks_latch(const union xkb_action *action, enum xkb_internal_action_flags flag, xkb_mod_mask_t mask) { switch (action->type) { case ACTION_TYPE_NONE: case ACTION_TYPE_VOID: case ACTION_TYPE_PTR_BUTTON: case ACTION_TYPE_PTR_LOCK: case ACTION_TYPE_CTRL_SET: case ACTION_TYPE_CTRL_LOCK: case ACTION_TYPE_SWITCH_VT: case ACTION_TYPE_TERMINATE: return true; case ACTION_TYPE_INTERNAL: return (action->internal.flags & flag) && ((action->internal.clear_latched_mods & mask) == mask); default: {} /* Label followed by declaration requires C23 */ /* Ensure to not miss `xkb_action_type` updates */ static_assert(ACTION_TYPE_INTERNAL == 18 && ACTION_TYPE_INTERNAL + 1 == _ACTION_TYPE_NUM_ENTRIES, "Missing action type"); return false; } } enum xkb_key_latch_state { NO_LATCH = 0, LATCH_KEY_DOWN, LATCH_PENDING, _KEY_LATCH_STATE_NUM_ENTRIES }; #define MAX_XKB_KEY_LATCH_STATE_LOG2 2 #if (_KEY_LATCH_STATE_NUM_ENTRIES > (1 << MAX_XKB_KEY_LATCH_STATE_LOG2)) || \ (-XKB_MAX_GROUPS) < (INT32_MIN >> MAX_XKB_KEY_LATCH_STATE_LOG2) || \ XKB_MAX_GROUPS > (INT32_MAX >> MAX_XKB_KEY_LATCH_STATE_LOG2) #error "Cannot represent priv field of the group latch filter" #endif /* Hold the latch state *and* the group delta */ union group_latch_priv { uint32_t priv; struct { /* The type is really: enum xkb_key_latch_state, but it is problematic * on Windows, because it is interpreted as signed and leads to wrong * negative values. */ unsigned int latch:MAX_XKB_KEY_LATCH_STATE_LOG2; int32_t group_delta:(32 - MAX_XKB_KEY_LATCH_STATE_LOG2); }; }; static void xkb_filter_group_latch_new(struct xkb_state *state, struct xkb_filter *filter) { const union group_latch_priv priv = { .latch = LATCH_KEY_DOWN, .group_delta = (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH) ? filter->action.group.group - state->components.base_group : filter->action.group.group }; filter->priv = priv.priv; /* Like group set */ apply_group_delta(filter, state, base_group); } static bool xkb_filter_group_latch_func(struct xkb_state *state, struct xkb_filter *filter, const struct xkb_key *key, enum xkb_key_direction direction) { union group_latch_priv priv = {.priv = filter->priv}; enum xkb_key_latch_state latch = priv.latch; if (direction == XKB_KEY_DOWN) { const union xkb_action *actions = NULL; const xkb_action_count_t count = xkb_key_get_actions(state, key, &actions); if (latch == LATCH_KEY_DOWN) { /* * Another key was pressed while we’ve still got the latching key * held down. * * The exact behavior depends on the keymap format version. * It results in either: * • No change. * • Prevent the latch to trigger and keep the base group set by * xkb_filter_group_latch_new(), until the latch key is * released. */ if (state->keymap->format == XKB_KEYMAP_FORMAT_TEXT_V1) { /* Keymap v1: unconditionally prevent the latch to trigger. */ latch = NO_LATCH; } else { /* * Keymap v2+: prevent the latch to trigger only if some of the * pressed key’s actions breaks latches, mirroring the behavior * in the LATCH_PENDING state. * * This is an extension to the X11 XKB protocol. */ for (xkb_action_count_t k = 0; k < count; k++) { if (xkb_action_breaks_latch(&(actions[k]), INTERNAL_BREAKS_GROUP_LATCH, 0)) { latch = NO_LATCH; break; } } } } else if (latch == LATCH_PENDING) { /* If this is a new keypress and we're awaiting our single latched * keypress, then either break the latch if any random key is * pressed, or promote it to a lock if it's the same group delta & * flags and latchToLock option is enabled. */ for (xkb_action_count_t k = 0; k < count; k++) { if (actions[k].type == ACTION_TYPE_GROUP_LATCH && actions[k].group.group == filter->action.group.group && actions[k].group.flags == filter->action.group.flags) { filter->action = actions[k]; if (filter->action.group.flags & ACTION_LATCH_TO_LOCK && filter->action.group.group != 0) { /* Promote to lock */ filter->action.type = ACTION_TYPE_GROUP_LOCK; filter->func = xkb_filter_group_lock_func; xkb_filter_group_lock_new(state, filter); state->components.latched_group -= priv.group_delta; filter->key = key; /* XXX beep beep! */ return XKB_FILTER_CONSUME; } /* Do nothing if `latchToLock` option is not activated; if * the latch is not broken by the following actions and the * key is not consumed, then another latch filter will be * created. */ continue; } else if (xkb_action_breaks_latch(&(actions[k]), INTERNAL_BREAKS_GROUP_LATCH, 0)) { /* Breaks the latch */ state->components.latched_group -= priv.group_delta; filter->func = NULL; return XKB_FILTER_CONTINUE; } } } else { /* Ignore press in NO_LATCH state */ assert(latch == NO_LATCH); } } else if (direction == XKB_KEY_UP && key == filter->key) { /* Our key got released. If we've set it to clear locks, and we * currently have a group locked, then release it and * don't actually latch. Else we've actually hit the latching * stage, so set PENDING and move our group from base to * latched. */ if ((filter->action.group.flags & ACTION_LOCK_CLEAR) && state->components.locked_group) { if (latch == LATCH_PENDING) state->components.latched_group -= priv.group_delta; else state->components.base_group -= priv.group_delta; state->components.locked_group = 0; filter->func = NULL; } /* Broken latch */ else if (latch == NO_LATCH) { state->components.base_group -= priv.group_delta; filter->func = NULL; } /* We may already have reached the latch state if pressing the * key multiple times without latch-to-lock enabled. */ else if (latch == LATCH_KEY_DOWN) { latch = LATCH_PENDING; /* Switch from set to latch */ state->components.base_group -= priv.group_delta; state->components.latched_group += priv.group_delta; /* XXX beep beep! */ } } else { /* Ignore release of other keys */ } priv.latch = latch; filter->priv = priv.priv; return XKB_FILTER_CONTINUE; } static void xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter) { const enum xkb_action_flags unlock = ACTION_UNLOCK_ON_PRESS | ACTION_LOCK_CLEAR; if ((filter->action.mods.flags & unlock) == unlock) { /* * Unlock on press * * This is a keymap v2 extension. */ filter->priv = filter->action.mods.mods.mask & ~state->components.locked_mods; state->components.locked_mods &= ~filter->action.mods.mods.mask; } else { filter->priv = filter->action.mods.mods.mask; } state->set_mods |= (xkb_mod_mask_t) filter->priv; } static bool xkb_filter_mod_set_func(struct xkb_state *state, struct xkb_filter *filter, const struct xkb_key *key, enum xkb_key_direction direction) { if (key != filter->key) { filter->action.mods.flags &= ~ACTION_LOCK_CLEAR; return XKB_FILTER_CONTINUE; } if (direction == XKB_KEY_DOWN) { filter->refcnt++; return XKB_FILTER_CONSUME; } else if (--filter->refcnt > 0) { return XKB_FILTER_CONSUME; } state->clear_mods |= (xkb_mod_mask_t) filter->priv; const enum xkb_action_flags unlock = ACTION_UNLOCK_ON_PRESS | ACTION_LOCK_CLEAR; if ((filter->action.mods.flags & unlock) == ACTION_LOCK_CLEAR) state->components.locked_mods &= ~filter->action.mods.mods.mask; filter->func = NULL; return XKB_FILTER_CONTINUE; } static void xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter) { filter->priv = (state->components.locked_mods & filter->action.mods.mods.mask); if (filter->priv && (filter->action.mods.flags & ACTION_UNLOCK_ON_PRESS)) { /* * Some of the target modifiers were locked before key press: unlock. * * This is a keymap v2 extension: unlock-on-press. */ if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK)) state->components.locked_mods &= ~filter->priv; /* No further action: cancel filter */ filter->func = NULL; } else { /* Set base mods; lock mods if relevant (XKB 1.0 spec) */ state->set_mods |= filter->action.mods.mods.mask; if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK)) state->components.locked_mods |= filter->action.mods.mods.mask; } } static bool xkb_filter_mod_lock_func(struct xkb_state *state, struct xkb_filter *filter, const struct xkb_key *key, enum xkb_key_direction direction) { if (key != filter->key) return XKB_FILTER_CONTINUE; if (direction == XKB_KEY_DOWN) { filter->refcnt++; return XKB_FILTER_CONSUME; } if (--filter->refcnt > 0) return XKB_FILTER_CONSUME; state->clear_mods |= filter->action.mods.mods.mask; if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK)) state->components.locked_mods &= ~filter->priv; filter->func = NULL; return XKB_FILTER_CONTINUE; } static void xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter) { /* Latch-on-press + clear-locks imply unlock-on-press */ const enum xkb_action_flags unlockOnPress = ACTION_UNLOCK_ON_PRESS | ACTION_LATCH_ON_PRESS; if ((filter->action.mods.flags & ACTION_LOCK_CLEAR) && (filter->action.mods.flags & unlockOnPress) && (state->components.locked_mods & filter->action.mods.mods.mask) == filter->action.mods.mods.mask) { /* * Unlock on press * * This is a keymap v2 extension: clear locks and do not latch. */ state->components.locked_mods &= ~filter->action.mods.mods.mask; filter->func = NULL; } else if (filter->action.mods.flags & ACTION_LATCH_ON_PRESS) { /* * Latch on key press * * This is a keymap format v2 extension. */ filter->priv = LATCH_PENDING; state->components.latched_mods |= filter->action.mods.mods.mask; /* XXX beep beep! */ } else { /* XKB standard latch action */ filter->priv = LATCH_KEY_DOWN; state->set_mods |= filter->action.mods.mods.mask; } } static bool xkb_filter_mod_latch_func(struct xkb_state *state, struct xkb_filter *filter, const struct xkb_key *key, enum xkb_key_direction direction) { enum xkb_key_latch_state latch = filter->priv; if (direction == XKB_KEY_DOWN) { const union xkb_action *actions = NULL; const xkb_action_count_t count = xkb_key_get_actions(state, key, &actions); if (latch == LATCH_KEY_DOWN) { /* * Another key was pressed while we’ve still got the latching key * held down. * * The exact behavior depends on the keymap format version. * It results in either: * • No change. * • Prevent the latch to trigger and keep the base modifiers set * by xkb_filter_mod_latch_new(), until the latch key is released. */ if (state->keymap->format == XKB_KEYMAP_FORMAT_TEXT_V1) { /* Keymap v1: unconditionally prevent the latch to trigger. */ latch = NO_LATCH; } else { /* * Keymap v2+: prevent the latch to trigger only if some of the * pressed key’s actions breaks latches, mirroring the behavior * in the LATCH_PENDING state. * * This is an extension to the X11 XKB protocol. */ for (xkb_action_count_t k = 0; k < count; k++) { if (xkb_action_breaks_latch(&(actions[k]), INTERNAL_BREAKS_MOD_LATCH, filter->action.mods.mods.mask)) { latch = NO_LATCH; break; } } } } else if (latch == LATCH_PENDING) { /* If this is a new keypress and we're awaiting our single latched * keypress, then either break the latch if any random key is pressed, * or promote it to a lock or plain base set if it's the same * modifier. */ for (xkb_action_count_t k = 0; k < count; k++) { if (actions[k].type == ACTION_TYPE_MOD_LATCH && actions[k].mods.flags == filter->action.mods.flags && actions[k].mods.mods.mask == filter->action.mods.mods.mask) { filter->action = actions[k]; if (filter->action.mods.flags & ACTION_LATCH_TO_LOCK) { /* Mutate the action to LockMods() */ filter->action.type = ACTION_TYPE_MOD_LOCK; filter->func = xkb_filter_mod_lock_func; xkb_filter_mod_lock_new(state, filter); } else { /* Mutate the action to SetMods() */ filter->action.type = ACTION_TYPE_MOD_SET; filter->func = xkb_filter_mod_set_func; xkb_filter_mod_set_new(state, filter); } filter->key = key; /* Clear latches */ state->components.latched_mods &= ~filter->action.mods.mods.mask; /* XXX beep beep! */ return XKB_FILTER_CONSUME; } else if (xkb_action_breaks_latch(&(actions[k]), INTERNAL_BREAKS_MOD_LATCH, filter->action.mods.mods.mask)) { /* XXX: This may be totally broken, we might need to break the * latch in the next run after this press? */ state->components.latched_mods &= ~filter->action.mods.mods.mask; filter->func = NULL; return XKB_FILTER_CONTINUE; } } } else { /* Ignore press in NO_LATCH state */ assert(latch == NO_LATCH); } } else if (direction == XKB_KEY_UP && key == filter->key) { /* Our key got released. If we’ve set it to clear locks, and we * currently have the same modifiers locked, then release them and * don't actually latch. Else we’ve actually hit the latching * stage, so set PENDING and move our modifier from base to * latched. */ /* Latch-on-press + clear-locks imply unlock-on-press */ const enum xkb_action_flags unlockOnPress = ACTION_UNLOCK_ON_PRESS | ACTION_LATCH_ON_PRESS; if ((filter->action.mods.flags & ACTION_LOCK_CLEAR) && !(filter->action.mods.flags & unlockOnPress) && (state->components.locked_mods & filter->action.mods.mods.mask) == filter->action.mods.mods.mask) { /* XXX: We might be a bit overenthusiastic about clearing * mods other filters have set here? */ if (latch == LATCH_PENDING) state->components.latched_mods &= ~filter->action.mods.mods.mask; else state->clear_mods |= filter->action.mods.mods.mask; state->components.locked_mods &= ~filter->action.mods.mods.mask; filter->func = NULL; } else if (latch == NO_LATCH) { /* Broken latch */ state->clear_mods |= filter->action.mods.mods.mask; filter->func = NULL; } else if (!(filter->action.mods.flags & ACTION_LATCH_ON_PRESS)) { latch = LATCH_PENDING; state->clear_mods |= filter->action.mods.mods.mask; state->components.latched_mods |= filter->action.mods.mods.mask; /* XXX beep beep! */ } } else { /* Ignore release of other keys */ } filter->priv = latch; return XKB_FILTER_CONTINUE; } static const struct { void (*new)(struct xkb_state *state, struct xkb_filter *filter); bool (*func)(struct xkb_state *state, struct xkb_filter *filter, const struct xkb_key *key, enum xkb_key_direction direction); } filter_action_funcs[_ACTION_TYPE_NUM_ENTRIES] = { [ACTION_TYPE_MOD_SET] = { xkb_filter_mod_set_new, xkb_filter_mod_set_func }, [ACTION_TYPE_MOD_LATCH] = { xkb_filter_mod_latch_new, xkb_filter_mod_latch_func }, [ACTION_TYPE_MOD_LOCK] = { xkb_filter_mod_lock_new, xkb_filter_mod_lock_func }, [ACTION_TYPE_GROUP_SET] = { xkb_filter_group_set_new, xkb_filter_group_set_func }, [ACTION_TYPE_GROUP_LATCH] = { xkb_filter_group_latch_new, xkb_filter_group_latch_func }, [ACTION_TYPE_GROUP_LOCK] = { xkb_filter_group_lock_new, xkb_filter_group_lock_func }, }; /** * Applies any relevant filters to the key, first from the list of filters * that are currently active, then if no filter has claimed the key, possibly * apply a new filter from the key action. */ static void xkb_filter_apply_all(struct xkb_state *state, const struct xkb_key *key, enum xkb_key_direction direction) { /* First run through all the currently active filters and see if any of * them have consumed this event. */ bool consumed = false; struct xkb_filter *filter; darray_foreach(filter, state->filters) { if (!filter->func) continue; if (filter->func(state, filter, key, direction) == XKB_FILTER_CONSUME) consumed = true; } if (consumed || direction == XKB_KEY_UP) return; /* No filter consumed this event, so proceed with the key actions */ const union xkb_action *actions = NULL; const xkb_action_count_t count = xkb_key_get_actions(state, key, &actions); /* * Process actions sequentially. * * NOTE: We rely on the parser to disallow multiple modifier or group * actions (see `CheckMultipleActionsCategories`). Allowing multiple such * actions requires a refactor of the state handling. */ for (xkb_action_count_t k = 0; k < count; k++) { /* * It's possible for the keymap to set action->type explicitly, like so: * interpret XF86_Next_VMode { * action = Private(type=0x86, data="+VMode"); * }; * We don't handle those. */ if (actions[k].type >= _ACTION_TYPE_NUM_ENTRIES) continue; /* Go to next action if no corresponding action handler */ if (!filter_action_funcs[actions[k].type].new) continue; /* Add a new filter and run the corresponding initial action */ filter = xkb_filter_new(state); filter->key = key; filter->func = filter_action_funcs[actions[k].type].func; filter->action = actions[k]; filter_action_funcs[actions[k].type].new(state, filter); } } struct xkb_state * xkb_state_new(struct xkb_keymap *keymap) { struct xkb_state* restrict const state = calloc(1, sizeof(*state)); if (!state) return NULL; state->refcnt = 1; state->keymap = xkb_keymap_ref(keymap); return state; } struct xkb_state * xkb_state_ref(struct xkb_state *state) { assert(state->refcnt > 0); state->refcnt++; return state; } void xkb_state_unref(struct xkb_state *state) { assert(!state || state->refcnt > 0); if (!state || --state->refcnt > 0) return; xkb_keymap_unref(state->keymap); darray_free(state->filters); free(state); } struct xkb_keymap * xkb_state_get_keymap(struct xkb_state *state) { return state->keymap; } /** * Update the LED state to match the rest of the xkb_state. */ static void xkb_state_led_update_all(struct xkb_state *state) { xkb_led_index_t idx; const struct xkb_led *led; state->components.leds = 0; xkb_leds_enumerate(idx, led, state->keymap) { if (led->which_mods != 0 && led->mods.mask != 0) { xkb_mod_mask_t mod_mask = 0; if (led->which_mods & XKB_STATE_MODS_EFFECTIVE) mod_mask |= state->components.mods; if (led->which_mods & XKB_STATE_MODS_DEPRESSED) mod_mask |= state->components.base_mods; if (led->which_mods & XKB_STATE_MODS_LATCHED) mod_mask |= state->components.latched_mods; if (led->which_mods & XKB_STATE_MODS_LOCKED) mod_mask |= state->components.locked_mods; if (led->mods.mask & mod_mask) { state->components.leds |= (UINT32_C(1) << idx); continue; } } if (led->which_groups != 0) { if (likely(led->groups) != 0) { xkb_layout_mask_t group_mask = 0; /* Effective and locked groups have been brought into range */ assert(state->components.group < XKB_MAX_GROUPS); assert(state->components.locked_group >= 0 && state->components.locked_group < XKB_MAX_GROUPS); /* Effective and locked groups are used as mask */ if (led->which_groups & XKB_STATE_LAYOUT_EFFECTIVE) group_mask |= (UINT32_C(1) << state->components.group); if (led->which_groups & XKB_STATE_LAYOUT_LOCKED) group_mask |= (UINT32_C(1) << state->components.locked_group); /* Base and latched groups only have to be non-zero */ if ((led->which_groups & XKB_STATE_LAYOUT_DEPRESSED) && state->components.base_group != 0) group_mask |= led->groups; if ((led->which_groups & XKB_STATE_LAYOUT_LATCHED) && state->components.latched_group != 0) group_mask |= led->groups; if (led->groups & group_mask) { state->components.leds |= (UINT32_C(1) << idx); continue; } } else { /* Special case for Base and latched groups */ if (((led->which_groups & XKB_STATE_LAYOUT_DEPRESSED) && state->components.base_group == 0) || ((led->which_groups & XKB_STATE_LAYOUT_LATCHED) && state->components.latched_group == 0)) { state->components.leds |= (UINT32_C(1) << idx); continue; } } } if (led->ctrls & state->keymap->enabled_ctrls) { state->components.leds |= (UINT32_C(1) << idx); continue; } } } /** * Calculates the derived state (effective mods/group and LEDs) from an * up-to-date xkb_state. */ static void xkb_state_update_derived(struct xkb_state *state) { xkb_layout_index_t wrapped; state->components.mods = (state->components.base_mods | state->components.latched_mods | state->components.locked_mods); /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */ /* Lock group must be adjusted, but not base nor latched groups */ wrapped = XkbWrapGroupIntoRange(state->components.locked_group, state->keymap->num_groups, RANGE_WRAP, 0); static_assert(XKB_MAX_GROUPS < INT32_MAX, "Max groups don't fit"); state->components.locked_group = (int32_t) (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped); /* Effective group must be adjusted */ wrapped = XkbWrapGroupIntoRange(state->components.base_group + state->components.latched_group + state->components.locked_group, state->keymap->num_groups, RANGE_WRAP, 0); state->components.group = (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped); xkb_state_led_update_all(state); } static enum xkb_state_component get_state_component_changes(const struct state_components *a, const struct state_components *b) { xkb_mod_mask_t mask = 0; if (a->group != b->group) mask |= XKB_STATE_LAYOUT_EFFECTIVE; if (a->base_group != b->base_group) mask |= XKB_STATE_LAYOUT_DEPRESSED; if (a->latched_group != b->latched_group) mask |= XKB_STATE_LAYOUT_LATCHED; if (a->locked_group != b->locked_group) mask |= XKB_STATE_LAYOUT_LOCKED; if (a->mods != b->mods) mask |= XKB_STATE_MODS_EFFECTIVE; if (a->base_mods != b->base_mods) mask |= XKB_STATE_MODS_DEPRESSED; if (a->latched_mods != b->latched_mods) mask |= XKB_STATE_MODS_LATCHED; if (a->locked_mods != b->locked_mods) mask |= XKB_STATE_MODS_LOCKED; if (a->leds != b->leds) mask |= XKB_STATE_LEDS; return mask; } /** * Given a particular key event, updates the state structure to reflect the * new modifiers. */ enum xkb_state_component xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc, enum xkb_key_direction direction) { const struct xkb_key* const key = XkbKey(state->keymap, kc); if (!key) return 0; const struct state_components prev_components = state->components; state->set_mods = 0; state->clear_mods = 0; xkb_filter_apply_all(state, key, direction); xkb_mod_index_t i; xkb_mod_mask_t bit; for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) { if (state->set_mods & bit) { state->mod_key_count[i]++; state->components.base_mods |= bit; state->set_mods &= ~bit; } } for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) { if (state->clear_mods & bit) { state->mod_key_count[i]--; if (state->mod_key_count[i] <= 0) { state->components.base_mods &= ~bit; state->mod_key_count[i] = 0; } state->clear_mods &= ~bit; } } xkb_state_update_derived(state); return get_state_component_changes(&prev_components, &state->components); } /* We need fake keys for `update_latch_modifiers` and `update_latch_group`. * These keys must have at least one level in order to break latches. We need 2 * keys with specific actions in order to update group/mod latches without * affecting each other. */ static struct xkb_key_type_entry synthetic_key_level_entry = { 0 }; static struct xkb_key_type synthetic_key_type = { .num_entries = 1, .num_levels = 1, .entries = &synthetic_key_level_entry }; static const struct xkb_key synthetic_key = { 0 }; /* Transcription from xserver: XkbLatchModifiers */ static void update_latch_modifiers(struct xkb_state *state, xkb_mod_mask_t mask, xkb_mod_mask_t latches) { /* Clear affected latched modifiers */ const xkb_mod_mask_t clear = mask & ~latches; state->components.latched_mods &= ~clear; /* Clear any pending latch to locks using ad hoc action: * only affect corresponding modifier latches and no group latch. */ struct xkb_level synthetic_key_level_break_mod_latch = { .num_syms = 0, .num_actions = 1, .upper = XKB_KEY_NoSymbol, .s.sym = XKB_KEY_NoSymbol, .a.action.internal = { .type = ACTION_TYPE_INTERNAL, .flags = INTERNAL_BREAKS_MOD_LATCH, .clear_latched_mods = clear } }; struct xkb_group synthetic_key_group_break_mod_latch = { .type = &synthetic_key_type, .levels = &synthetic_key_level_break_mod_latch }; const struct xkb_key synthetic_key_break_mod_latch = { .num_groups = 1, .groups = &synthetic_key_group_break_mod_latch }; xkb_filter_apply_all(state, &synthetic_key_break_mod_latch, XKB_KEY_DOWN); /* Finally set the latched mods by simulate tapping a key with the * corresponding action */ const struct xkb_key* const key = &synthetic_key; const union xkb_action latch_mods = { .mods = { .type = ACTION_TYPE_MOD_LATCH, .mods = { .mask = mask & latches }, .flags = 0, }, }; struct xkb_filter* const filter = xkb_filter_new(state); filter->key = key; filter->func = xkb_filter_mod_latch_func; filter->action = latch_mods; xkb_filter_mod_latch_new(state, filter); /* We added the filter manually, so only fire “up” event */ xkb_filter_mod_latch_func(state, filter, key, XKB_KEY_UP); } /* Transcription from xserver: XkbLatchGroup */ static void update_latch_group(struct xkb_state *state, int32_t group) { /* Clear any pending latch to locks. */ static struct xkb_level synthetic_key_level_break_group_latch = { .num_syms = 0, .num_actions = 1, .upper = XKB_KEY_NoSymbol, .s.sym = XKB_KEY_NoSymbol, .a.action.internal = { .type = ACTION_TYPE_INTERNAL, .flags = INTERNAL_BREAKS_GROUP_LATCH, .clear_latched_mods = 0 } }; static struct xkb_group synthetic_key_group_break_group_latch = { .type = &synthetic_key_type, .levels = &synthetic_key_level_break_group_latch }; static const struct xkb_key synthetic_key_break_group_latch = { .num_groups = 1, .groups = &synthetic_key_group_break_group_latch }; xkb_filter_apply_all(state, &synthetic_key_break_group_latch, XKB_KEY_DOWN); /* Simulate tapping a key with a group latch action, but in isolation: i.e. * without affecting the other filters. */ const struct xkb_key* const key = &synthetic_key; const union xkb_action latch_group = { .group = { .type = ACTION_TYPE_GROUP_LATCH, .flags = ACTION_ABSOLUTE_SWITCH, .group = group, }, }; struct xkb_filter* const filter = xkb_filter_new(state); filter->key = key; filter->func = xkb_filter_group_latch_func; filter->action = latch_group; xkb_filter_group_latch_new(state, filter); /* We added the filter manually, so only fire “up” event */ xkb_filter_group_latch_func(state, filter, key, XKB_KEY_UP); } /** * Compute the resolved effective mask of an arbitrary input. * * Contrary to `mod_mask_get_effective`, it resolves only modifiers not present * in the canonical mask, so that it enables `xkb_state_serialize_mods` to * round trip via `xkb_state_update_mask`. */ static inline xkb_mod_mask_t resolve_to_canonical_mods(struct xkb_keymap *keymap, xkb_mod_mask_t mods) { return /* * Keep canonical modifier mask. * It contains either real modifiers or canonical virtual modifiers. */ (mods & keymap->canonical_state_mask) | /* Resolve other modifiers */ mod_mask_get_effective(keymap, mods & ~keymap->canonical_state_mask); } enum xkb_state_component xkb_state_update_latched_locked(struct xkb_state *state, xkb_mod_mask_t affect_latched_mods, xkb_mod_mask_t latched_mods, bool affect_latched_layout, int32_t latched_layout, xkb_mod_mask_t affect_locked_mods, xkb_mod_mask_t locked_mods, bool affect_locked_layout, int32_t locked_layout) { const struct state_components prev_components = state->components; /* Update locks */ affect_locked_mods = resolve_to_canonical_mods(state->keymap, affect_locked_mods); if (affect_locked_mods) { locked_mods = resolve_to_canonical_mods(state->keymap, locked_mods); state->components.locked_mods &= ~affect_locked_mods; state->components.locked_mods |= locked_mods & affect_locked_mods; } if (affect_locked_layout) { state->components.locked_group = locked_layout; } /* Update latches */ affect_latched_mods = resolve_to_canonical_mods(state->keymap, affect_latched_mods); if (affect_latched_mods) { latched_mods = resolve_to_canonical_mods(state->keymap, latched_mods); update_latch_modifiers(state, affect_latched_mods, latched_mods); } if (affect_latched_layout) { update_latch_group(state, latched_layout); } xkb_state_update_derived(state); return get_state_component_changes(&prev_components, &state->components); } /** * Updates the state from a set of explicit masks as gained from * xkb_state_serialize_mods and xkb_state_serialize_groups. As noted in the * documentation for these functions in xkbcommon.h, this round-trip is * lossy, and should only be used to update a slave state mirroring the * master, e.g. in a client/server window system. */ enum xkb_state_component xkb_state_update_mask(struct xkb_state *state, xkb_mod_mask_t base_mods, xkb_mod_mask_t latched_mods, xkb_mod_mask_t locked_mods, xkb_layout_index_t base_group, xkb_layout_index_t latched_group, xkb_layout_index_t locked_group) { const struct state_components prev_components = state->components; /* * Make sure the mods are fully resolved - since we get arbitrary * input, they might not be. * * It might seem more reasonable to do this only for components.mods * in xkb_state_update_derived(), rather than for each component * separately. That would allow to distinguish between "really" * depressed mods (would be in MODS_DEPRESSED) and indirectly * depressed to to a mapping (would only be in MODS_EFFECTIVE). * However, the traditional behavior of xkb_state_update_key() is that * if a vmod is depressed, its mappings are depressed with it; so we're * expected to do the same here. Also, LEDs (usually) look if a real * mod is locked, not just effective; otherwise it won't be lit. */ state->components.base_mods = resolve_to_canonical_mods(state->keymap, base_mods); state->components.latched_mods = resolve_to_canonical_mods(state->keymap, latched_mods); state->components.locked_mods = resolve_to_canonical_mods(state->keymap, locked_mods); static_assert(XKB_MAX_GROUPS < INT32_MAX, "Max groups don't fit"); state->components.base_group = (int32_t) base_group; state->components.latched_group = (int32_t) latched_group; state->components.locked_group = (int32_t) locked_group; xkb_state_update_derived(state); return get_state_component_changes(&prev_components, &state->components); } /* * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier */ static bool should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc) { return xkb_state_mod_index_is_active(state, XKB_MOD_INDEX_CAPS, XKB_STATE_MODS_EFFECTIVE) > 0 && xkb_state_mod_index_is_consumed(state, kc, XKB_MOD_INDEX_CAPS) == 0; } /* * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier */ static bool should_do_ctrl_transformation(struct xkb_state *state, xkb_keycode_t kc) { return xkb_state_mod_index_is_active(state, XKB_MOD_INDEX_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0 && xkb_state_mod_index_is_consumed(state, kc, XKB_MOD_INDEX_CTRL) == 0; } /** * Provides the symbols to use for the given key and state. Returns the * number of symbols pointed to in syms_out. */ int xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc, const xkb_keysym_t **syms_out) { const xkb_layout_index_t layout = xkb_state_key_get_layout(state, kc); if (layout == XKB_LAYOUT_INVALID) goto err; const xkb_level_index_t level = xkb_state_key_get_level(state, kc, layout); if (level == XKB_LEVEL_INVALID) goto err; const struct xkb_key* const key = XkbKey(state->keymap, kc); if (!key) goto err; const struct xkb_level* const leveli = xkb_keymap_key_get_level(state->keymap, key, layout, level); if (!leveli) goto err; const xkb_keysym_count_t num_syms = leveli->num_syms; if (num_syms == 0) goto err; if (should_do_caps_transformation(state, kc)) { /* Only simple capitalization rules: keysyms count is unchanged. */ if (num_syms > 1) { *syms_out = (leveli->has_upper) ? leveli->s.syms + num_syms : leveli->s.syms; } else { *syms_out = &leveli->upper; } } else { *syms_out = (num_syms > 1) ? leveli->s.syms : &leveli->s.sym; } return (int) num_syms; err: *syms_out = NULL; return 0; } /* * Verbatim from `libX11:src/xkb/XKBBind.c`. * * The basic transformations are defined in “[Interpreting the Control Modifier]”. * They correspond to the [caret notation], which maps the characters * `@ABC...XYZ[\]^_` by masking them with `0x1f`. Note that there is no * transformation for `?`, although `^?` is defined in the [caret notation]. * * For convenience, the range ```abc...xyz{|}~`` and the space character ` ` * are processed the same way. This allow to produce control characters without * requiring the use of the `Shift` modifier for letters. * * The transformation of the digits seems to originate from the [VT220 terminal], * as a compatibility for non-US keyboards. Indeed, these keyboards may not have * the punctuation characters available or in a convenient position. Some mnemonics: * * - ^2 maps to ^@ because @ is on the key 2 in the US layout. * - ^6 maps to ^^ because ^ is on the key 6 in the US layout. * - characters 3, 4, 5, 6, and 7 seems to align with the sequence `[\]^_`. * - 8 closes the sequence and so maps to the last control character. * * The `/` transformation seems to be defined for compatibility or convenience. * * [Interpreting the Control Modifier]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier * [caret notation]: https://en.wikipedia.org/wiki/Caret_notation * [VT220 terminal]: https://vt100.net/docs/vt220-rm/chapter3.html#T3-5 */ static char XkbToControl(char ch) { char c = ch; if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F; else if (c == '2') c = '\000'; else if (c >= '3' && c <= '7') c -= ('3' - '\033'); else if (c == '8') c = '\177'; else if (c == '/') c = '_' & 0x1F; return c; } /** * Provides either exactly one symbol, or XKB_KEY_NoSymbol. */ xkb_keysym_t xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc) { const xkb_keysym_t *syms = NULL; const int num_syms = xkb_state_key_get_syms(state, kc, &syms); if (num_syms != 1) return XKB_KEY_NoSymbol; else return syms[0]; } /* * The caps and ctrl transformations require some special handling, * so we cannot simply use xkb_state_get_one_sym() for them. * In particular, if Control is set, we must try very hard to find * some layout in which the keysym is ASCII and thus can be (maybe) * converted to a control character. libX11 allows to disable this * behavior with the XkbLC_ControlFallback (see XkbSetXlibControls(3)), * but it is enabled by default, yippee. */ static xkb_keysym_t get_one_sym_for_string(struct xkb_state *state, xkb_keycode_t kc) { const xkb_layout_index_t layout = xkb_state_key_get_layout(state, kc); const xkb_layout_index_t num_layouts = xkb_keymap_num_layouts_for_key(state->keymap, kc); xkb_level_index_t level = xkb_state_key_get_level(state, kc, layout); if (layout == XKB_LAYOUT_INVALID || num_layouts == 0 || level == XKB_LEVEL_INVALID) return XKB_KEY_NoSymbol; const xkb_keysym_t *syms = NULL; int nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level, &syms); if (nsyms != 1) return XKB_KEY_NoSymbol; xkb_keysym_t sym = syms[0]; if (should_do_ctrl_transformation(state, kc) && sym > 127u) { for (xkb_layout_index_t i = 0; i < num_layouts; i++) { level = xkb_state_key_get_level(state, kc, i); if (level == XKB_LEVEL_INVALID) continue; nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc, i, level, &syms); if (nsyms == 1 && syms[0] <= 127u) { sym = syms[0]; break; } } } if (should_do_caps_transformation(state, kc)) { sym = xkb_keysym_to_upper(sym); } return sym; } int xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t kc, char *buffer, size_t size) { int nsyms; const xkb_keysym_t *syms = NULL; const xkb_keysym_t sym = get_one_sym_for_string(state, kc); if (sym != XKB_KEY_NoSymbol) { nsyms = 1; syms = &sym; } else { nsyms = xkb_state_key_get_syms(state, kc, &syms); } /* Make sure not to truncate in the middle of a UTF-8 sequence. */ int offset = 0; char tmp[XKB_KEYSYM_UTF8_MAX_SIZE]; for (int i = 0; i < nsyms; i++) { int ret = xkb_keysym_to_utf8(syms[i], tmp, sizeof(tmp)); if (ret <= 0) goto err_bad; ret--; if ((size_t) offset + ret <= size) memcpy(buffer + offset, tmp, ret); offset += ret; } if ((size_t) offset >= size) goto err_trunc; buffer[offset] = '\0'; if (!is_valid_utf8(buffer, offset)) goto err_bad; if (offset == 1 && (unsigned int) buffer[0] <= 127u && should_do_ctrl_transformation(state, kc)) buffer[0] = XkbToControl(buffer[0]); return offset; err_trunc: if (size > 0) buffer[size - 1] = '\0'; return offset; err_bad: if (size > 0) buffer[0] = '\0'; return 0; } uint32_t xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t kc) { const xkb_keysym_t sym = get_one_sym_for_string(state, kc); uint32_t cp = xkb_keysym_to_utf32(sym); if (cp <= 127u && should_do_ctrl_transformation(state, kc)) cp = (uint32_t) XkbToControl((char) cp); return cp; } /** * Serialises the requested modifier state into an xkb_mod_mask_t, with all * the same disclaimers as in xkb_state_update_mask. */ xkb_mod_mask_t xkb_state_serialize_mods(struct xkb_state *state, enum xkb_state_component type) { xkb_mod_mask_t ret = 0; if (type & XKB_STATE_MODS_EFFECTIVE) return state->components.mods; if (type & XKB_STATE_MODS_DEPRESSED) ret |= state->components.base_mods; if (type & XKB_STATE_MODS_LATCHED) ret |= state->components.latched_mods; if (type & XKB_STATE_MODS_LOCKED) ret |= state->components.locked_mods; return ret; } /** * Serialises the requested group state, with all the same disclaimers as * in xkb_state_update_mask. */ xkb_layout_index_t xkb_state_serialize_layout(struct xkb_state *state, enum xkb_state_component type) { xkb_layout_index_t ret = 0; if (type & XKB_STATE_LAYOUT_EFFECTIVE) return state->components.group; if (type & XKB_STATE_LAYOUT_DEPRESSED) ret += state->components.base_group; if (type & XKB_STATE_LAYOUT_LATCHED) ret += state->components.latched_group; if (type & XKB_STATE_LAYOUT_LOCKED) ret += state->components.locked_group; return ret; } /** * Gets a modifier mask and returns the resolved effective mask; this * is needed because some modifiers can also map to other modifiers, e.g. * the "NumLock" modifier usually also sets the "Mod2" modifier. */ xkb_mod_mask_t mod_mask_get_effective(struct xkb_keymap *keymap, xkb_mod_mask_t mods) { /* Initialize the effective mask with its corresponding real mods. */ xkb_mod_mask_t mask = mods & MOD_REAL_MASK_ALL; /* Resolve the virtual modifiers */ const struct xkb_mod *mod; xkb_mod_index_t i; xkb_vmods_enumerate(i, mod, &keymap->mods) if (mods & (UINT32_C(1) << i)) mask |= mod->mapping; return mask; } /** * Returns 1 if the given modifier is active with the specified type(s), 0 if * not, or -1 if the modifier is invalid. */ int xkb_state_mod_index_is_active(struct xkb_state *state, xkb_mod_index_t idx, enum xkb_state_component type) { if (unlikely(idx >= xkb_keymap_num_mods(state->keymap))) return -1; const xkb_mod_mask_t mapping = state->keymap->mods.mods[idx].mapping; if (!mapping) { /* Modifier not mapped */ return 0; } /* WARNING: this may overmatch for virtual modifiers */ return (xkb_state_serialize_mods(state, type) & mapping) == mapping; } /** * Helper function for xkb_state_mod_indices_are_active and * xkb_state_mod_names_are_active. */ static bool match_mod_masks(struct xkb_state *state, enum xkb_state_component type, enum xkb_state_match match, xkb_mod_mask_t wanted) { const xkb_mod_mask_t active = xkb_state_serialize_mods(state, type); if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted)) return false; if (match & XKB_STATE_MATCH_ANY) return active & wanted; return (active & wanted) == wanted; } /** * Returns 1 if the modifiers are active with the specified type(s), 0 if * not, or -1 if any of the modifiers are invalid. */ int xkb_state_mod_indices_are_active(struct xkb_state *state, enum xkb_state_component type, enum xkb_state_match match, ...) { va_list ap; xkb_mod_mask_t wanted = 0; int ret = 0; const xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap); va_start(ap, match); while (1) { xkb_mod_index_t idx = va_arg(ap, xkb_mod_index_t); if (idx == XKB_MOD_INVALID) break; if (unlikely(idx >= num_mods)) { ret = -1; break; } wanted |= state->keymap->mods.mods[idx].mapping; } va_end(ap); if (ret == -1) return ret; if (!wanted) { /* Modifiers not mapped */ return 0; } return match_mod_masks(state, type, match, wanted); } /** * Returns 1 if the given modifier is active with the specified type(s), 0 if * not, or -1 if the modifier is invalid. */ int xkb_state_mod_name_is_active(struct xkb_state *state, const char *name, enum xkb_state_component type) { const xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name); if (idx == XKB_MOD_INVALID) return -1; return xkb_state_mod_index_is_active(state, idx, type); } /** * Returns 1 if the modifiers are active with the specified type(s), 0 if * not, or -1 if any of the modifiers are invalid. */ ATTR_NULL_SENTINEL int xkb_state_mod_names_are_active(struct xkb_state *state, enum xkb_state_component type, enum xkb_state_match match, ...) { va_list ap; xkb_mod_mask_t wanted = 0; int ret = 0; va_start(ap, match); while (1) { const char *str = va_arg(ap, const char *); if (str == NULL) break; const xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, str); if (idx == XKB_MOD_INVALID) { ret = -1; break; } wanted |= state->keymap->mods.mods[idx].mapping; } va_end(ap); if (ret == -1) return ret; if (!wanted) { /* Modifiers not mapped */ return 0; } return match_mod_masks(state, type, match, wanted); } /** * Returns 1 if the given group is active with the specified type(s), 0 if * not, or -1 if the group is invalid. */ int xkb_state_layout_index_is_active(struct xkb_state *state, xkb_layout_index_t idx, enum xkb_state_component type) { if (idx >= state->keymap->num_groups) return -1; int ret = 0; if (type & XKB_STATE_LAYOUT_EFFECTIVE) ret |= (state->components.group == idx); if (type & XKB_STATE_LAYOUT_DEPRESSED) ret |= (state->components.base_group == (int32_t) idx); if (type & XKB_STATE_LAYOUT_LATCHED) ret |= (state->components.latched_group == (int32_t) idx); if (type & XKB_STATE_LAYOUT_LOCKED) ret |= (state->components.locked_group == (int32_t) idx); return ret; } /** * Returns 1 if the given modifier is active with the specified type(s), 0 if * not, or -1 if the modifier is invalid. */ int xkb_state_layout_name_is_active(struct xkb_state *state, const char *name, enum xkb_state_component type) { const xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name); if (idx == XKB_LAYOUT_INVALID) return -1; return xkb_state_layout_index_is_active(state, idx, type); } /** * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid. */ int xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx) { if (idx >= state->keymap->num_leds || state->keymap->leds[idx].name == XKB_ATOM_NONE) return -1; return !!(state->components.leds & (UINT32_C(1) << idx)); } /** * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid. */ int xkb_state_led_name_is_active(struct xkb_state *state, const char *name) { const xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name); if (idx == XKB_LED_INVALID) return -1; return xkb_state_led_index_is_active(state, idx); } /** * See: * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11. * - MyEnhancedXkbTranslateKeyCode(), a modification of the above, from GTK+. */ static xkb_mod_mask_t key_get_consumed(struct xkb_state *state, const struct xkb_key *key, enum xkb_consumed_mode mode) { const xkb_layout_index_t group = xkb_state_key_get_layout(state, key->keycode); if (group == XKB_LAYOUT_INVALID) return 0; xkb_mod_mask_t preserve = 0; xkb_mod_mask_t consumed = 0; const struct xkb_key_type_entry* const matching_entry = get_entry_for_key_state(state, key, group); if (matching_entry) preserve = matching_entry->preserve.mask; const struct xkb_key_type* const type = key->groups[group].type; switch (mode) { case XKB_CONSUMED_MODE_XKB: consumed = type->mods.mask; break; case XKB_CONSUMED_MODE_GTK: { const struct xkb_key_type_entry* const no_mods_entry = get_entry_for_mods(type, 0); const xkb_level_index_t no_mods_leveli = no_mods_entry ? no_mods_entry->level : 0; const struct xkb_level* const no_mods_level = &key->groups[group].levels[no_mods_leveli]; for (darray_size_t i = 0; i < type->num_entries; i++) { const struct xkb_key_type_entry* const entry = &type->entries[i]; if (!entry_is_active(entry)) continue; const struct xkb_level* const level = &key->groups[group].levels[entry->level]; if (XkbLevelsSameSyms(level, no_mods_level)) continue; if (entry == matching_entry || one_bit_set(entry->mods.mask)) consumed |= entry->mods.mask & ~entry->preserve.mask; } break; } } return consumed & ~preserve; } int xkb_state_mod_index_is_consumed2(struct xkb_state *state, xkb_keycode_t kc, xkb_mod_index_t idx, enum xkb_consumed_mode mode) { const struct xkb_key* const key = XkbKey(state->keymap, kc); if (unlikely(!key || idx >= xkb_keymap_num_mods(state->keymap))) return -1; const xkb_mod_mask_t mapping = state->keymap->mods.mods[idx].mapping; if (!mapping) { /* Modifier not mapped */ return 0; } return (mapping & key_get_consumed(state, key, mode)) == mapping; } int xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc, xkb_mod_index_t idx) { return xkb_state_mod_index_is_consumed2(state, kc, idx, XKB_CONSUMED_MODE_XKB); } xkb_mod_mask_t xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc, xkb_mod_mask_t mask) { const struct xkb_key* const key = XkbKey(state->keymap, kc); if (!key) return 0; return resolve_to_canonical_mods(state->keymap, mask) & ~key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB); } xkb_mod_mask_t xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc, enum xkb_consumed_mode mode) { switch (mode) { case XKB_CONSUMED_MODE_XKB: case XKB_CONSUMED_MODE_GTK: break; default: log_err_func(state->keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized consumed modifiers mode: %d\n", mode); return 0; } const struct xkb_key* const key = XkbKey(state->keymap, kc); if (!key) return 0; return key_get_consumed(state, key, mode); } xkb_mod_mask_t xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc) { return xkb_state_key_get_consumed_mods2(state, kc, XKB_CONSUMED_MODE_XKB); } xkbcommon-libxkbcommon-54ee7ac/src/text.c000066400000000000000000000216351510033435100206110ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #include "config.h" #include #include "keymap.h" #include "keysym.h" #include "text.h" bool LookupString(const LookupEntry tab[], const char *string, unsigned int *value_rtrn) { if (!string) return false; for (const LookupEntry *entry = tab; entry->name; entry++) { if (istreq(entry->name, string)) { *value_rtrn = entry->value; return true; } } return false; } const char * LookupValue(const LookupEntry tab[], unsigned int value) { for (const LookupEntry *entry = tab; entry->name; entry++) if (entry->value == value) return entry->name; return NULL; } const LookupEntry ctrlMaskNames[] = { { "RepeatKeys", CONTROL_REPEAT }, { "Repeat", CONTROL_REPEAT }, { "AutoRepeat", CONTROL_REPEAT }, { "SlowKeys", CONTROL_SLOW }, { "BounceKeys", CONTROL_DEBOUNCE }, { "StickyKeys", CONTROL_STICKY }, { "MouseKeys", CONTROL_MOUSEKEYS }, { "MouseKeysAccel", CONTROL_MOUSEKEYS_ACCEL }, { "AccessXKeys", CONTROL_AX }, { "AccessXTimeout", CONTROL_AX_TIMEOUT }, { "AccessXFeedback", CONTROL_AX_FEEDBACK }, { "AudibleBell", CONTROL_BELL }, { "IgnoreGroupLock", CONTROL_IGNORE_GROUP_LOCK }, { "all", CONTROL_ALL }, { "none", 0 }, { "Overlay1", 0 }, { "Overlay2", 0 }, { NULL, 0 } }; const LookupEntry modComponentMaskNames[] = { { "base", XKB_STATE_MODS_DEPRESSED }, { "latched", XKB_STATE_MODS_LATCHED }, { "locked", XKB_STATE_MODS_LOCKED }, { "effective", XKB_STATE_MODS_EFFECTIVE }, { "compat", XKB_STATE_MODS_EFFECTIVE }, { "any", XKB_STATE_MODS_EFFECTIVE }, { "none", 0 }, { NULL, 0 } }; const LookupEntry groupComponentMaskNames[] = { { "base", XKB_STATE_LAYOUT_DEPRESSED }, { "latched", XKB_STATE_LAYOUT_LATCHED }, { "locked", XKB_STATE_LAYOUT_LOCKED }, { "effective", XKB_STATE_LAYOUT_EFFECTIVE }, { "any", XKB_STATE_LAYOUT_EFFECTIVE }, { "none", 0 }, { NULL, 0 } }; const LookupEntry groupMaskNames[] = { { "none", 0x00 }, { "all", XKB_ALL_GROUPS }, { NULL, 0 } }; const LookupEntry buttonNames[] = { { "Button1", 1 }, { "Button2", 2 }, { "Button3", 3 }, { "Button4", 4 }, { "Button5", 5 }, { "default", 0 }, { NULL, 0 } }; const LookupEntry useModMapValueNames[] = { { "LevelOne", 1 }, { "Level1", 1 }, { "AnyLevel", 0 }, { "any", 0 }, { NULL, 0 } }; const LookupEntry actionTypeNames[] = { { "NoAction", ACTION_TYPE_NONE }, { "VoidAction", ACTION_TYPE_VOID }, { "SetMods", ACTION_TYPE_MOD_SET }, { "LatchMods", ACTION_TYPE_MOD_LATCH }, { "LockMods", ACTION_TYPE_MOD_LOCK }, { "SetGroup", ACTION_TYPE_GROUP_SET }, { "LatchGroup", ACTION_TYPE_GROUP_LATCH }, { "LockGroup", ACTION_TYPE_GROUP_LOCK }, { "MovePtr", ACTION_TYPE_PTR_MOVE }, { "MovePointer", ACTION_TYPE_PTR_MOVE }, { "PtrBtn", ACTION_TYPE_PTR_BUTTON }, { "PointerButton", ACTION_TYPE_PTR_BUTTON }, { "LockPtrBtn", ACTION_TYPE_PTR_LOCK }, { "LockPtrButton", ACTION_TYPE_PTR_LOCK }, { "LockPointerButton", ACTION_TYPE_PTR_LOCK }, { "LockPointerBtn", ACTION_TYPE_PTR_LOCK }, { "SetPtrDflt", ACTION_TYPE_PTR_DEFAULT }, { "SetPointerDefault", ACTION_TYPE_PTR_DEFAULT }, { "Terminate", ACTION_TYPE_TERMINATE }, { "TerminateServer", ACTION_TYPE_TERMINATE }, { "SwitchScreen", ACTION_TYPE_SWITCH_VT }, { "SetControls", ACTION_TYPE_CTRL_SET }, { "LockControls", ACTION_TYPE_CTRL_LOCK }, { "Private", ACTION_TYPE_PRIVATE }, /* deprecated actions below here - unused */ { "RedirectKey", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "Redirect", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "ISOLock", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "ActionMessage", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "MessageAction", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "Message", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "DeviceBtn", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "DevBtn", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "DevButton", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "DeviceButton", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "LockDeviceBtn", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "LockDevBtn", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "LockDevButton", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "LockDeviceButton", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "DeviceValuator", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "DevVal", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "DeviceVal", ACTION_TYPE_UNSUPPORTED_LEGACY }, { "DevValuator", ACTION_TYPE_UNSUPPORTED_LEGACY }, { NULL, 0 }, }; const LookupEntry symInterpretMatchMaskNames[] = { { "NoneOf", MATCH_NONE }, { "AnyOfOrNone", MATCH_ANY_OR_NONE }, { "AnyOf", MATCH_ANY }, { "AllOf", MATCH_ALL }, { "Exactly", MATCH_EXACTLY }, { NULL, 0 }, }; const char * ModIndexText(struct xkb_context *ctx, const struct xkb_mod_set *mods, xkb_mod_index_t ndx) { if (ndx == XKB_MOD_INVALID) return "none"; if (ndx == XKB_MOD_NONE) return "None"; if (ndx >= mods->num_mods) return NULL; return xkb_atom_text(ctx, mods->mods[ndx].name); } const char * ActionTypeText(enum xkb_action_type type) { const char *name = LookupValue(actionTypeNames, type); return name ? name : "Private"; } const char * KeysymText(struct xkb_context *ctx, xkb_keysym_t sym) { char *buffer = xkb_context_get_buffer(ctx, XKB_KEYSYM_NAME_MAX_SIZE); xkb_keysym_get_name(sym, buffer, XKB_KEYSYM_NAME_MAX_SIZE); return buffer; } const char * KeyNameText(struct xkb_context *ctx, xkb_atom_t name) { const char *sname = xkb_atom_text(ctx, name); size_t len = strlen_safe(sname) + 3; char *buf = xkb_context_get_buffer(ctx, len); snprintf(buf, len, "<%s>", strempty(sname)); return buf; } const char * SIMatchText(enum xkb_match_operation type) { return LookupValue(symInterpretMatchMaskNames, type); } const char * ModMaskText(struct xkb_context *ctx, enum mod_type type, const struct xkb_mod_set *mods, xkb_mod_mask_t mask) { char buf[1024] = {0}; size_t pos = 0; const struct xkb_mod *mod; /* We want to avoid boolean blindness, but we expected only 2 values */ assert(type == MOD_REAL || type == MOD_BOTH); if (mask == 0) return "none"; if (mask == MOD_REAL_MASK_ALL) return "all"; if ((type == MOD_REAL && (mask & ~MOD_REAL_MASK_ALL)) || unlikely(mask & ~((UINT64_C(1) << mods->num_mods) - 1))) { /* If we get a mask that cannot be expressed with the known modifiers * of the given type, print it as hexadecimal */ const int ret = snprintf(buf, sizeof(buf), "0x%"PRIx32, mask); static_assert(sizeof(mask) == 4 && sizeof(buf) >= sizeof("0xffffffff"), "Buffer too small"); assert(ret >= 0 && (size_t) ret < sizeof(buf)); pos = (size_t) ret; } else { /* Print known mods */ xkb_mods_mask_foreach(mask, mod, mods) { int ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s", pos == 0 ? "" : "+", xkb_atom_text(ctx, mod->name)); if (ret <= 0 || pos + ret >= sizeof(buf)) break; else pos += ret; } } pos++; return memcpy(xkb_context_get_buffer(ctx, pos), buf, pos); } const char * LedStateMaskText(struct xkb_context *ctx, const LookupEntry *lookup, enum xkb_state_component mask) { char buf[1024]; size_t pos = 0; if (mask == 0) return "0"; for (unsigned int i = 0; mask; i++) { int ret; if (!(mask & (1u << i))) continue; mask &= ~(1u << i); const char* const maskText = LookupValue(lookup, 1u << i); assert(maskText != NULL); ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s", pos == 0 ? "" : "+", maskText); if (ret <= 0 || pos + ret >= sizeof(buf)) break; else pos += ret; } pos++; return memcpy(xkb_context_get_buffer(ctx, pos), buf, pos); } const char * ControlMaskText(struct xkb_context *ctx, enum xkb_action_controls mask) { char buf[1024]; size_t pos = 0; if (mask == 0) return "none"; if (mask == CONTROL_ALL) return "all"; for (unsigned int i = 0; mask; i++) { int ret; if (!(mask & (1u << i))) continue; mask &= ~(1u << i); const char* const maskText = LookupValue(ctrlMaskNames, 1u << i); assert(maskText != NULL); ret = snprintf(buf + pos, sizeof(buf) - pos, "%s%s", pos == 0 ? "" : "+", maskText); if (ret <= 0 || pos + ret >= sizeof(buf)) break; else pos += ret; } pos++; return memcpy(xkb_context_get_buffer(ctx, pos), buf, pos); } xkbcommon-libxkbcommon-54ee7ac/src/text.h000066400000000000000000000030251510033435100206070ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "atom.h" #include "keymap.h" typedef struct { const char *name; uint32_t value; } LookupEntry; bool LookupString(const LookupEntry tab[], const char *string, unsigned int *value_rtrn); const char * LookupValue(const LookupEntry tab[], unsigned int value); extern const LookupEntry ctrlMaskNames[]; extern const LookupEntry modComponentMaskNames[]; extern const LookupEntry groupComponentMaskNames[]; extern const LookupEntry groupMaskNames[]; extern const LookupEntry buttonNames[]; extern const LookupEntry useModMapValueNames[]; extern const LookupEntry actionTypeNames[]; extern const LookupEntry symInterpretMatchMaskNames[]; const char * ModMaskText(struct xkb_context *ctx, enum mod_type type, const struct xkb_mod_set *mods, xkb_mod_mask_t mask); const char * ModIndexText(struct xkb_context *ctx, const struct xkb_mod_set *mods, xkb_mod_index_t ndx); const char * ActionTypeText(enum xkb_action_type type); const char * KeysymText(struct xkb_context *ctx, xkb_keysym_t sym); const char * KeyNameText(struct xkb_context *ctx, xkb_atom_t name); const char * SIMatchText(enum xkb_match_operation type); const char * LedStateMaskText(struct xkb_context *ctx, const LookupEntry *lookup, enum xkb_state_component mask); const char * ControlMaskText(struct xkb_context *ctx, enum xkb_action_controls mask); xkbcommon-libxkbcommon-54ee7ac/src/utf8-decoding.c000066400000000000000000000051411510033435100222570ustar00rootroot00000000000000/* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include "utils.h" #include "utf8-decoding.h" /* Array mapping the leading byte to the length of a UTF-8 sequence. * A value of zero indicates that the byte can not begin a UTF-8 sequence. */ static const uint8_t utf8_sequence_length_by_leading_byte[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00-0x0F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x10-0x1F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x20-0x2F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x30-0x3F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x40-0x4F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x50-0x5F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x60-0x6F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x70-0x7F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80-0x8F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90-0x9F */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0-0xAF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0-0xBF */ 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xC0-0xCF */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xD0-0xDF */ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xE0-0xEF */ 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xF0-0xFF */ }; /* Length of next utf-8 sequence */ uint8_t utf8_sequence_length(const char *s) { return utf8_sequence_length_by_leading_byte[(unsigned char)s[0]]; } /* Reads the next UTF-8 sequence in a string */ uint32_t utf8_next_code_point(const char *s, size_t max_size, size_t *size_out) { uint32_t cp = 0; uint8_t len = utf8_sequence_length(s); *size_out = 0; if (!max_size || len > max_size) return INVALID_UTF8_CODE_POINT; /* Handle leading byte */ switch (len) { case 1: *size_out = 1; return (uint32_t)s[0]; case 2: cp = (uint32_t)s[0] & 0x1f; break; case 3: cp = (uint32_t)s[0] & 0x0f; break; case 4: cp = (uint32_t)s[0] & 0x07; break; default: return INVALID_UTF8_CODE_POINT; } /* Process remaining bytes of the UTF-8 sequence */ for (size_t k = 1; k < len; k++) { if (((uint32_t)s[k] & 0xc0) != 0x80) return INVALID_UTF8_CODE_POINT; cp <<= 6; cp |= (uint32_t)s[k] & 0x3f; } /* Check surrogates */ if (is_surrogate(cp)) return INVALID_UTF8_CODE_POINT; *size_out = len; return cp; } xkbcommon-libxkbcommon-54ee7ac/src/utf8-decoding.h000066400000000000000000000006731510033435100222710ustar00rootroot00000000000000/* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include /* Check if a char is the start of a UTF-8 sequence */ #define is_utf8_start(c) (((c) & 0xc0) != 0x80) #define INVALID_UTF8_CODE_POINT UINT32_MAX uint8_t utf8_sequence_length(const char *s); uint32_t utf8_next_code_point(const char *s, size_t max_size, size_t *size_out); xkbcommon-libxkbcommon-54ee7ac/src/utf8.c000066400000000000000000000064061510033435100205120ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * Copyright © 2014 Ran Benita * SPDX-License-Identifier: MIT * * Author: Rob Bradford */ #include "config.h" #include "utils.h" #include "utf8.h" /* Conformant encoding form conversion from UTF-32 to UTF-8. * * See https://www.unicode.org/versions/Unicode15.0.0/ch03.pdf#G28875 * for further details. */ int utf32_to_utf8(uint32_t unichar, char *buffer) { int count, shift, length; uint8_t head; /* NOLINTBEGIN(bugprone-branch-clone) */ if (unichar <= 0x007f) { buffer[0] = (char) unichar; buffer[1] = '\0'; return 2; } else if (unichar <= 0x07FF) { length = 2; head = 0xc0; } /* Handle surrogates */ else if (is_surrogate(unichar)) { goto ill_formed_code_unit_subsequence; } else if (unichar <= 0xffff) { length = 3; head = 0xe0; } else if (unichar <= 0x10ffff) { length = 4; head = 0xf0; } else { goto ill_formed_code_unit_subsequence; } /* NOLINTEND(bugprone-branch-clone) */ for (count = length - 1, shift = 0; count > 0; count--, shift += 6) buffer[count] = (char)(0x80 | ((unichar >> shift) & 0x3f)); buffer[0] = (char)(head | ((unichar >> shift) & 0x3f)); buffer[length] = '\0'; return length + 1; ill_formed_code_unit_subsequence: buffer[0] = '\0'; return 0; } bool is_valid_utf8(const char *ss, size_t len) { size_t i = 0; size_t tail_bytes = 0; const uint8_t *s = (const uint8_t *) ss; /* This beauty is from: * The Unicode Standard Version 6.2 - Core Specification, Table 3.7 * https://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G7404 * We can optimize if needed. */ while (i < len) { /* NOLINTBEGIN(bugprone-branch-clone) */ if (s[i] <= 0x7F) { tail_bytes = 0; } else if (s[i] >= 0xC2 && s[i] <= 0xDF) { tail_bytes = 1; } else if (s[i] == 0xE0) { i++; if (i >= len || !(s[i] >= 0xA0 && s[i] <= 0xBF)) return false; tail_bytes = 1; } else if (s[i] >= 0xE1 && s[i] <= 0xEC) { tail_bytes = 2; } else if (s[i] == 0xED) { i++; if (i >= len || !(s[i] >= 0x80 && s[i] <= 0x9F)) return false; tail_bytes = 1; } else if (s[i] >= 0xEE && s[i] <= 0xEF) { tail_bytes = 2; } else if (s[i] == 0xF0) { i++; if (i >= len || !(s[i] >= 0x90 && s[i] <= 0xBF)) return false; tail_bytes = 2; } else if (s[i] >= 0xF1 && s[i] <= 0xF3) { tail_bytes = 3; } else if (s[i] == 0xF4) { i++; if (i >= len || !(s[i] >= 0x80 && s[i] <= 0x8F)) return false; tail_bytes = 2; } else { return false; } /* NOLINTEND(bugprone-branch-clone) */ i++; while (i < len && tail_bytes > 0 && s[i] >= 0x80 && s[i] <= 0xBF) { i++; tail_bytes--; } if (tail_bytes != 0) return false; } return true; } xkbcommon-libxkbcommon-54ee7ac/src/utf8.h000066400000000000000000000006611510033435100205140ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * Copyright © 2014 Ran Benita * SPDX-License-Identifier: MIT * * Author: Rob Bradford */ #pragma once #include "config.h" #include #include #include #include "utils.h" XKB_EXPORT_PRIVATE int utf32_to_utf8(uint32_t unichar, char *buffer); XKB_EXPORT_PRIVATE bool is_valid_utf8(const char *ss, size_t len); xkbcommon-libxkbcommon-54ee7ac/src/util-list.c000066400000000000000000000032561510033435100215520ustar00rootroot00000000000000/* * Copyright © 2008-2011 Kristian Høgsberg * Copyright © 2011 Intel Corporation * Copyright © 2013-2015 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "util-list.h" void list_init(struct list *list) { list->prev = list; list->next = list; } void list_insert(struct list *list, struct list *elm) { assert((list->next != NULL && list->prev != NULL) || !"list->next|prev is NULL, possibly missing list_init()"); assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) || !"elm->next|prev is not NULL, list node used twice?"); elm->prev = list; elm->next = list->next; list->next = elm; elm->next->prev = elm; } void list_append(struct list *list, struct list *elm) { assert((list->next != NULL && list->prev != NULL) || !"list->next|prev is NULL, possibly missing list_init()"); assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) || !"elm->next|prev is not NULL, list node used twice?"); elm->next = list; elm->prev = list->prev; list->prev = elm; elm->prev->next = elm; } void list_remove(struct list *elm) { assert((elm->next != NULL && elm->prev != NULL) || !"list->next|prev is NULL, possibly missing list_init()"); elm->prev->next = elm->next; elm->next->prev = elm->prev; elm->next = NULL; elm->prev = NULL; } bool list_empty(const struct list *list) { assert((list->next != NULL && list->prev != NULL) || !"list->next|prev is NULL, possibly missing list_init()"); return list->next == list; } bool list_is_last(const struct list *list, const struct list *elm) { return elm->next == list; } xkbcommon-libxkbcommon-54ee7ac/src/util-list.h000066400000000000000000000031271510033435100215540ustar00rootroot00000000000000/* * Copyright © 2008-2011 Kristian Høgsberg * Copyright © 2011 Intel Corporation * Copyright © 2013-2015 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include /* * This list data structure is a verbatim copy from wayland-util.h from the * Wayland project; except that wl_ prefix has been removed. */ struct list { struct list *prev; struct list *next; }; void list_init(struct list *list); void list_insert(struct list *list, struct list *elm); void list_append(struct list *list, struct list *elm); void list_remove(struct list *elm); bool list_empty(const struct list *list); bool list_is_last(const struct list *list, const struct list *elm); #define container_of(ptr, type, member) \ (__typeof__(type) *)((char *)(ptr) - \ offsetof(__typeof__(type), member)) #define list_first_entry(head, pos, member) \ container_of((head)->next, __typeof__(*(pos)), member) #define list_last_entry(head, pos, member) \ container_of((head)->prev, __typeof__(*(pos)), member) #define list_for_each(pos, head, member) \ for ((pos) = 0, (pos) = list_first_entry(head, pos, member); \ &(pos)->member != (head); \ (pos) = list_first_entry(&(pos)->member, pos, member)) #define list_for_each_safe(pos, tmp, head, member) \ for ((pos) = 0, (tmp) = 0, \ (pos) = list_first_entry(head, pos, member), \ (tmp) = list_first_entry(&(pos)->member, tmp, member); \ &(pos)->member != (head); \ (pos) = (tmp), \ (tmp) = list_first_entry(&(pos)->member, tmp, member)) xkbcommon-libxkbcommon-54ee7ac/src/util-mem.h000066400000000000000000000007331510033435100213570ustar00rootroot00000000000000/* * Copyright © 2020 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include static inline void* _steal(void *ptr) { void **original = (void**)ptr; void *swapped = *original; *original = NULL; return swapped; } /** * Resets the pointer content and resets the data to NULL. */ #ifdef _WIN32 #define steal(ptr_) \ _steal(ptr_) #else #define steal(ptr_) \ (__typeof__(*(ptr_)))_steal(ptr_) #endif xkbcommon-libxkbcommon-54ee7ac/src/utils-checked-arithmetic.h000066400000000000000000000521261510033435100245040ustar00rootroot00000000000000/* * SPDX-License-Identifier: ISC * * Copyright 2023 Justine Alexandra Roberts Tunney * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the * above copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /** * @fileoverview C23 Checked Arithmetic * * This header defines three type generic functions: * * - `bool ckd_add(res, a, b)` * - `bool ckd_sub(res, a, b)` * - `bool ckd_mul(res, a, b)` * * Which allow integer arithmetic errors to be detected. There are many * kinds of integer errors, e.g. overflow, truncation, etc. These funcs * catch them all. Here's an example of how it works: * * uint32_t c; * int32_t a = 0x7fffffff; * int32_t b = 2; * assert(!ckd_add(&c, a, b)); * assert(c == 0x80000001u); * * Experienced C / C++ users should find this example counter-intuitive * because the expression `0x7fffffff + 2` not only overflows it's also * undefined behavior. However here we see it's specified, and does not * result in an error. That's because C23 checked arithmetic is not the * arithmetic you're used to. The new standard changes the mathematics. * * C23 checked arithmetic is defined as performing the arithmetic using * infinite precision and then checking if the resulting value will fit * in the output type. Our example above did not result in an error due * to `0x80000001` being a legal value for `uint32_t`. * * This implementation will use the GNU compiler builtins, when they're * available, only if you don't use build flags like `-std=c11` because * they define `__STRICT_ANSI__` and GCC extensions aren't really ANSI. * Instead, you'll get a pretty good pure C11 and C++11 implementation. * * @see https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3096.pdf * @version 1.0 (2024-12-07) */ #pragma once #include "config.h" #ifdef __has_include #define __ckd_has_include(x) __has_include(x) #else #define __ckd_has_include(x) 0 #endif #if __ckd_has_include() #include #else #define __STDC_VERSION_STDCKDINT_H__ 202311L #if (!defined(__STRICT_ANSI__) && defined(__SIZEOF_INT128__)) #define __ckd_have_int128 #define __ckd_intmax __int128 #elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) #define __ckd_intmax long long #else #define __ckd_intmax long #endif typedef signed __ckd_intmax __ckd_intmax_t; typedef unsigned __ckd_intmax __ckd_uintmax_t; #ifdef __has_builtin #define __ckd_has_builtin(x) __has_builtin(x) #else #define __ckd_has_builtin(x) 0 #endif #if (!defined(__STRICT_ANSI__) && \ ((defined(__GNUC__) && __GNUC__ >= 5 && !defined(__ICC)) || \ (__ckd_has_builtin(__builtin_add_overflow) && \ __ckd_has_builtin(__builtin_sub_overflow) && \ __ckd_has_builtin(__builtin_mul_overflow)))) #define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res)) #define ckd_sub(res, x, y) __builtin_sub_overflow((x), (y), (res)) #define ckd_mul(res, x, y) __builtin_mul_overflow((x), (y), (res)) #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L #define ckd_add(res, a, b) __ckd_expr(add, (res), (a), (b)) #define ckd_sub(res, a, b) __ckd_expr(sub, (res), (a), (b)) #define ckd_mul(res, a, b) __ckd_expr(mul, (res), (a), (b)) #if defined(__GNUC__) || defined(__llvm__) #define __ckd_inline \ extern __inline __attribute__((__gnu_inline__, \ __always_inline__, \ __artificial__)) #else #define __ckd_inline static inline #endif #ifdef __ckd_have_int128 #define __ckd_generic_int128(x, y) , signed __int128: x, unsigned __int128: y #else #define __ckd_generic_int128(x, y) #endif #define __ckd_sign(T) \ ((T)1 << (sizeof(T) * 8 - 1)) #define __ckd_is_signed(x) \ _Generic(x, \ signed char: 1, \ unsigned char: 0, \ signed short: 1, \ unsigned short: 0, \ signed int: 1, \ unsigned int: 0, \ signed long: 1, \ unsigned long: 0, \ signed long long: 1, \ unsigned long long: 0 \ __ckd_generic_int128(1, 0)) #define __ckd_expr(op, res, a, b) \ (_Generic(*res, \ signed char: __ckd_##op##_schar, \ unsigned char: __ckd_##op##_uchar, \ signed short: __ckd_##op##_sshort, \ unsigned short: __ckd_##op##_ushort, \ signed int: __ckd_##op##_sint, \ unsigned int: __ckd_##op##_uint, \ signed long: __ckd_##op##_slong, \ unsigned long: __ckd_##op##_ulong, \ signed long long: __ckd_##op##_slonger, \ unsigned long long: __ckd_##op##_ulonger \ __ckd_generic_int128( \ __ckd_##op##_sint128, \ __ckd_##op##_uint128))( \ res, a, b, \ __ckd_is_signed(a), \ __ckd_is_signed(b))) #define __ckd_declare_add(S, T) \ __ckd_inline char S(void *__res, \ __ckd_uintmax_t __x, \ __ckd_uintmax_t __y, \ char __a_signed, \ char __b_signed) { \ __ckd_uintmax_t __z = __x + __y; \ *(T *)__res = (T)__z; \ char __truncated = 0; \ if (sizeof(T) < sizeof(__ckd_intmax_t)) { \ __truncated = __z != (__ckd_uintmax_t)(T)__z; \ } \ switch (__ckd_is_signed((T)0) << 2 | \ __a_signed << 1 | __b_signed) { \ case 0: /* u = u + u */ \ return __truncated | (__z < __x); \ case 1: /* u = u + s */ \ __y ^= __ckd_sign(__ckd_uintmax_t); \ return __truncated | \ ((__ckd_intmax_t)((__z ^ __x) & \ (__z ^ __y)) < 0); \ case 2: /* u = s + u */ \ __x ^= __ckd_sign(__ckd_uintmax_t); \ return __truncated | \ ((__ckd_intmax_t)((__z ^ __x) & \ (__z ^ __y)) < 0); \ case 3: /* u = s + s */ \ return __truncated | \ ((__ckd_intmax_t)(((__z | __x) & __y) | \ ((__z & __x) & ~__y)) < 0); \ case 4: /* s = u + u */ \ return __truncated | (__z < __x) | ((__ckd_intmax_t)__z < 0); \ case 5: /* s = u + s */ \ __y ^= __ckd_sign(__ckd_uintmax_t); \ return __truncated | (__x + __y < __y); \ case 6: /* s = s + u */ \ __x ^= __ckd_sign(__ckd_uintmax_t); \ return __truncated | (__x + __y < __x); \ case 7: /* s = s + s */ \ return __truncated | \ ((__ckd_intmax_t)((__z ^ __x) & \ (__z ^ __y)) < 0); \ default: \ for (;;) (void)0; \ } \ } __ckd_declare_add(__ckd_add_schar, signed char) __ckd_declare_add(__ckd_add_uchar, unsigned char) __ckd_declare_add(__ckd_add_sshort, signed short) __ckd_declare_add(__ckd_add_ushort, unsigned short) __ckd_declare_add(__ckd_add_sint, signed int) __ckd_declare_add(__ckd_add_uint, unsigned int) __ckd_declare_add(__ckd_add_slong, signed long) __ckd_declare_add(__ckd_add_ulong, unsigned long) __ckd_declare_add(__ckd_add_slonger, signed long long) __ckd_declare_add(__ckd_add_ulonger, unsigned long long) #ifdef __ckd_have_int128 __ckd_declare_add(__ckd_add_sint128, signed __int128) __ckd_declare_add(__ckd_add_uint128, unsigned __int128) #endif #define __ckd_declare_sub(S, T) \ __ckd_inline char S(void *__res, \ __ckd_uintmax_t __x, \ __ckd_uintmax_t __y, \ char __a_signed, \ char __b_signed) { \ __ckd_uintmax_t __z = __x - __y; \ *(T *)__res = (T)__z; \ char __truncated = 0; \ if (sizeof(T) < sizeof(__ckd_intmax_t)) { \ __truncated = __z != (__ckd_uintmax_t)(T)__z; \ } \ switch (__ckd_is_signed((T)0) << 2 | \ __a_signed << 1 | __b_signed) { \ case 0: /* u = u - u */ \ return __truncated | (__x < __y); \ case 1: /* u = u - s */ \ __y ^= __ckd_sign(__ckd_uintmax_t); \ return __truncated | \ ((__ckd_intmax_t)((__x ^ __y) & \ (__z ^ __x)) < 0); \ case 2: /* u = s - u */ \ return __truncated | (__y > __x) | ((__ckd_intmax_t)__x < 0); \ case 3: /* u = s - s */ \ return __truncated | \ ((__ckd_intmax_t)(((__z & __x) & __y) | \ ((__z | __x) & ~__y)) < 0); \ case 4: /* s = u - u */ \ return __truncated | ((__x < __y) ^ ((__ckd_intmax_t)__z < 0)); \ case 5: /* s = u - s */ \ __y ^= __ckd_sign(__ckd_uintmax_t); \ return __truncated | (__x >= __y); \ case 6: /* s = s - u */ \ __x ^= __ckd_sign(__ckd_uintmax_t); \ return __truncated | (__x < __y); \ case 7: /* s = s - s */ \ return __truncated | \ ((__ckd_intmax_t)((__x ^ __y) & \ (__z ^ __x)) < 0); \ default: \ for (;;) (void)0; \ } \ } __ckd_declare_sub(__ckd_sub_schar, signed char) __ckd_declare_sub(__ckd_sub_uchar, unsigned char) __ckd_declare_sub(__ckd_sub_sshort, signed short) __ckd_declare_sub(__ckd_sub_ushort, unsigned short) __ckd_declare_sub(__ckd_sub_sint, signed int) __ckd_declare_sub(__ckd_sub_uint, unsigned int) __ckd_declare_sub(__ckd_sub_slong, signed long) __ckd_declare_sub(__ckd_sub_ulong, unsigned long) __ckd_declare_sub(__ckd_sub_slonger, signed long long) __ckd_declare_sub(__ckd_sub_ulonger, unsigned long long) #ifdef __ckd_have_int128 __ckd_declare_sub(__ckd_sub_sint128, signed __int128) __ckd_declare_sub(__ckd_sub_uint128, unsigned __int128) #endif #define __ckd_declare_mul(S, T) \ __ckd_inline char S(void *__res, \ __ckd_uintmax_t __x, \ __ckd_uintmax_t __y, \ char __a_signed, \ char __b_signed) { \ switch (__ckd_is_signed((T)0) << 2 | \ __a_signed << 1 | __b_signed) { \ case 0: { /* u = u * u */ \ __ckd_uintmax_t __z = __x * __y; \ int __o = __x && __z / __x != __y; \ *(T *)__res = (T)__z; \ return (char) \ (__o | (sizeof(T) < sizeof(__z) && \ __z != (__ckd_uintmax_t)*(T *)__res)); \ } \ case 1: { /* u = u * s */ \ __ckd_uintmax_t __z = __x * __y; \ int __o = __x && __z / __x != __y; \ *(T *)__res = (T)__z; \ return (char) \ (__o | (((__ckd_intmax_t)__y < 0) & !!__x) | \ (sizeof(T) < sizeof(__z) && \ __z != (__ckd_uintmax_t)*(T *)__res)); \ } \ case 2: { /* u = s * u */ \ __ckd_uintmax_t __z = __x * __y; \ int __o = __x && __z / __x != __y; \ *(T *)__res = (T)__z; \ return (char) \ (__o | (((__ckd_intmax_t)__x < 0) & !!__y) | \ (sizeof(T) < sizeof(__z) && \ __z != (__ckd_uintmax_t)*(T *)__res)); \ } \ case 3: { /* u = s * s */ \ int __o = 0; \ if ((__ckd_intmax_t)(__x & __y) < 0) { \ __x = 0 - __x; \ __y = 0 - __y; \ } else if ((__ckd_intmax_t)(__x ^ __y) < 0) { \ __o = __x && __y; \ } \ __ckd_uintmax_t __z = __x * __y; \ __o |= __x && __z / __x != __y; \ *(T *)__res = (T)__z; \ return (char) \ (__o | (sizeof(T) < sizeof(__z) && \ __z != (__ckd_uintmax_t)*(T *)__res)); \ } \ case 4: { /* s = u * u */ \ __ckd_uintmax_t __z = __x * __y; \ int __o = __x && __z / __x != __y; \ *(T *)__res = (T)__z; \ return (char) \ (__o | ((__ckd_intmax_t)(__z) < 0) | \ (sizeof(T) < sizeof(__z) && \ __z != (__ckd_uintmax_t)*(T *)__res)); \ } \ case 5: { /* s = u * s */ \ __ckd_uintmax_t __t = 0 - __y; \ __t = (__ckd_intmax_t)(__t) < 0 ? __y : __t; \ __ckd_uintmax_t __p = __t * __x; \ int __o = __t && __p / __t != __x; \ int __n = (__ckd_intmax_t)__y < 0; \ __ckd_uintmax_t __z = __n ? 0 - __p : __p; \ *(T *)__res = (T)__z; \ __ckd_uintmax_t __m = __ckd_sign(__ckd_uintmax_t) - 1; \ return (char) \ (__o | (__p > __m + __n) | \ (sizeof(T) < sizeof(__z) && \ __z != (__ckd_uintmax_t)*(T *)__res)); \ } \ case 6: { /* s = s * u */ \ __ckd_uintmax_t __t = 0 - __x; \ __t = (__ckd_intmax_t)(__t) < 0 ? __x : __t; \ __ckd_uintmax_t __p = __t * __y; \ int __o = __t && __p / __t != __y; \ int __n = (__ckd_intmax_t)__x < 0; \ __ckd_uintmax_t __z = __n ? 0 - __p : __p; \ *(T *)__res = (T)__z; \ __ckd_uintmax_t __m = __ckd_sign(__ckd_uintmax_t) - 1; \ return (char) \ (__o | (__p > __m + __n) | \ (sizeof(T) < sizeof(__z) && \ __z != (__ckd_uintmax_t)*(T *)__res)); \ } \ case 7: { /* s = s * s */ \ __ckd_uintmax_t __z = __x * __y; \ *(T *)__res = (T)__z; \ return (char) \ (((((__ckd_intmax_t)__y < 0) && \ (__x == __ckd_sign(__ckd_uintmax_t))) || \ (__y && (((__ckd_intmax_t)__z / \ (__ckd_intmax_t)__y) != \ (__ckd_intmax_t)__x))) | \ (sizeof(T) < sizeof(__z) && \ __z != (__ckd_uintmax_t)*(T *)__res)); \ } \ default: \ for (;;) (void)0; \ } \ } __ckd_declare_mul(__ckd_mul_schar, signed char) __ckd_declare_mul(__ckd_mul_uchar, unsigned char) __ckd_declare_mul(__ckd_mul_sshort, signed short) __ckd_declare_mul(__ckd_mul_ushort, unsigned short) __ckd_declare_mul(__ckd_mul_sint, signed int) __ckd_declare_mul(__ckd_mul_uint, unsigned int) __ckd_declare_mul(__ckd_mul_slong, signed long) __ckd_declare_mul(__ckd_mul_ulong, unsigned long) __ckd_declare_mul(__ckd_mul_slonger, signed long long) __ckd_declare_mul(__ckd_mul_ulonger, unsigned long long) #ifdef __ckd_have_int128 __ckd_declare_mul(__ckd_mul_sint128, signed __int128) __ckd_declare_mul(__ckd_mul_uint128, unsigned __int128) #endif #else #ifdef _MSC_VER #pragma warning("checked integer arithmetic unsupported in this environment") #else #pragma GCC warning "checked integer arithmetic unsupported in this environment" #endif #define ckd_add(res, x, y) (*(res) = (x) + (y), 0) #define ckd_sub(res, x, y) (*(res) = (x) - (y), 0) #define ckd_mul(res, x, y) (*(res) = (x) * (y), 0) #endif /* GNU */ #endif /* stdckdint.h */ xkbcommon-libxkbcommon-54ee7ac/src/utils-numbers.h000066400000000000000000000121461510033435100224400ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include #include "utils.h" /* * Define various parsers to avoid the use of strto* -- it’s slower and accepts * a bunch of stuff we don’t want to allow, like signs, spaces, even locale stuff. * * But the real feature is that it does not require a NULL-terminated string, so * it works safely *also* on any buffer, assuming the correct corresponding size * is provided. For NULL-terminated strings, just pass `SIZE_MAX` as the length: * the parsers will *always* stop on a NULL character. */ #define MAKE_PARSE_DEC_TO(type, max) \ static inline int \ parse_dec_to_##type(const char *s, size_t len, type (*out)) \ { \ type result = 0; \ size_t i; \ for (i = 0; \ i < len && (unsigned char)(s[i] - '0') < 10U && \ result <= (max) / 10 && \ result * 10 <= (max) - (unsigned char) (s[i] - '0');\ i++) { \ result = result * 10 + (s[i] - '0'); \ } \ *out = result; \ /* Check if there is more to parse */ \ /* We can safely convert the length to int on success */ \ return (i >= len || (unsigned char)(s[i] - '0') >= 10U) \ ? (int) i \ : -1; \ } /** * Parse a `uint32_t` in decimal format. * * @returns -1 on error (overflow) or the count of characters parsed. */ MAKE_PARSE_DEC_TO(uint32_t, UINT32_MAX) /** * Parse a `uint64_t` in decimal format. * * @returns -1 on error (overflow) or the count of characters parsed. */ MAKE_PARSE_DEC_TO(uint64_t, UINT64_MAX) #undef MAKE_PARSE_DEC_TO static const unsigned char digits__[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; #define MAKE_PARSE_HEX_TO(type, max) \ static inline int \ parse_hex_to_##type(const char *s, size_t len, type (*out)) \ { \ type result = 0; \ size_t i = 0; \ for (; i < len && digits__[(unsigned char) s[i]] < 16u && \ result <= (max) >> 4; \ i++) { \ result = result * 16 + digits__[(unsigned char) s[i]]; \ } \ *out = result; \ /* Check if there is more to parse */ \ /* We can safely convert the length to int on success */ \ return (i >= len || !is_xdigit(s[i])) ? (int) i : -1; \ } /** * Parse a `uint32_t` in hexdecimal format. * * @returns -1 on error (overflow) or the count of characters parsed. */ MAKE_PARSE_HEX_TO(uint32_t, UINT32_MAX) /** * Parse a `uint64_t` in hexdecimal format. * * @returns -1 on error (overflow) or the count of characters parsed. */ MAKE_PARSE_HEX_TO(uint64_t, UINT64_MAX) #undef MAKE_PARSE_HEX_TO xkbcommon-libxkbcommon-54ee7ac/src/utils-paths.c000066400000000000000000000015641510033435100221010ustar00rootroot00000000000000/* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include "utils.h" #include "utils-paths.h" /* Caller must ensure that the input is not NULL or empty */ bool is_absolute_path(const char *path) { #ifdef _WIN32 /* * A file name is relative to the current directory if it does not begin with * one of the following: * - A UNC name of any format, which always start with two backslash characters ("\\"). * - A disk designator with a backslash, for example "C:\" or "d:\". * - A single backslash, for example, "\directory" or "\file.txt". * See: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file */ return is_path_separator(path[0]) || (strlen_safe(path) >= 3 && path[1] == ':' && is_path_separator(path[2])); #else return is_path_separator(path[0]); #endif } xkbcommon-libxkbcommon-54ee7ac/src/utils-paths.h000066400000000000000000000007241510033435100221030ustar00rootroot00000000000000/* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include "utils.h" #ifdef _WIN32 #define PATH_SEPARATOR '\\' #define ALT_PATH_SEPARATOR '/' #define is_path_separator(s) \ ((s) == PATH_SEPARATOR || (s) == ALT_PATH_SEPARATOR) #else #define PATH_SEPARATOR '/' #define is_path_separator(s) ((s) == PATH_SEPARATOR) #endif XKB_EXPORT_PRIVATE bool is_absolute_path(const char *path); xkbcommon-libxkbcommon-54ee7ac/src/utils.c000066400000000000000000000123501510033435100207570ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "utils.h" #ifdef HAVE_MMAP #include #include #include bool map_file(FILE *file, char **string_out, size_t *size_out) { struct stat stat_buf; int fd; char *string; /* Make sure to keep the errno on failure! */ fd = fileno(file); if (fd < 0) return false; if (fstat(fd, &stat_buf) != 0) return false; string = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_SHARED, fd, 0); if (string == MAP_FAILED) return false; *string_out = string; *size_out = stat_buf.st_size; return true; } void unmap_file(char *str, size_t size) { munmap(str, size); } #else bool map_file(FILE *file, char **string_out, size_t *size_out) { long ret; size_t ret_s; char *string; size_t size; /* Make sure to keep the errno on failure! */ ret = fseek(file, 0, SEEK_END); if (ret != 0) return false; ret = ftell(file); if (ret < 0) return false; size = (size_t) ret; ret = fseek(file, 0, SEEK_SET); if (ret < 0) return false; string = malloc(size); if (!string) return false; ret_s = fread(string, 1, size, file); if (ret_s < size) { free(string); return false; } *string_out = string; *size_out = size; return true; } void unmap_file(char *str, size_t size) { free(str); } #endif /* Open a file and ensure it is a regular file. * Returns NULL in case of error. */ FILE* open_file(const char *path) { if (!path) return NULL; int fd = open(path, O_RDONLY); if (fd < 0) return NULL; struct stat stat_buf; int err = fstat(fd, &stat_buf); if (err != 0 || !S_ISREG(stat_buf.st_mode)) { close(fd); return NULL; } /* While unlikely to happen, if `fp` is NULL then we must close the file * descriptor. This is poorly documented and missing from the man page; see instead: * https://www.ibm.com/docs/en/i/7.3?topic=functions-fdopen-associates-stream-file-descriptor) * Confirmed by Peter to be necessary in glibc. */ FILE *fp = fdopen(fd, "rb"); if (fp == NULL) { close(fd); } return fp; } // ASCII lower-case map. static const unsigned char lower_map[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; // ASCII tolower (to avoid locale issues). char to_lower(char c) { return (char) lower_map[(unsigned char) c]; } // ASCII strcasecmp (to avoid locale issues). int istrcmp(const char *a, const char *b) { for (size_t i = 0; ; i++) { if (to_lower(a[i]) != to_lower(b[i])) return (int) to_lower(a[i]) - (int) to_lower(b[i]); if (!a[i]) break; } return 0; } // ASCII strncasecmp (to avoid locale issues). int istrncmp(const char *a, const char *b, size_t n) { for (size_t i = 0; i < n; i++) { if (to_lower(a[i]) != to_lower(b[i])) return (int) to_lower(a[i]) - (int) to_lower(b[i]); if (!a[i]) break; } return 0; } #if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF) int asprintf(char **strp, const char *fmt, ...) { int ret; va_list ap; va_start(ap, fmt); ret = vasprintf(strp, fmt, ap); va_end(ap); return ret; } # if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF) int vasprintf(char **strp, const char *fmt, va_list ap) { int ret; char *buf; va_list ap_copy; /* * The value of the va_list parameter is undefined after the call to * vsnprintf() returns: pass a copy to make sure "ap" remains valid. */ va_copy(ap_copy, ap); ret = vsnprintf(NULL, 0, fmt, ap_copy); va_end(ap_copy); if (ret < 0) return ret; if (!(buf = malloc(ret + 1))) return -1; if ((ret = vsnprintf(buf, ret + 1, fmt, ap)) < 0) { free(buf); return ret; } *strp = buf; return ret; } # endif /* !HAVE_VASPRINTF */ #endif /* !HAVE_ASPRINTF */ xkbcommon-libxkbcommon-54ee7ac/src/utils.h000066400000000000000000000174761510033435100210020ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include #include #include #include #include #if HAVE_UNISTD_H # include #else /* Required on Windows where unistd.h doesn't exist */ # define R_OK 4 /* Test for read permission. */ # define W_OK 2 /* Test for write permission. */ # define X_OK 1 /* Test for execute permission. */ # define F_OK 0 /* Test for existence. */ #endif #ifdef _WIN32 # include # include # include # ifndef S_ISDIR # define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) # endif # ifndef S_ISREG # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) # endif #ifdef _MSC_VER typedef SSIZE_T ssize_t; #endif #endif #include "darray.h" static inline bool is_aligned(const void *restrict pointer, size_t byte_count) { return (uintptr_t) pointer % byte_count == 0; } #define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr)))) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) /* Round up @a so it's divisible by @b. */ #define ROUNDUP(a, b) (((a) + (b) - 1) / (b) * (b)) #define STRINGIFY(x) #x #define STRINGIFY2(x) STRINGIFY(x) #define CONCAT(x,y) x ## y #define CONCAT2(x,y) CONCAT(x,y) /* Check if a Unicode code point is valid in a string literal */ static inline bool is_valid_char(uint32_t cp) { /* Currently we only check for NULL character, but this could be extended * in the future to further ASCII control characters. */ return cp != 0; } /* Check if a Unicode code point is a surrogate. * Those code points are used only in UTF-16 encodings. */ static inline bool is_surrogate(uint32_t cp) { return (cp >= 0xd800 && cp <= 0xdfff); } char to_lower(char c); int istrcmp(const char *a, const char *b); int istrncmp(const char *a, const char *b, size_t n); static inline bool streq(const char *s1, const char *s2) { assert(s1 && s2); return strcmp(s1, s2) == 0; } static inline bool streq_null(const char *s1, const char *s2) { if (s1 == NULL || s2 == NULL) return s1 == s2; return streq(s1, s2); } static inline bool streq_not_null(const char *s1, const char *s2) { if (!s1 || !s2) return false; return streq(s1, s2); } static inline bool istreq(const char *s1, const char *s2) { return istrcmp(s1, s2) == 0; } static inline bool istrneq(const char *s1, const char *s2, size_t len) { return istrncmp(s1, s2, len) == 0; } #define istreq_prefix(s1, s2) istrneq(s1, s2, sizeof(s1) - 1) static inline char * strcpy_safe(char *dest, size_t size, const char *src) { if (!dest || !size || !src) return NULL; const char * const limit = dest + size - 1; while (dest < limit && *src) { *dest++ = *src++; } *dest = '\0'; return *src ? NULL : dest; } static inline char * strdup_safe(const char *s) { return s ? strdup(s) : NULL; } static inline size_t strlen_safe(const char *s) { return s ? strlen(s) : 0; } static inline bool isempty(const char *s) { return s == NULL || s[0] == '\0'; } static inline const char * strnull(const char *s) { return s ? s : "(null)"; } static inline const char * strempty(const char *s) { return s ? s : ""; } static inline void * memdup(const void *mem, size_t nmemb, size_t size) { void *p = calloc(nmemb, size); if (p) memcpy(p, mem, nmemb * size); return p; } #if !(defined(HAVE_STRNDUP) && HAVE_STRNDUP) static inline char * strndup(const char *s, size_t n) { size_t slen = strlen(s); size_t len = MIN(slen, n); char *p = malloc(len + 1); if (!p) return NULL; memcpy(p, s, len); p[len] = '\0'; return p; } #endif /* ctype.h is locale-dependent and has other oddities. */ static inline bool is_ascii(char ch) { return (ch & ~0x7f) == 0; } static inline bool is_space(char ch) { return ch == ' ' || (ch >= '\t' && ch <= '\r'); } static inline bool is_alpha(char ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); } static inline bool is_digit(char ch) { return ch >= '0' && ch <= '9'; } static inline bool is_alnum(char ch) { return is_alpha(ch) || is_digit(ch); } static inline bool is_xdigit(char ch) { return (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'); } static inline bool is_graph(char ch) { /* See table in ascii(7). */ return ch >= '!' && ch <= '~'; } /* * Return the bit position of the most significant bit. * Note: this is 1-based! It's more useful this way, and returns 0 when * mask is all 0s. */ static inline unsigned int msb_pos(uint32_t mask) { unsigned int pos = 0; while (mask) { pos++; mask >>= 1u; } return pos; } static inline int one_bit_set(uint32_t x) { return x && (x & (x - 1)) == 0; } bool map_file(FILE *file, char **string_out, size_t *size_out); void unmap_file(char *string, size_t size); static inline bool check_eaccess(const char *path, int mode) { #if defined(HAVE_EACCESS) if (eaccess(path, mode) != 0) return false; #elif defined(HAVE_EUIDACCESS) if (euidaccess(path, mode) != 0) return false; #endif return true; } FILE* open_file(const char *path); #if defined(HAVE_SECURE_GETENV) # define secure_getenv secure_getenv #elif defined(HAVE___SECURE_GETENV) # define secure_getenv __secure_getenv #else # define secure_getenv getenv #endif #if defined(HAVE___BUILTIN_EXPECT) # define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __builtin_expect(!!(x), 0) #else # define likely(x) (x) # define unlikely(x) (x) #endif /* Compiler Attributes */ /* Private functions only exposed in tests. */ #ifdef ENABLE_PRIVATE_APIS # if defined(__GNUC__) && !defined(__CYGWIN__) # define XKB_EXPORT_PRIVATE __attribute__((visibility("default"))) # elif defined(_WIN32) # define XKB_EXPORT_PRIVATE __declspec(dllexport) # else # define XKB_EXPORT_PRIVATE # endif #else # define XKB_EXPORT_PRIVATE #endif #if defined(__MINGW32__) # define ATTR_PRINTF(x,y) __attribute__((__format__(__MINGW_PRINTF_FORMAT, x, y))) #elif defined(__GNUC__) # define ATTR_PRINTF(x,y) __attribute__((__format__(__printf__, x, y))) #else # define ATTR_PRINTF(x,y) #endif #if defined(__GNUC__) # define ATTR_NORETURN __attribute__((__noreturn__)) #else # define ATTR_NORETURN #endif /* GNUC */ #if defined(__GNUC__) #define ATTR_MALLOC __attribute__((__malloc__)) #else #define ATTR_MALLOC #endif #if defined(__GNUC__) # define ATTR_NULL_SENTINEL __attribute__((__sentinel__)) #else # define ATTR_NULL_SENTINEL #endif #if defined(__GNUC__) #define ATTR_PACKED __attribute__((__packed__)) #else #define ATTR_PACKED #endif #if !(defined(HAVE_ASPRINTF) && HAVE_ASPRINTF) XKB_EXPORT_PRIVATE int asprintf(char **strp, const char *fmt, ...) ATTR_PRINTF(2, 3); # if !(defined(HAVE_VASPRINTF) && HAVE_VASPRINTF) # include XKB_EXPORT_PRIVATE int vasprintf(char **strp, const char *fmt, va_list ap); # endif /* !HAVE_VASPRINTF */ #endif /* !HAVE_ASPRINTF */ static inline bool ATTR_PRINTF(3, 4) snprintf_safe(char *buf, size_t sz, const char *format, ...) { va_list ap; int rc; va_start(ap, format); rc = vsnprintf(buf, sz, format, ap); va_end(ap); return rc >= 0 && (size_t)rc < sz; } static inline char * ATTR_PRINTF(1, 0) vasprintf_safe(const char *fmt, va_list args) { char *str; int len; len = vasprintf(&str, fmt, args); if (len == -1) return NULL; return str; } /** * A version of asprintf that returns the allocated string or NULL on error. */ static inline char * ATTR_PRINTF(1, 2) asprintf_safe(const char *fmt, ...) { va_list args; char *str; va_start(args, fmt); str = vasprintf_safe(fmt, args); va_end(args); return str; } xkbcommon-libxkbcommon-54ee7ac/src/x11/000077500000000000000000000000001510033435100200635ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/src/x11/keymap.c000066400000000000000000001301551510033435100215220ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "atom.h" #include "keymap.h" #include "x11-priv.h" /* * References for the lonesome traveler: * Xkb protocol specification: * https://www.x.org/releases/current/doc/kbproto/xkbproto.html * The XCB xkb XML protocol file: * /user/share/xcb/xkb.xml * The XCB xkb header file: * /usr/include/xcb/xkb.h * The old kbproto header files: * /usr/include/X11/extensions/XKB{,proto,str}.h * Xlib XKB source code: * /src/xkb/XKBGetMap.c (and friends) * X server XKB protocol handling: * /xkb/xkb.c * Man pages: * XkbGetMap(3), XkbGetCompatMap(3), etc. */ /* Constants from /usr/include/X11/extensions/XKB.h */ /* XkbNumModifiers. */ #define NUM_REAL_MODS 8u /* XkbNumVirtualMods. */ #define NUM_VMODS 16u /* XkbNoModifier. */ #define NO_MODIFIER 0xff /* XkbNumIndicators. */ #define NUM_INDICATORS 32u /* XkbAllIndicatorsMask. */ #define ALL_INDICATORS_MASK 0xffffffff /* Some macros. Not very nice but it'd be worse without them. */ /* * We try not to trust the server too much and be paranoid. If we get * something which we definitely shouldn't, we fail. */ #define FAIL_UNLESS(expr) do { \ if (!(expr)) { \ log_err(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, \ "x11: failed to get keymap from X server: " \ "unmet condition in %s(): %s\n", \ __func__, STRINGIFY(expr)); \ goto fail; \ } \ } while (0) #define FAIL_IF_BAD_REPLY(reply, request_name) do { \ if (!(reply)) { \ log_err(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, \ "x11: failed to get keymap from X server: " \ "%s request failed\n", \ (request_name)); \ goto fail; \ } \ } while (0) #define ALLOC_OR_FAIL(arr, nmemb) do { \ if ((nmemb) > 0) { \ (arr) = calloc((nmemb), sizeof(*(arr))); \ if (!(arr)) \ goto fail; \ } \ } while (0) static const xcb_xkb_map_part_t get_map_required_components = (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP); static const xcb_xkb_name_detail_t get_names_wanted = (XCB_XKB_NAME_DETAIL_KEYCODES | XCB_XKB_NAME_DETAIL_SYMBOLS | XCB_XKB_NAME_DETAIL_TYPES | XCB_XKB_NAME_DETAIL_COMPAT | XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES | XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES | XCB_XKB_NAME_DETAIL_INDICATOR_NAMES | XCB_XKB_NAME_DETAIL_KEY_NAMES | XCB_XKB_NAME_DETAIL_KEY_ALIASES | XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES | XCB_XKB_NAME_DETAIL_GROUP_NAMES); static const xcb_xkb_name_detail_t get_names_required = (XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES | XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES | XCB_XKB_NAME_DETAIL_KEY_NAMES | XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES); static xkb_mod_mask_t translate_mods(uint8_t rmods, uint16_t vmods_low, uint16_t vmods_high) { /* We represent mod masks in a single uint32_t value, with real mods * first and vmods after (though we don't make these distinctions). */ return ((xkb_mod_mask_t) rmods) | ((xkb_mod_mask_t) vmods_low << 8) | ((xkb_mod_mask_t) vmods_high << 16); } static enum xkb_action_controls translate_controls_mask(uint32_t wire) { enum xkb_action_controls ret = 0; if (wire & XCB_XKB_BOOL_CTRL_REPEAT_KEYS) ret |= CONTROL_REPEAT; if (wire & XCB_XKB_BOOL_CTRL_SLOW_KEYS) ret |= CONTROL_SLOW; if (wire & XCB_XKB_BOOL_CTRL_BOUNCE_KEYS) ret |= CONTROL_DEBOUNCE; if (wire & XCB_XKB_BOOL_CTRL_STICKY_KEYS) ret |= CONTROL_STICKY; if (wire & XCB_XKB_BOOL_CTRL_MOUSE_KEYS) ret |= CONTROL_MOUSEKEYS; if (wire & XCB_XKB_BOOL_CTRL_MOUSE_KEYS_ACCEL) ret |= CONTROL_MOUSEKEYS_ACCEL; if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_KEYS) ret |= CONTROL_AX; if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_TIMEOUT_MASK) ret |= CONTROL_AX_TIMEOUT; if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_FEEDBACK_MASK) ret |= CONTROL_AX_FEEDBACK; if (wire & XCB_XKB_BOOL_CTRL_AUDIBLE_BELL_MASK) ret |= CONTROL_BELL; if (wire & XCB_XKB_BOOL_CTRL_IGNORE_GROUP_LOCK_MASK) ret |= CONTROL_IGNORE_GROUP_LOCK; /* Some controls are not supported and don't appear here. */ return ret; } static void translate_action(union xkb_action *action, const xcb_xkb_action_t *wire) { switch (wire->type) { case XCB_XKB_SA_TYPE_SET_MODS: action->type = ACTION_TYPE_MOD_SET; action->mods.mods.mods = translate_mods(wire->setmods.realMods, wire->setmods.vmodsLow, wire->setmods.vmodsHigh); action->mods.mods.mask = translate_mods(wire->setmods.mask, 0, 0); if (wire->setmods.flags & XCB_XKB_SA_CLEAR_LOCKS) action->mods.flags |= ACTION_LOCK_CLEAR; if (wire->setmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) action->mods.flags |= ACTION_LATCH_TO_LOCK; if (wire->setmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; break; case XCB_XKB_SA_TYPE_LATCH_MODS: action->type = ACTION_TYPE_MOD_LATCH; action->mods.mods.mods = translate_mods(wire->latchmods.realMods, wire->latchmods.vmodsLow, wire->latchmods.vmodsHigh); action->mods.mods.mask = translate_mods(wire->latchmods.mask, 0, 0); if (wire->latchmods.flags & XCB_XKB_SA_CLEAR_LOCKS) action->mods.flags |= ACTION_LOCK_CLEAR; if (wire->latchmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) action->mods.flags |= ACTION_LATCH_TO_LOCK; if (wire->latchmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; break; case XCB_XKB_SA_TYPE_LOCK_MODS: action->type = ACTION_TYPE_MOD_LOCK; action->mods.mods.mods = translate_mods(wire->lockmods.realMods, wire->lockmods.vmodsLow, wire->lockmods.vmodsHigh); action->mods.mods.mask = translate_mods(wire->lockmods.mask, 0, 0); if (wire->lockmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_LOCK) action->mods.flags |= ACTION_LOCK_NO_LOCK; if (wire->lockmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_UNLOCK) action->mods.flags |= ACTION_LOCK_NO_UNLOCK; if (wire->lockmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; break; case XCB_XKB_SA_TYPE_SET_GROUP: action->type = ACTION_TYPE_GROUP_SET; action->group.group = wire->setgroup.group; if (wire->setmods.flags & XCB_XKB_SA_CLEAR_LOCKS) action->group.flags |= ACTION_LOCK_CLEAR; if (wire->setmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) action->group.flags |= ACTION_LATCH_TO_LOCK; if (wire->setmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) action->group.flags |= ACTION_ABSOLUTE_SWITCH; break; case XCB_XKB_SA_TYPE_LATCH_GROUP: action->type = ACTION_TYPE_GROUP_LATCH; action->group.group = wire->latchgroup.group; if (wire->latchmods.flags & XCB_XKB_SA_CLEAR_LOCKS) action->group.flags |= ACTION_LOCK_CLEAR; if (wire->latchmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) action->group.flags |= ACTION_LATCH_TO_LOCK; if (wire->latchmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) action->group.flags |= ACTION_ABSOLUTE_SWITCH; break; case XCB_XKB_SA_TYPE_LOCK_GROUP: action->type = ACTION_TYPE_GROUP_LOCK; action->group.group = wire->lockgroup.group; if (wire->lockgroup.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) action->group.flags |= ACTION_ABSOLUTE_SWITCH; break; case XCB_XKB_SA_TYPE_MOVE_PTR: action->type = ACTION_TYPE_PTR_MOVE; action->ptr.x = (int16_t) (wire->moveptr.xLow | ((uint16_t) wire->moveptr.xHigh << 8)); action->ptr.y = (int16_t) (wire->moveptr.yLow | ((uint16_t) wire->moveptr.yHigh << 8)); if (!(wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_NO_ACCELERATION)) action->ptr.flags |= ACTION_ACCEL; if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_X) action->ptr.flags |= ACTION_ABSOLUTE_X; if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_Y) action->ptr.flags |= ACTION_ABSOLUTE_Y; break; case XCB_XKB_SA_TYPE_PTR_BTN: action->type = ACTION_TYPE_PTR_BUTTON; action->btn.count = wire->ptrbtn.count; action->btn.button = wire->ptrbtn.button; action->btn.flags = 0; break; case XCB_XKB_SA_TYPE_LOCK_PTR_BTN: action->type = ACTION_TYPE_PTR_LOCK; action->btn.button = wire->lockptrbtn.button; if (wire->lockptrbtn.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_LOCK) action->btn.flags |= ACTION_LOCK_NO_LOCK; if (wire->lockptrbtn.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_UNLOCK) action->btn.flags |= ACTION_LOCK_NO_UNLOCK; break; case XCB_XKB_SA_TYPE_SET_PTR_DFLT: action->type = ACTION_TYPE_PTR_DEFAULT; action->dflt.value = wire->setptrdflt.value; if (wire->setptrdflt.flags & XCB_XKB_SA_SET_PTR_DFLT_FLAG_DFLT_BTN_ABSOLUTE) action->dflt.flags |= ACTION_ABSOLUTE_SWITCH; break; case XCB_XKB_SA_TYPE_TERMINATE: action->type = ACTION_TYPE_TERMINATE; break; case XCB_XKB_SA_TYPE_SWITCH_SCREEN: action->type = ACTION_TYPE_SWITCH_VT; action->screen.screen = wire->switchscreen.newScreen; if (!(wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_APPLICATION)) action->screen.flags |= ACTION_SAME_SCREEN; if (wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_ABSOLUTE) action->screen.flags |= ACTION_ABSOLUTE_SWITCH; break; case XCB_XKB_SA_TYPE_SET_CONTROLS: action->type = ACTION_TYPE_CTRL_SET; { const uint16_t mask = (wire->setcontrols.boolCtrlsLow | (wire->setcontrols.boolCtrlsHigh << 8)); action->ctrls.ctrls = translate_controls_mask(mask); } break; case XCB_XKB_SA_TYPE_LOCK_CONTROLS: action->type = ACTION_TYPE_CTRL_LOCK; { const uint16_t mask = (wire->lockcontrols.boolCtrlsLow | (wire->lockcontrols.boolCtrlsHigh << 8)); action->ctrls.ctrls = translate_controls_mask(mask); } break; case XCB_XKB_SA_TYPE_NO_ACTION: /* We don't support these. */ case XCB_XKB_SA_TYPE_ISO_LOCK: case XCB_XKB_SA_TYPE_REDIRECT_KEY: case XCB_XKB_SA_TYPE_ACTION_MESSAGE: case XCB_XKB_SA_TYPE_DEVICE_BTN: case XCB_XKB_SA_TYPE_LOCK_DEVICE_BTN: case XCB_XKB_SA_TYPE_DEVICE_VALUATOR: action->type = ACTION_TYPE_NONE; break; default: if (wire->type < ACTION_TYPE_PRIVATE) { action->type = ACTION_TYPE_NONE; break; } /* Treat high unknown actions as Private actions. */ action->priv.type = wire->noaction.type; static_assert(sizeof(action->priv.data) == 7 && sizeof(wire->noaction.pad0) == 7, "The private action data must be 7 bytes long!"); memcpy(action->priv.data, wire->noaction.pad0, 7); break; } } static bool get_types(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) { int types_length = xcb_xkb_get_map_map_types_rtrn_length(reply, map); xcb_xkb_key_type_iterator_t types_iter = xcb_xkb_get_map_map_types_rtrn_iterator(reply, map); FAIL_UNLESS(reply->firstType == 0); keymap->num_types = reply->nTypes; ALLOC_OR_FAIL(keymap->types, keymap->num_types); assert(types_length == (int) keymap->num_types); for (int i = 0; i < types_length; i++) { xcb_xkb_key_type_t *wire_type = types_iter.data; struct xkb_key_type *type = &keymap->types[i]; FAIL_UNLESS(wire_type->numLevels > 0); type->mods.mods = translate_mods(wire_type->mods_mods, wire_type->mods_vmods, 0); type->mods.mask = translate_mods(wire_type->mods_mask, 0, 0); type->num_levels = wire_type->numLevels; { int entries_length = xcb_xkb_key_type_map_length(wire_type); xcb_xkb_kt_map_entry_iterator_t entries_iter = xcb_xkb_key_type_map_iterator(wire_type); type->num_entries = wire_type->nMapEntries; ALLOC_OR_FAIL(type->entries, type->num_entries); assert(entries_length == (int) type->num_entries); for (int j = 0; j < entries_length; j++) { xcb_xkb_kt_map_entry_t *wire_entry = entries_iter.data; struct xkb_key_type_entry *entry = &type->entries[j]; FAIL_UNLESS(wire_entry->level < type->num_levels); entry->level = wire_entry->level; entry->mods.mods = translate_mods(wire_entry->mods_mods, wire_entry->mods_vmods, 0); entry->mods.mask = translate_mods(wire_entry->mods_mask, 0, 0); xcb_xkb_kt_map_entry_next(&entries_iter); } } { int preserves_length = xcb_xkb_key_type_preserve_length(wire_type); xcb_xkb_mod_def_iterator_t preserves_iter = xcb_xkb_key_type_preserve_iterator(wire_type); FAIL_UNLESS((unsigned) preserves_length <= type->num_entries); for (int j = 0; j < preserves_length; j++) { xcb_xkb_mod_def_t *wire_preserve = preserves_iter.data; struct xkb_key_type_entry *entry = &type->entries[j]; entry->preserve.mods = translate_mods(wire_preserve->realMods, wire_preserve->vmods, 0); entry->preserve.mask = translate_mods(wire_preserve->mask, 0, 0); xcb_xkb_mod_def_next(&preserves_iter); } } /* Checked only when compiling a keymap from text */ type->required = true; xcb_xkb_key_type_next(&types_iter); } return true; fail: return false; } static bool get_sym_maps(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) { int sym_maps_length = xcb_xkb_get_map_map_syms_rtrn_length(reply, map); xcb_xkb_key_sym_map_iterator_t sym_maps_iter = xcb_xkb_get_map_map_syms_rtrn_iterator(reply, map); FAIL_UNLESS(reply->minKeyCode <= reply->maxKeyCode); FAIL_UNLESS(reply->firstKeySym >= reply->minKeyCode); FAIL_UNLESS(reply->firstKeySym + reply->nKeySyms <= reply->maxKeyCode + 1); keymap->min_key_code = reply->minKeyCode; keymap->max_key_code = reply->maxKeyCode; keymap->num_keys = keymap->num_keys_low = reply->maxKeyCode + 1; ALLOC_OR_FAIL(keymap->keys, keymap->max_key_code + 1); for (xkb_keycode_t kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++) keymap->keys[kc].keycode = kc; for (int i = 0; i < sym_maps_length; i++) { xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data; struct xkb_key *key = &keymap->keys[reply->firstKeySym + i]; key->num_groups = wire_sym_map->groupInfo & 0x0f; FAIL_UNLESS(key->num_groups <= ARRAY_SIZE(wire_sym_map->kt_index)); ALLOC_OR_FAIL(key->groups, key->num_groups); for (xkb_layout_index_t j = 0; j < key->num_groups; j++) { FAIL_UNLESS(wire_sym_map->kt_index[j] < keymap->num_types); key->groups[j].type = &keymap->types[wire_sym_map->kt_index[j]]; ALLOC_OR_FAIL(key->groups[j].levels, key->groups[j].type->num_levels); } key->out_of_range_group_number = (wire_sym_map->groupInfo & 0x30) >> 4; FAIL_UNLESS(key->out_of_range_group_number <= key->num_groups); if (wire_sym_map->groupInfo & XCB_XKB_GROUPS_WRAP_CLAMP_INTO_RANGE) key->out_of_range_group_action = RANGE_SATURATE; else if (wire_sym_map->groupInfo & XCB_XKB_GROUPS_WRAP_REDIRECT_INTO_RANGE) key->out_of_range_group_action = RANGE_REDIRECT; else key->out_of_range_group_action = RANGE_WRAP; { int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map); xcb_keysym_t *syms_iter = xcb_xkb_key_sym_map_syms(wire_sym_map); FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups); if (syms_length > 0) key->explicit |= EXPLICIT_SYMBOLS; for (xkb_layout_index_t group = 0; group < key->num_groups; group++) { for (xkb_level_index_t level = 0; level < wire_sym_map->width; level++) { xcb_keysym_t wire_keysym = *syms_iter; assert(key->groups[group].type != NULL); if (level < key->groups[group].type->num_levels) { /* Do not discard the keysym yet if it is NoSymbol, because * there may be an action set */ key->groups[group].levels[level].num_syms = 1; key->groups[group].levels[level].s.sym = wire_keysym; /* Set capitalization transformation */ key->groups[group].levels[level].upper = xkb_keysym_to_upper(wire_keysym); } syms_iter++; } } } xcb_xkb_key_sym_map_next(&sym_maps_iter); } return true; fail: return false; } static bool get_actions(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) { int acts_count_length = xcb_xkb_get_map_map_acts_rtrn_count_length(reply, map); uint8_t *acts_count_iter = xcb_xkb_get_map_map_acts_rtrn_count(map); xcb_xkb_action_iterator_t acts_iter = xcb_xkb_get_map_map_acts_rtrn_acts_iterator(reply, map); xcb_xkb_key_sym_map_iterator_t sym_maps_iter = xcb_xkb_get_map_map_syms_rtrn_iterator(reply, map); FAIL_UNLESS(reply->firstKeyAction == keymap->min_key_code); FAIL_UNLESS(reply->firstKeyAction + reply->nKeyActions == keymap->max_key_code + 1); for (int i = 0; i < acts_count_length; i++) { xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data; int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map); uint8_t wire_count = *acts_count_iter; struct xkb_key *key = &keymap->keys[reply->firstKeyAction + i]; FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups); FAIL_UNLESS(wire_count == 0 || wire_count == syms_length); if (wire_count != 0) { for (xkb_layout_index_t group = 0; group < key->num_groups; group++) { for (xkb_level_index_t level = 0; level < wire_sym_map->width; level++) { xcb_xkb_action_t *wire_action = acts_iter.data; if (level < key->groups[group].type->num_levels) { key->groups[group].levels[level].num_actions = 1; union xkb_action *action = &key->groups[group].levels[level].a.action; translate_action(action, wire_action); /* If the action and the keysym are both undefined, * discard them */ if (action->type == ACTION_TYPE_NONE && key->groups[group].levels[level].s.sym == XKB_KEY_NoSymbol) { key->groups[group].levels[level].num_syms = 0; key->groups[group].levels[level].num_actions = 0; } } xcb_xkb_action_next(&acts_iter); } } } acts_count_iter++; xcb_xkb_key_sym_map_next(&sym_maps_iter); } return true; fail: return false; } static bool get_vmods(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) { uint8_t *iter = xcb_xkb_get_map_map_vmods_rtrn(map); keymap->mods.num_mods = NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS); FAIL_UNLESS(keymap->mods.num_mods <= XKB_MAX_MODS); static_assert(NUM_REAL_MODS + NUM_VMODS <= XKB_MAX_MODS, ""); for (unsigned i = 0; i < NUM_VMODS; i++) { if (reply->virtualMods & (1u << i)) { uint8_t wire = *iter; struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i]; mod->type = MOD_VIRT; mod->mapping = translate_mods(wire, 0, 0); iter++; } } return true; fail: return false; } static bool get_explicits(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) { int length = xcb_xkb_get_map_map_explicit_rtrn_length(reply, map); xcb_xkb_set_explicit_iterator_t iter = xcb_xkb_get_map_map_explicit_rtrn_iterator(reply, map); for (int i = 0; i < length; i++) { xcb_xkb_set_explicit_t *wire = iter.data; struct xkb_key *key; FAIL_UNLESS(wire->keycode >= keymap->min_key_code && wire->keycode <= keymap->max_key_code); key = &keymap->keys[wire->keycode]; if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_1) && key->num_groups > 0) { key->groups[0].explicit_type = true; key->explicit |= EXPLICIT_TYPES; } if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_2) && key->num_groups > 1) { key->groups[1].explicit_type = true; key->explicit |= EXPLICIT_TYPES; } if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_3) && key->num_groups > 2) { key->groups[2].explicit_type = true; key->explicit |= EXPLICIT_TYPES; } if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_4) && key->num_groups > 3) { key->groups[3].explicit_type = true; key->explicit |= EXPLICIT_TYPES; } if (wire->explicit & XCB_XKB_EXPLICIT_INTERPRET) { key->explicit |= EXPLICIT_INTERP; /* Make all key groups have explicit actions too */ for (xkb_layout_index_t l = 0; l < key->num_groups; l++) { key->groups[l].explicit_actions = true; } } if (wire->explicit & XCB_XKB_EXPLICIT_AUTO_REPEAT) key->explicit |= EXPLICIT_REPEAT; if (wire->explicit & XCB_XKB_EXPLICIT_V_MOD_MAP) key->explicit |= EXPLICIT_VMODMAP; xcb_xkb_set_explicit_next(&iter); } return true; fail: return false; } static bool get_modmaps(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) { int length = xcb_xkb_get_map_map_modmap_rtrn_length(reply, map); xcb_xkb_key_mod_map_iterator_t iter = xcb_xkb_get_map_map_modmap_rtrn_iterator(reply, map); for (int i = 0; i < length; i++) { xcb_xkb_key_mod_map_t *wire = iter.data; struct xkb_key *key; FAIL_UNLESS(wire->keycode >= keymap->min_key_code && wire->keycode <= keymap->max_key_code); key = &keymap->keys[wire->keycode]; key->modmap = wire->mods; xcb_xkb_key_mod_map_next(&iter); } return true; fail: return false; } static bool get_vmodmaps(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map) { int length = xcb_xkb_get_map_map_vmodmap_rtrn_length(reply, map); xcb_xkb_key_v_mod_map_iterator_t iter = xcb_xkb_get_map_map_vmodmap_rtrn_iterator(reply, map); for (int i = 0; i < length; i++) { xcb_xkb_key_v_mod_map_t *wire = iter.data; struct xkb_key *key; FAIL_UNLESS(wire->keycode >= keymap->min_key_code && wire->keycode <= keymap->max_key_code); key = &keymap->keys[wire->keycode]; key->vmodmap = translate_mods(0, wire->vmods, 0); xcb_xkb_key_v_mod_map_next(&iter); } return true; fail: return false; } static bool get_map(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_map_cookie_t cookie) { xcb_xkb_get_map_reply_t *reply = xcb_xkb_get_map_reply(conn, cookie, NULL); xcb_xkb_get_map_map_t map; FAIL_IF_BAD_REPLY(reply, "XkbGetMap"); if ((reply->present & get_map_required_components) != get_map_required_components) goto fail; xcb_xkb_get_map_map_unpack(xcb_xkb_get_map_map(reply), reply->nTypes, reply->nKeySyms, reply->nKeyActions, reply->totalActions, reply->totalKeyBehaviors, reply->virtualMods, reply->totalKeyExplicit, reply->totalModMapKeys, reply->totalVModMapKeys, reply->present, &map); if (!get_types(keymap, conn, reply, &map) || !get_sym_maps(keymap, conn, reply, &map) || !get_actions(keymap, conn, reply, &map) || !get_vmods(keymap, conn, reply, &map) || !get_explicits(keymap, conn, reply, &map) || !get_modmaps(keymap, conn, reply, &map) || !get_vmodmaps(keymap, conn, reply, &map)) goto fail; free(reply); return true; fail: free(reply); return false; } static bool get_indicators(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_indicator_map_reply_t *reply) { xcb_xkb_indicator_map_iterator_t iter = xcb_xkb_get_indicator_map_maps_iterator(reply); keymap->num_leds = msb_pos(reply->which); FAIL_UNLESS(keymap->num_leds <= XKB_MAX_LEDS); static_assert(XKB_MAX_LEDS == NUM_INDICATORS, ""); for (unsigned i = 0; i < NUM_INDICATORS; i++) { if (reply->which & (UINT32_C(1) << i)) { xcb_xkb_indicator_map_t *wire = iter.data; struct xkb_led *led = &keymap->leds[i]; if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_BASE) led->which_groups |= XKB_STATE_LAYOUT_DEPRESSED; if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_LATCHED) led->which_groups |= XKB_STATE_LAYOUT_LATCHED; if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_LOCKED) led->which_groups |= XKB_STATE_LAYOUT_LOCKED; if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_EFFECTIVE) led->which_groups |= XKB_STATE_LAYOUT_EFFECTIVE; if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_COMPAT) led->which_groups |= XKB_STATE_LAYOUT_EFFECTIVE; led->groups = wire->groups; if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_BASE) led->which_mods |= XKB_STATE_MODS_DEPRESSED; if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_LATCHED) led->which_mods |= XKB_STATE_MODS_LATCHED; if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_LOCKED) led->which_mods |= XKB_STATE_MODS_LOCKED; if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_EFFECTIVE) led->which_mods |= XKB_STATE_MODS_EFFECTIVE; if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_COMPAT) led->which_mods |= XKB_STATE_MODS_EFFECTIVE; led->mods.mods = translate_mods(wire->realMods, wire->vmods, 0); led->mods.mask = translate_mods(wire->mods, 0, 0); led->ctrls = translate_controls_mask(wire->ctrls); xcb_xkb_indicator_map_next(&iter); } } return true; fail: return false; } static bool get_indicator_map(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_indicator_map_cookie_t cookie) { xcb_xkb_get_indicator_map_reply_t *reply = xcb_xkb_get_indicator_map_reply(conn, cookie, NULL); FAIL_IF_BAD_REPLY(reply, "XkbGetIndicatorMap"); if (!get_indicators(keymap, conn, reply)) goto fail; free(reply); return true; fail: free(reply); return false; } static bool get_sym_interprets(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_compat_map_reply_t *reply) { int length = xcb_xkb_get_compat_map_si_rtrn_length(reply); xcb_xkb_sym_interpret_iterator_t iter = xcb_xkb_get_compat_map_si_rtrn_iterator(reply); FAIL_UNLESS(reply->firstSIRtrn == 0); FAIL_UNLESS(reply->nSIRtrn == reply->nTotalSI); keymap->num_sym_interprets = reply->nSIRtrn; ALLOC_OR_FAIL(keymap->sym_interprets, keymap->num_sym_interprets); for (int i = 0; i < length; i++) { xcb_xkb_sym_interpret_t *wire = iter.data; struct xkb_sym_interpret *sym_interpret = &keymap->sym_interprets[i]; sym_interpret->sym = wire->sym; switch (wire->match & XCB_XKB_SYM_INTERP_MATCH_OP_MASK) { case XCB_XKB_SYM_INTERPRET_MATCH_NONE_OF: sym_interpret->match = MATCH_NONE; break; case XCB_XKB_SYM_INTERPRET_MATCH_ANY_OF_OR_NONE: sym_interpret->match = MATCH_ANY_OR_NONE; break; case XCB_XKB_SYM_INTERPRET_MATCH_ANY_OF: sym_interpret->match = MATCH_ANY; break; case XCB_XKB_SYM_INTERPRET_MATCH_ALL_OF: sym_interpret->match = MATCH_ALL; break; case XCB_XKB_SYM_INTERPRET_MATCH_EXACTLY: sym_interpret->match = MATCH_EXACTLY; break; default: log_err_func(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized interpret match value: %#x\n", wire->match & XCB_XKB_SYM_INTERP_MATCH_OP_MASK); goto fail; } sym_interpret->level_one_only = (wire->match & XCB_XKB_SYM_INTERP_MATCH_LEVEL_ONE_ONLY); sym_interpret->mods = wire->mods; if (wire->virtualMod == NO_MODIFIER) sym_interpret->virtual_mod = XKB_MOD_INVALID; else sym_interpret->virtual_mod = NUM_REAL_MODS + wire->virtualMod; sym_interpret->repeat = (wire->flags & 0x01); translate_action(&sym_interpret->a.action, (xcb_xkb_action_t *) &wire->action); sym_interpret->num_actions = (sym_interpret->a.action.type != ACTION_TYPE_NONE); /* Checked only when compiling a keymap from text */ sym_interpret->required = true; xcb_xkb_sym_interpret_next(&iter); } return true; fail: return false; } static bool get_compat_map(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_compat_map_cookie_t cookie) { xcb_xkb_get_compat_map_reply_t *reply = xcb_xkb_get_compat_map_reply(conn, cookie, NULL); FAIL_IF_BAD_REPLY(reply, "XkbGetCompatMap"); if (!get_sym_interprets(keymap, conn, reply)) goto fail; free(reply); return true; fail: free(reply); return false; } static bool get_type_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { int key_type_names_length = xcb_xkb_get_names_value_list_type_names_length(reply, list); xcb_atom_t *key_type_names_iter = xcb_xkb_get_names_value_list_type_names(list); int n_levels_per_type_length = xcb_xkb_get_names_value_list_n_levels_per_type_length(reply, list); uint8_t *n_levels_per_type_iter = xcb_xkb_get_names_value_list_n_levels_per_type(list); xcb_atom_t *kt_level_names_iter = xcb_xkb_get_names_value_list_kt_level_names(list); FAIL_UNLESS(reply->nTypes == keymap->num_types); FAIL_UNLESS(key_type_names_length == n_levels_per_type_length); for (int i = 0; i < key_type_names_length; i++) { xcb_atom_t wire_type_name = *key_type_names_iter; uint8_t wire_num_levels = *n_levels_per_type_iter; struct xkb_key_type *type = &keymap->types[i]; /* Levels names are optional, but the maximum is the level count */ FAIL_UNLESS(type->num_levels >= wire_num_levels); /* Allocate names for all levels, even if some names are missing */ ALLOC_OR_FAIL(type->level_names, type->num_levels); x11_atom_interner_adopt_atom(interner, wire_type_name, &type->name); for (size_t j = 0; j < wire_num_levels; j++) { x11_atom_interner_adopt_atom(interner, kt_level_names_iter[j], &type->level_names[j]); } /* We may have received less names than there are levels: ensure * missing names have a fallback. */ for (size_t j = wire_num_levels; j < type->num_levels; j++) type->level_names[j] = XKB_ATOM_NONE; type->num_level_names = type->num_levels; kt_level_names_iter += wire_num_levels; key_type_names_iter++; n_levels_per_type_iter++; } return true; fail: return false; } static bool get_indicator_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { xcb_atom_t *iter = xcb_xkb_get_names_value_list_indicator_names(list); FAIL_UNLESS(msb_pos(reply->indicators) <= keymap->num_leds); for (unsigned i = 0; i < NUM_INDICATORS; i++) { if (reply->indicators & (UINT32_C(1) << i)) { xcb_atom_t wire = *iter; struct xkb_led *led = &keymap->leds[i]; x11_atom_interner_adopt_atom(interner, wire, &led->name); iter++; } } return true; fail: return false; } static bool get_vmod_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { xcb_atom_t *iter = xcb_xkb_get_names_value_list_virtual_mod_names(list); /* * GetMap's reply->virtualMods is always 0xffff. This one really * tells us which vmods exist (a vmod must have a name), so we fix * up the size here. */ keymap->mods.num_mods = NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS); FAIL_UNLESS(keymap->mods.num_mods <= XKB_MAX_MODS); static_assert(NUM_REAL_MODS + NUM_VMODS <= XKB_MAX_MODS, ""); for (unsigned i = 0; i < NUM_VMODS; i++) { if (reply->virtualMods & (1u << i)) { xcb_atom_t wire = *iter; struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i]; x11_atom_interner_adopt_atom(interner, wire, &mod->name); iter++; } } return true; fail: return false; } static bool get_group_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { int length = xcb_xkb_get_names_value_list_groups_length(reply, list); xcb_atom_t *iter = xcb_xkb_get_names_value_list_groups(list); keymap->num_group_names = msb_pos(reply->groupNames); ALLOC_OR_FAIL(keymap->group_names, keymap->num_group_names); for (int i = 0; i < length; i++) { x11_atom_interner_adopt_atom(interner, iter[i], &keymap->group_names[i]); } return true; fail: return false; } static bool get_key_names(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { int length = xcb_xkb_get_names_value_list_key_names_length(reply, list); xcb_xkb_key_name_iterator_t iter = xcb_xkb_get_names_value_list_key_names_iterator(reply, list); FAIL_UNLESS(reply->minKeyCode == keymap->min_key_code); FAIL_UNLESS(reply->maxKeyCode == keymap->max_key_code); FAIL_UNLESS(reply->firstKey == keymap->min_key_code); FAIL_UNLESS(reply->firstKey + reply->nKeys - 1U == keymap->max_key_code); for (int i = 0; i < length; i++) { xcb_xkb_key_name_t *wire = iter.data; xkb_atom_t *key_name = &keymap->keys[reply->firstKey + i].name; if (wire->name[0] == '\0') { *key_name = XKB_ATOM_NONE; } else { *key_name = xkb_atom_intern(keymap->ctx, wire->name, strnlen(wire->name, XCB_XKB_CONST_KEY_NAME_LENGTH)); if (!*key_name) return false; } xcb_xkb_key_name_next(&iter); } return true; fail: return false; } static bool get_aliases(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { int length = xcb_xkb_get_names_value_list_key_aliases_length(reply, list); xcb_xkb_key_alias_iterator_t iter = xcb_xkb_get_names_value_list_key_aliases_iterator(reply, list); keymap->num_key_aliases = reply->nKeyAliases; ALLOC_OR_FAIL(keymap->key_aliases, keymap->num_key_aliases); for (int i = 0; i < length; i++) { xcb_xkb_key_alias_t *wire = iter.data; struct xkb_key_alias *alias = &keymap->key_aliases[i]; alias->real = xkb_atom_intern(keymap->ctx, wire->real, strnlen(wire->real, XCB_XKB_CONST_KEY_NAME_LENGTH)); alias->alias = xkb_atom_intern(keymap->ctx, wire->alias, strnlen(wire->alias, XCB_XKB_CONST_KEY_NAME_LENGTH)); if (!alias->real || !alias->alias) goto fail; xcb_xkb_key_alias_next(&iter); } return true; fail: return false; } static bool get_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, xcb_xkb_get_names_cookie_t cookie) { xcb_connection_t *conn = interner->conn; xcb_xkb_get_names_reply_t *reply = xcb_xkb_get_names_reply(conn, cookie, NULL); xcb_xkb_get_names_value_list_t list; FAIL_IF_BAD_REPLY(reply, "XkbGetNames"); FAIL_UNLESS((reply->which & get_names_required) == get_names_required); xcb_xkb_get_names_value_list_unpack(xcb_xkb_get_names_value_list(reply), reply->nTypes, reply->indicators, reply->virtualMods, reply->groupNames, reply->nKeys, reply->nKeyAliases, reply->nRadioGroups, reply->which, &list); x11_atom_interner_get_escaped_atom_name(interner, list.keycodesName, &keymap->keycodes_section_name); x11_atom_interner_get_escaped_atom_name(interner, list.symbolsName, &keymap->symbols_section_name); x11_atom_interner_get_escaped_atom_name(interner, list.typesName, &keymap->types_section_name); x11_atom_interner_get_escaped_atom_name(interner, list.compatName, &keymap->compat_section_name); if (!get_type_names(keymap, interner, reply, &list) || !get_indicator_names(keymap, interner, reply, &list) || !get_vmod_names(keymap, interner, reply, &list) || !get_group_names(keymap, interner, reply, &list) || !get_key_names(keymap, conn, reply, &list) || !get_aliases(keymap, conn, reply, &list)) goto fail; free(reply); return true; fail: free(reply); return false; } static bool get_controls(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_xkb_get_controls_cookie_t cookie) { xcb_xkb_get_controls_reply_t *reply = xcb_xkb_get_controls_reply(conn, cookie, NULL); FAIL_IF_BAD_REPLY(reply, "XkbGetControls"); FAIL_UNLESS(reply->numGroups > 0 && reply->numGroups <= 4); keymap->enabled_ctrls = translate_controls_mask(reply->enabledControls); keymap->num_groups = reply->numGroups; FAIL_UNLESS(keymap->max_key_code < XCB_XKB_CONST_PER_KEY_BIT_ARRAY_SIZE * 8); for (xkb_keycode_t i = keymap->min_key_code; i <= keymap->max_key_code; i++) keymap->keys[i].repeats = (reply->perKeyRepeat[i / 8] & (1u << (i % 8))); free(reply); return true; fail: free(reply); return false; } struct xkb_keymap * xkb_x11_keymap_new_from_device(struct xkb_context *ctx, xcb_connection_t *conn, int32_t device_id, enum xkb_keymap_compile_flags flags) { struct xkb_keymap *keymap; const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1; if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "unrecognized flags: %#x\n", flags); return NULL; } if (device_id < 0 || device_id > 127) { log_err_func(ctx, XKB_LOG_MESSAGE_NO_ID, "illegal device ID: %"PRId32"\n", device_id); return NULL; } keymap = xkb_keymap_new(ctx, format, flags); if (!keymap) return NULL; struct x11_atom_interner interner; x11_atom_interner_init(&interner, ctx, conn); /* * Send all requests together so only one roundtrip is needed * to get the replies. */ xcb_xkb_get_map_cookie_t map_cookie = xcb_xkb_get_map(conn, device_id, get_map_required_components, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); xcb_xkb_get_indicator_map_cookie_t indicator_map_cookie = xcb_xkb_get_indicator_map(conn, device_id, ALL_INDICATORS_MASK); xcb_xkb_get_compat_map_cookie_t compat_map_cookie = xcb_xkb_get_compat_map(conn, device_id, 0, true, 0, 0); xcb_xkb_get_names_cookie_t names_cookie = xcb_xkb_get_names(conn, device_id, get_names_wanted); xcb_xkb_get_controls_cookie_t controls_cookie = xcb_xkb_get_controls(conn, device_id); if (!get_map(keymap, conn, map_cookie)) goto err_map; if (!get_indicator_map(keymap, conn, indicator_map_cookie)) goto err_indicator_map; if (!get_compat_map(keymap, conn, compat_map_cookie)) goto err_compat_map; if (!get_names(keymap, &interner, names_cookie)) goto err_names; if (!get_controls(keymap, conn, controls_cookie)) goto err_controls; x11_atom_interner_round_trip(&interner); if (interner.had_error) goto err_interner; return keymap; err_map: xcb_discard_reply(conn, indicator_map_cookie.sequence); err_indicator_map: xcb_discard_reply(conn, compat_map_cookie.sequence); err_compat_map: xcb_discard_reply(conn, names_cookie.sequence); err_names: xcb_discard_reply(conn, controls_cookie.sequence); err_controls: x11_atom_interner_round_trip(&interner); err_interner: xkb_keymap_unref(keymap); return NULL; } xkbcommon-libxkbcommon-54ee7ac/src/x11/state.c000066400000000000000000000025471510033435100213570ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include "x11-priv.h" static bool update_initial_state(struct xkb_state *state, xcb_connection_t *conn, uint16_t device_id) { xcb_xkb_get_state_cookie_t cookie = xcb_xkb_get_state(conn, device_id); xcb_xkb_get_state_reply_t *reply = xcb_xkb_get_state_reply(conn, cookie, NULL); if (!reply) return false; xkb_state_update_mask(state, reply->baseMods, reply->latchedMods, reply->lockedMods, reply->baseGroup, reply->latchedGroup, reply->lockedGroup); free(reply); return true; } struct xkb_state * xkb_x11_state_new_from_device(struct xkb_keymap *keymap, xcb_connection_t *conn, int32_t device_id) { struct xkb_state *state; if (device_id < 0 || device_id > 255) { log_err_func(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "illegal device ID: %"PRId32, device_id); return NULL; } state = xkb_state_new(keymap); if (!state) return NULL; if (!update_initial_state(state, conn, device_id)) { xkb_state_unref(state); return NULL; } return state; } xkbcommon-libxkbcommon-54ee7ac/src/x11/util.c000066400000000000000000000205031510033435100212040ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include "x11-priv.h" int xkb_x11_setup_xkb_extension(xcb_connection_t *conn, uint16_t major_xkb_version, uint16_t minor_xkb_version, enum xkb_x11_setup_xkb_extension_flags flags, uint16_t *major_xkb_version_out, uint16_t *minor_xkb_version_out, uint8_t *base_event_out, uint8_t *base_error_out) { uint8_t base_event, base_error; uint16_t server_major, server_minor; if (flags & ~(XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS)) { /* log_err_func(ctx, "unrecognized flags: %#x\n", flags); */ return 0; } { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(conn, &xcb_xkb_id); if (!reply) { /* log_err_func(ctx, "failed to query for XKB extension\n"); */ return 0; } if (!reply->present) { /* log_err_func(ctx, "failed to start using XKB extension: not available in server\n"); */ return 0; } base_event = reply->first_event; base_error = reply->first_error; } { xcb_generic_error_t *error = NULL; xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension(conn, major_xkb_version, minor_xkb_version); xcb_xkb_use_extension_reply_t *reply = xcb_xkb_use_extension_reply(conn, cookie, &error); if (!reply) { /* log_err_func(ctx, */ /* "failed to start using XKB extension: error code %d\n", */ /* error ? error->error_code : -1); */ free(error); return 0; } if (!reply->supported) { /* log_err_func(ctx, */ /* "failed to start using XKB extension: server doesn't support version %d.%d\n", */ /* major_xkb_version, minor_xkb_version); */ free(reply); return 0; } server_major = reply->serverMajor; server_minor = reply->serverMinor; free(reply); } /* * The XkbUseExtension() in libX11 has a *bunch* of legacy stuff, but * it doesn't seem like any of it is useful to us. */ if (major_xkb_version_out) *major_xkb_version_out = server_major; if (minor_xkb_version_out) *minor_xkb_version_out = server_minor; if (base_event_out) *base_event_out = base_event; if (base_error_out) *base_error_out = base_error; return 1; } int32_t xkb_x11_get_core_keyboard_device_id(xcb_connection_t *conn) { int32_t device_id; xcb_xkb_get_device_info_cookie_t cookie = xcb_xkb_get_device_info(conn, XCB_XKB_ID_USE_CORE_KBD, 0, 0, 0, 0, 0, 0); xcb_xkb_get_device_info_reply_t *reply = xcb_xkb_get_device_info_reply(conn, cookie, NULL); if (!reply) return -1; device_id = reply->deviceID; free(reply); return device_id; } struct x11_atom_cache { /* * Invalidate the cache based on the XCB connection. * X11 atoms are actually not per connection or client, but per X server * session. But better be safe just in case we survive an X server restart. */ xcb_connection_t *conn; struct { xcb_atom_t from; xkb_atom_t to; } cache[256]; size_t len; }; static struct x11_atom_cache * get_cache(struct xkb_context *ctx, xcb_connection_t *conn) { if (!ctx->x11_atom_cache) { ctx->x11_atom_cache = calloc(1, sizeof(struct x11_atom_cache)); } /* Can be NULL in case the malloc failed. */ struct x11_atom_cache *cache = ctx->x11_atom_cache; if (cache && cache->conn != conn) { cache->conn = conn; cache->len = 0; } return cache; } void x11_atom_interner_init(struct x11_atom_interner *interner, struct xkb_context *ctx, xcb_connection_t *conn) { interner->had_error = false; interner->ctx = ctx; interner->conn = conn; interner->num_pending = 0; interner->num_copies = 0; interner->num_escaped = 0; } void x11_atom_interner_adopt_atom(struct x11_atom_interner *interner, const xcb_atom_t atom, xkb_atom_t *out) { *out = XKB_ATOM_NONE; if (atom == XCB_ATOM_NONE) return; /* Can be NULL in case the malloc failed. */ struct x11_atom_cache *cache = get_cache(interner->ctx, interner->conn); retry: /* Already in the cache? */ if (cache) { for (size_t c = 0; c < cache->len; c++) { if (cache->cache[c].from == atom) { *out = cache->cache[c].to; return; } } } /* Already pending? */ for (size_t i = 0; i < interner->num_pending; i++) { if (interner->pending[i].from == atom) { if (interner->num_copies == ARRAY_SIZE(interner->copies)) { x11_atom_interner_round_trip(interner); goto retry; } size_t idx = interner->num_copies++; interner->copies[idx].from = atom; interner->copies[idx].out = out; return; } } /* We have to send a GetAtomName request */ if (interner->num_pending == ARRAY_SIZE(interner->pending)) { x11_atom_interner_round_trip(interner); assert(interner->num_pending < ARRAY_SIZE(interner->pending)); } size_t idx = interner->num_pending++; interner->pending[idx].from = atom; interner->pending[idx].out = out; interner->pending[idx].cookie = xcb_get_atom_name(interner->conn, atom); } void x11_atom_interner_round_trip(struct x11_atom_interner *interner) { struct xkb_context *ctx = interner->ctx; xcb_connection_t *conn = interner->conn; /* Can be NULL in case the malloc failed. */ struct x11_atom_cache *cache = get_cache(ctx, conn); for (size_t i = 0; i < interner->num_pending; i++) { xcb_get_atom_name_reply_t *reply; reply = xcb_get_atom_name_reply(conn, interner->pending[i].cookie, NULL); if (!reply) { interner->had_error = true; continue; } xcb_atom_t x11_atom = interner->pending[i].from; xkb_atom_t atom = xkb_atom_intern(ctx, xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply)); free(reply); if (cache && cache->len < ARRAY_SIZE(cache->cache)) { size_t idx = cache->len++; cache->cache[idx].from = x11_atom; cache->cache[idx].to = atom; } *interner->pending[i].out = atom; for (size_t j = 0; j < interner->num_copies; j++) { if (interner->copies[j].from == x11_atom) *interner->copies[j].out = atom; } } for (size_t i = 0; i < interner->num_escaped; i++) { xcb_get_atom_name_reply_t *reply; int length; char *name; char **out = interner->escaped[i].out; reply = xcb_get_atom_name_reply(conn, interner->escaped[i].cookie, NULL); *interner->escaped[i].out = NULL; if (!reply) { interner->had_error = true; } else { length = xcb_get_atom_name_name_length(reply); name = xcb_get_atom_name_name(reply); *out = strndup(name, length); free(reply); if (*out == NULL) { interner->had_error = true; } else { XkbEscapeMapName(*out); } } } interner->num_pending = 0; interner->num_copies = 0; interner->num_escaped = 0; } void x11_atom_interner_get_escaped_atom_name(struct x11_atom_interner *interner, xcb_atom_t atom, char **out) { if (atom == 0) { *out = NULL; return; } size_t idx = interner->num_escaped++; /* There can only be a fixed number of calls to this function "in-flight", * thus we assert this number. Increase the array size if this assert fails. */ assert(idx < ARRAY_SIZE(interner->escaped)); interner->escaped[idx].out = out; interner->escaped[idx].cookie = xcb_get_atom_name(interner->conn, atom); } xkbcommon-libxkbcommon-54ee7ac/src/x11/x11-priv.h000066400000000000000000000032221510033435100216220ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include "keymap.h" #include "xkbcommon/xkbcommon-x11.h" struct x11_atom_interner { struct xkb_context *ctx; xcb_connection_t *conn; bool had_error; /* Atoms for which we send a GetAtomName request */ struct { xcb_atom_t from; xkb_atom_t *out; xcb_get_atom_name_cookie_t cookie; } pending[128]; size_t num_pending; /* Atoms which were already pending but queried again */ struct { xcb_atom_t from; xkb_atom_t *out; } copies[128]; size_t num_copies; /* These are not interned, but saved directly (after XkbEscapeMapName) */ struct { xcb_get_atom_name_cookie_t cookie; char **out; } escaped[4]; size_t num_escaped; }; void x11_atom_interner_init(struct x11_atom_interner *interner, struct xkb_context *ctx, xcb_connection_t *conn); void x11_atom_interner_round_trip(struct x11_atom_interner *interner); /* * Make a xkb_atom_t's from X atoms. The actual write is delayed until the next * call to x11_atom_interner_round_trip() or when too many atoms are pending. */ void x11_atom_interner_adopt_atom(struct x11_atom_interner *interner, const xcb_atom_t atom, xkb_atom_t *out); /* * Get a strdup'd and XkbEscapeMapName'd name of an X atom. The actual write is * delayed until the next call to x11_atom_interner_round_trip(). */ void x11_atom_interner_get_escaped_atom_name(struct x11_atom_interner *interner, xcb_atom_t atom, char **out); xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/000077500000000000000000000000001510033435100211155ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/action.c000066400000000000000000001053001510033435100225350ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT * * Author: Daniel Stone * Author: Ran Benita */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "context.h" #include "keymap.h" #include "messages-codes.h" #include "xkbcomp-priv.h" #include "text.h" #include "expr.h" #include "xkbcomp/ast.h" #include "action.h" static const ExprBoolean constTrue = { .common = { .type = STMT_EXPR_BOOLEAN_LITERAL, .next = NULL }, .set = true, }; static const ExprBoolean constFalse = { .common = { .type = STMT_EXPR_BOOLEAN_LITERAL, .next = NULL }, .set = false, }; enum action_field { ACTION_FIELD_CLEAR_LOCKS, ACTION_FIELD_LATCH_TO_LOCK, ACTION_FIELD_GEN_KEY_EVENT, ACTION_FIELD_REPORT, ACTION_FIELD_DEFAULT, ACTION_FIELD_AFFECT, ACTION_FIELD_INCREMENT, ACTION_FIELD_MODIFIERS, ACTION_FIELD_GROUP, ACTION_FIELD_X, ACTION_FIELD_Y, ACTION_FIELD_ACCEL, ACTION_FIELD_BUTTON, ACTION_FIELD_VALUE, ACTION_FIELD_CONTROLS, ACTION_FIELD_TYPE, ACTION_FIELD_COUNT, ACTION_FIELD_SCREEN, ACTION_FIELD_SAME, ACTION_FIELD_DATA, ACTION_FIELD_DEVICE, ACTION_FIELD_KEYCODE, ACTION_FIELD_MODS_TO_CLEAR, ACTION_FIELD_LOCK_ON_RELEASE, ACTION_FIELD_UNLOCK_ON_PRESS, ACTION_FIELD_LATCH_ON_PRESS, }; void InitActionsInfo(ActionsInfo *info) { for (enum xkb_action_type type = 0; type < _ACTION_TYPE_NUM_ENTRIES; type++) info->actions[type].type = type; /* Apply some "factory defaults". */ /* Increment default button. */ info->actions[ACTION_TYPE_PTR_DEFAULT].dflt.flags = 0; info->actions[ACTION_TYPE_PTR_DEFAULT].dflt.value = 1; info->actions[ACTION_TYPE_PTR_MOVE].ptr.flags = ACTION_ACCEL; info->actions[ACTION_TYPE_SWITCH_VT].screen.flags = ACTION_SAME_SCREEN; } static const LookupEntry fieldStrings[] = { { "clearLocks", ACTION_FIELD_CLEAR_LOCKS }, { "latchToLock", ACTION_FIELD_LATCH_TO_LOCK }, { "genKeyEvent", ACTION_FIELD_GEN_KEY_EVENT }, { "generateKeyEvent", ACTION_FIELD_GEN_KEY_EVENT }, { "report", ACTION_FIELD_REPORT }, { "default", ACTION_FIELD_DEFAULT }, { "affect", ACTION_FIELD_AFFECT }, { "increment", ACTION_FIELD_INCREMENT }, { "modifiers", ACTION_FIELD_MODIFIERS }, { "mods", ACTION_FIELD_MODIFIERS }, { "group", ACTION_FIELD_GROUP }, { "x", ACTION_FIELD_X }, { "y", ACTION_FIELD_Y }, { "accel", ACTION_FIELD_ACCEL }, { "accelerate", ACTION_FIELD_ACCEL }, { "repeat", ACTION_FIELD_ACCEL }, { "button", ACTION_FIELD_BUTTON }, { "value", ACTION_FIELD_VALUE }, { "controls", ACTION_FIELD_CONTROLS }, { "ctrls", ACTION_FIELD_CONTROLS }, { "type", ACTION_FIELD_TYPE }, { "count", ACTION_FIELD_COUNT }, { "screen", ACTION_FIELD_SCREEN }, { "same", ACTION_FIELD_SAME }, { "sameServer", ACTION_FIELD_SAME }, { "data", ACTION_FIELD_DATA }, { "device", ACTION_FIELD_DEVICE }, { "dev", ACTION_FIELD_DEVICE }, { "key", ACTION_FIELD_KEYCODE }, { "keycode", ACTION_FIELD_KEYCODE }, { "kc", ACTION_FIELD_KEYCODE }, { "clearmods", ACTION_FIELD_MODS_TO_CLEAR }, { "clearmodifiers", ACTION_FIELD_MODS_TO_CLEAR }, { "lockOnRelease", ACTION_FIELD_LOCK_ON_RELEASE }, { "unlockOnPress", ACTION_FIELD_UNLOCK_ON_PRESS }, { "latchOnPress", ACTION_FIELD_LATCH_ON_PRESS }, { NULL, 0 } }; static bool stringToActionType(const char *str, enum xkb_action_type *type_rtrn) { unsigned int type = 0; const bool ret = LookupString(actionTypeNames, str, &type); *type_rtrn = (enum xkb_action_type) type; return ret; } static bool stringToField(const char *str, enum action_field *field_rtrn) { unsigned int field = 0; const bool ret = LookupString(fieldStrings, str, &field); *field_rtrn = (enum action_field) field; return ret; } static const char * fieldText(enum action_field field) { return LookupValue(fieldStrings, field); } /***====================================================================***/ static inline bool ReportMismatch(struct xkb_context *ctx, xkb_message_code_t code, enum xkb_action_type action, enum action_field field, const char *type) { log_err(ctx, code, "Value of %s field must be of type %s; " "Action %s definition ignored\n", fieldText(field), type, ActionTypeText(action)); return false; } static inline bool ReportFormatVersionMismatch(struct xkb_context *ctx, enum xkb_action_type action, enum action_field field, enum xkb_keymap_format format, const char *versions) { log_err(ctx, XKB_ERROR_INCOMPATIBLE_KEYMAP_TEXT_FORMAT, "Field %s for an action of type %s requires keymap text format %s, " " but got: %d; Action definition ignored\n", fieldText(field), ActionTypeText(action), versions, format); return false; } static inline bool ReportIllegal(struct xkb_context *ctx, enum xkb_action_type action, enum action_field field) { log_err(ctx, XKB_ERROR_INVALID_ACTION_FIELD, "Field %s is not defined for an action of type %s; " "Action definition ignored\n", fieldText(field), ActionTypeText(action)); return false; } static inline bool ReportActionNotArray(struct xkb_context *ctx, enum xkb_action_type action, enum action_field field) { log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "The %s field in the %s action is not an array; " "Action definition ignored\n", fieldText(field), ActionTypeText(action)); return false; } static bool HandleNoAction(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { log_err(ctx, XKB_ERROR_INVALID_ACTION_FIELD, "The \"%s\" action takes no argument, but got \"%s\" field; " "Action definition ignored\n", ActionTypeText(action->type), fieldText(field)); return false; } static bool CheckBooleanFlag(struct xkb_context *ctx, enum xkb_action_type action, enum action_field field, enum xkb_action_flags flag, const ExprDef *array_ndx, const ExprDef *value, enum xkb_action_flags *flags_inout) { bool set = false; if (array_ndx) return ReportActionNotArray(ctx, action, field); if (!ExprResolveBoolean(ctx, value, &set)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action, field, "boolean"); if (set) *flags_inout |= flag; else *flags_inout &= ~flag; return true; } static bool CheckModifierField(struct xkb_context *ctx, const struct xkb_mod_set *mods, enum xkb_action_type action, const ExprDef *array_ndx, const ExprDef *value, enum xkb_action_flags *flags_inout, xkb_mod_mask_t *mods_rtrn) { if (array_ndx) return ReportActionNotArray(ctx, action, ACTION_FIELD_MODIFIERS); if (value->common.type == STMT_EXPR_IDENT) { const char *valStr; valStr = xkb_atom_text(ctx, value->ident.ident); if (valStr && (istreq(valStr, "usemodmapmods") || istreq(valStr, "modmapmods"))) { *mods_rtrn = 0; *flags_inout |= ACTION_MODS_LOOKUP_MODMAP; return true; } } if (!ExprResolveModMask(ctx, value, MOD_BOTH, mods, mods_rtrn)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action, ACTION_FIELD_MODIFIERS, "modifier mask"); *flags_inout &= ~ACTION_MODS_LOOKUP_MODMAP; return true; } static const LookupEntry lockWhich[] = { { "both", 0 }, { "lock", ACTION_LOCK_NO_UNLOCK }, { "neither", (ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK) }, { "unlock", ACTION_LOCK_NO_LOCK }, { NULL, 0 } }; static bool CheckAffectField(struct xkb_context *ctx, enum xkb_action_type action, const ExprDef *array_ndx, const ExprDef *value, enum xkb_action_flags *flags_inout) { if (array_ndx) return ReportActionNotArray(ctx, action, ACTION_FIELD_AFFECT); uint32_t flags = 0; if (!ExprResolveEnum(ctx, value, &flags, lockWhich)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action, ACTION_FIELD_AFFECT, "lock, unlock, both, neither"); *flags_inout &= ~(ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK); *flags_inout |= (enum xkb_action_flags) flags; return true; } static bool HandleSetLatchLockMods(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { struct xkb_mod_action *act = &action->mods; const enum xkb_action_type type = action->type; if (field == ACTION_FIELD_MODIFIERS) return CheckModifierField(ctx, mods, action->type, array_ndx, value, &act->flags, &act->mods.mods); if (field == ACTION_FIELD_UNLOCK_ON_PRESS) { /* Ensure to update if a new modifier action is introduced. */ assert(type == ACTION_TYPE_MOD_SET || type == ACTION_TYPE_MOD_LATCH || type == ACTION_TYPE_MOD_LOCK); if (isModsUnLockOnPressSupported(format)) { return CheckBooleanFlag(ctx, action->type, field, ACTION_UNLOCK_ON_PRESS, array_ndx, value, &act->flags); } else { return ReportFormatVersionMismatch(ctx, action->type, field, format, ">= 2"); } } if ((type == ACTION_TYPE_MOD_SET || type == ACTION_TYPE_MOD_LATCH) && field == ACTION_FIELD_CLEAR_LOCKS) return CheckBooleanFlag(ctx, action->type, field, ACTION_LOCK_CLEAR, array_ndx, value, &act->flags); if (type == ACTION_TYPE_MOD_LATCH) { if (field == ACTION_FIELD_LATCH_TO_LOCK) return CheckBooleanFlag(ctx, action->type, field, ACTION_LATCH_TO_LOCK, array_ndx, value, &act->flags); if (field == ACTION_FIELD_LATCH_ON_PRESS) { if (isModsLatchOnPressSupported(format)) { return CheckBooleanFlag(ctx, action->type, field, ACTION_LATCH_ON_PRESS, array_ndx, value, &act->flags); } else { return ReportFormatVersionMismatch(ctx, action->type, field, format, ">= 2"); } } } if (type == ACTION_TYPE_MOD_LOCK && field == ACTION_FIELD_AFFECT) return CheckAffectField(ctx, action->type, array_ndx, value, &act->flags); return ReportIllegal(ctx, action->type, field); } static bool CheckGroupField(struct xkb_context *ctx, enum xkb_action_type action, xkb_layout_index_t max_groups, const ExprDef *array_ndx, const ExprDef *value, enum xkb_action_flags *flags_inout, int32_t *group_rtrn) { const ExprDef *spec; xkb_layout_index_t idx = 0; enum xkb_action_flags flags = *flags_inout; if (array_ndx) return ReportActionNotArray(ctx, action, ACTION_FIELD_GROUP); if (value->common.type == STMT_EXPR_NEGATE || value->common.type == STMT_EXPR_UNARY_PLUS) { flags &= ~ACTION_ABSOLUTE_SWITCH; spec = value->unary.child; } else { flags |= ACTION_ABSOLUTE_SWITCH; spec = value; } if (!ExprResolveGroup(ctx, max_groups, spec, &idx)) return ReportMismatch(ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, action, ACTION_FIELD_GROUP, "integer"); /* `+n`, `-n` are relative, `n` is absolute. */ if (value->common.type == STMT_EXPR_NEGATE || value->common.type == STMT_EXPR_UNARY_PLUS) { *group_rtrn = (int32_t) idx; if (value->common.type == STMT_EXPR_NEGATE) *group_rtrn = -*group_rtrn; } else { *group_rtrn = (int32_t) (idx - 1); } *flags_inout = flags; return true; } static bool HandleSetLatchLockGroup(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { struct xkb_group_action *act = &action->group; const enum xkb_action_type type = action->type; if (field == ACTION_FIELD_GROUP) { const xkb_layout_index_t max_groups = format_max_groups(format); return CheckGroupField(ctx, action->type, max_groups, array_ndx, value, &act->flags, &act->group); } if ((type == ACTION_TYPE_GROUP_SET || type == ACTION_TYPE_GROUP_LATCH) && field == ACTION_FIELD_CLEAR_LOCKS) return CheckBooleanFlag(ctx, action->type, field, ACTION_LOCK_CLEAR, array_ndx, value, &act->flags); if (type == ACTION_TYPE_GROUP_LATCH && field == ACTION_FIELD_LATCH_TO_LOCK) return CheckBooleanFlag(ctx, action->type, field, ACTION_LATCH_TO_LOCK, array_ndx, value, &act->flags); if (type == ACTION_TYPE_GROUP_LOCK && field == ACTION_FIELD_LOCK_ON_RELEASE) { /* TODO: support this for `ACTION_TYPE_MOD_LOCK` too? */ if (isGroupLockOnReleaseSupported(format)) { return CheckBooleanFlag(ctx, action->type, field, ACTION_LOCK_ON_RELEASE, array_ndx, value, &act->flags); } else { return ReportFormatVersionMismatch(ctx, action->type, field, format, ">= v2"); } } return ReportIllegal(ctx, action->type, field); } static bool HandleMovePtr(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { struct xkb_pointer_action *act = &action->ptr; if (field == ACTION_FIELD_X || field == ACTION_FIELD_Y) { int64_t val = 0; const bool absolute = (value->common.type != STMT_EXPR_NEGATE && value->common.type != STMT_EXPR_UNARY_PLUS); if (array_ndx) return ReportActionNotArray(ctx, action->type, field); if (!ExprResolveInteger(ctx, value, &val)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action->type, field, "integer"); if (val < INT16_MIN || val > INT16_MAX) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "The %s field in the %s action must be in range %d..%d, " "but got %"PRId64". Action definition ignored\n", fieldText(field), ActionTypeText(action->type), INT16_MIN, INT16_MAX, val); return false; } if (field == ACTION_FIELD_X) { if (absolute) act->flags |= ACTION_ABSOLUTE_X; act->x = (int16_t) val; } else { if (absolute) act->flags |= ACTION_ABSOLUTE_Y; act->y = (int16_t) val; } return true; } else if (field == ACTION_FIELD_ACCEL) { return CheckBooleanFlag(ctx, action->type, field, ACTION_ACCEL, array_ndx, value, &act->flags); } return ReportIllegal(ctx, action->type, field); } static bool HandlePtrBtn(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { struct xkb_pointer_button_action *act = &action->btn; if (field == ACTION_FIELD_BUTTON) { int64_t btn = 0; if (array_ndx) return ReportActionNotArray(ctx, action->type, field); if (!ExprResolveButton(ctx, value, &btn)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action->type, field, "integer (range 1..5)"); if (btn < 0 || btn > 5) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Button must specify default or be in the range 1..5; " "Illegal button value %"PRId64" ignored\n", btn); return false; } act->button = (uint8_t) btn; return true; } else if (action->type == ACTION_TYPE_PTR_LOCK && field == ACTION_FIELD_AFFECT) { return CheckAffectField(ctx, action->type, array_ndx, value, &act->flags); } else if (field == ACTION_FIELD_COUNT) { int64_t val = 0; if (array_ndx) return ReportActionNotArray(ctx, action->type, field); if (!ExprResolveInteger(ctx, value, &val)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action->type, field, "integer"); if (val < 0 || val > 255) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "The count field must have a value in the range 0..255; " "Illegal count %"PRId64" ignored\n", val); return false; } act->count = (uint8_t) val; return true; } return ReportIllegal(ctx, action->type, field); } static const LookupEntry ptrDflts[] = { { "dfltbtn", 1 }, { "defaultbutton", 1 }, { "button", 1 }, { NULL, 0 } }; static bool HandleSetPtrDflt(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { struct xkb_pointer_default_action *act = &action->dflt; if (field == ACTION_FIELD_AFFECT) { uint32_t val = 0; if (array_ndx) return ReportActionNotArray(ctx, action->type, field); if (!ExprResolveEnum(ctx, value, &val, ptrDflts)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action->type, field, "pointer component"); return true; } else if (field == ACTION_FIELD_BUTTON || field == ACTION_FIELD_VALUE) { const ExprDef *button; int64_t btn = 0; if (array_ndx) return ReportActionNotArray(ctx, action->type, field); if (value->common.type == STMT_EXPR_NEGATE || value->common.type == STMT_EXPR_UNARY_PLUS) { act->flags &= ~ACTION_ABSOLUTE_SWITCH; button = value->unary.child; } else { act->flags |= ACTION_ABSOLUTE_SWITCH; button = value; } if (!ExprResolveButton(ctx, button, &btn)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action->type, field, "integer (range 1..5)"); if (btn < 0 || btn > 5) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "New default button value must be in the range 1..5; " "Illegal default button value %"PRId64" ignored\n", btn); return false; } if (btn == 0) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Cannot set default pointer button to \"default\"; " "Illegal default button setting ignored\n"); return false; } act->value = (int8_t) (value->common.type == STMT_EXPR_NEGATE ? -btn: btn); return true; } return ReportIllegal(ctx, action->type, field); } static bool HandleSwitchScreen(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { struct xkb_switch_screen_action *act = &action->screen; if (field == ACTION_FIELD_SCREEN) { const ExprDef *scrn; int64_t val = 0; if (array_ndx) return ReportActionNotArray(ctx, action->type, field); if (value->common.type == STMT_EXPR_NEGATE || value->common.type == STMT_EXPR_UNARY_PLUS) { act->flags &= ~ACTION_ABSOLUTE_SWITCH; scrn = value->unary.child; } else { act->flags |= ACTION_ABSOLUTE_SWITCH; scrn = value; } if (!ExprResolveInteger(ctx, scrn, &val)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action->type, field, "integer (-128..127)"); val = (value->common.type == STMT_EXPR_NEGATE ? -val : val); if (val < INT8_MIN || val > INT8_MAX) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Screen index must be in the range %d..%d; " "Illegal screen value %"PRId64" ignored\n", INT8_MIN, INT8_MAX, val); return false; } act->screen = (int8_t) val; return true; } else if (field == ACTION_FIELD_SAME) { return CheckBooleanFlag(ctx, action->type, field, ACTION_SAME_SCREEN, array_ndx, value, &act->flags); } return ReportIllegal(ctx, action->type, field); } static bool HandleSetLockControls(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { struct xkb_controls_action *act = &action->ctrls; if (field == ACTION_FIELD_CONTROLS) { if (array_ndx) return ReportActionNotArray(ctx, action->type, field); uint32_t mask = 0; if (!ExprResolveMask(ctx, value, &mask, ctrlMaskNames)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action->type, field, "controls mask"); act->ctrls = (enum xkb_action_controls) mask; return true; } else if (field == ACTION_FIELD_AFFECT && action->type == ACTION_TYPE_CTRL_LOCK) { return CheckAffectField(ctx, action->type, array_ndx, value, &act->flags); } return ReportIllegal(ctx, action->type, field); } static bool HandleUnsupportedLegacy(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { /* Do not check any field */ return true; } static bool HandlePrivate(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value) { struct xkb_private_action *act = &action->priv; if (field == ACTION_FIELD_TYPE) { int64_t type = 0; if (array_ndx) return ReportActionNotArray(ctx, action->type, field); if (!ExprResolveInteger(ctx, value, &type)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, ACTION_TYPE_PRIVATE, field, "integer"); if (type < 0 || type > 255) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Private action type must be in the range 0..255; " "Illegal type %"PRId64" ignored\n", type); return false; } /* * It's possible for someone to write something like this: * actions = [ Private(type=3,data[0]=1,data[1]=3,data[2]=3) ] * where the type refers to some existing action type, e.g. LockMods. * This assumes that this action's struct is laid out in memory * exactly as described in the XKB specification and libraries. * We, however, have changed these structs in various ways, so this * assumption is no longer true. Since this is a lousy "feature", we * make actions like these no-ops for now. */ if (type < ACTION_TYPE_PRIVATE) { log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "Private actions of type %s are not supported; Ignored\n", ActionTypeText((enum xkb_action_type) type)); act->type = ACTION_TYPE_NONE; } else { act->type = (enum xkb_action_type) type; } return true; } else if (field == ACTION_FIELD_DATA) { if (array_ndx == NULL) { xkb_atom_t val = XKB_ATOM_NONE; if (!ExprResolveString(ctx, value, &val)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, action->type, field, "string"); const char *str = xkb_atom_text(ctx, val); size_t len = strlen(str); if (len < 1 || len > sizeof(act->data)) { log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "A private action has %zu data bytes; " "Illegal data ignored\n", sizeof(act->data)); return false; } /* act->data may not be null-terminated, this is intentional */ memset(act->data, 0, sizeof(act->data)); memcpy(act->data, str, len); return true; } else { int64_t ndx = 0, datum = 0; if (!ExprResolveInteger(ctx, array_ndx, &ndx)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Array subscript must be integer; " "Illegal subscript ignored\n"); return false; } if (ndx < 0 || (size_t) ndx >= sizeof(act->data)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "The data for a private action is %zu bytes long; " "Attempt to use data[%"PRId64"] ignored\n", sizeof(act->data), ndx); return false; } if (!ExprResolveInteger(ctx, value, &datum)) return ReportMismatch(ctx, XKB_ERROR_WRONG_FIELD_TYPE, act->type, field, "integer"); if (datum < 0 || datum > 255) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "All data for a private action must be 0..255; " "Illegal datum %"PRId64" ignored\n", datum); return false; } act->data[ndx] = (uint8_t) datum; return true; } } return ReportIllegal(ctx, ACTION_TYPE_NONE, field); } typedef bool (*actionHandler)(struct xkb_context *ctx, enum xkb_keymap_format format, const struct xkb_mod_set *mods, union xkb_action *action, enum action_field field, const ExprDef *array_ndx, const ExprDef *value); static const actionHandler handleAction[_ACTION_TYPE_NUM_ENTRIES] = { [ACTION_TYPE_NONE] = HandleNoAction, [ACTION_TYPE_VOID] = HandleNoAction, [ACTION_TYPE_MOD_SET] = HandleSetLatchLockMods, [ACTION_TYPE_MOD_LATCH] = HandleSetLatchLockMods, [ACTION_TYPE_MOD_LOCK] = HandleSetLatchLockMods, [ACTION_TYPE_GROUP_SET] = HandleSetLatchLockGroup, [ACTION_TYPE_GROUP_LATCH] = HandleSetLatchLockGroup, [ACTION_TYPE_GROUP_LOCK] = HandleSetLatchLockGroup, [ACTION_TYPE_PTR_MOVE] = HandleMovePtr, [ACTION_TYPE_PTR_BUTTON] = HandlePtrBtn, [ACTION_TYPE_PTR_LOCK] = HandlePtrBtn, [ACTION_TYPE_PTR_DEFAULT] = HandleSetPtrDflt, [ACTION_TYPE_TERMINATE] = HandleNoAction, [ACTION_TYPE_SWITCH_VT] = HandleSwitchScreen, [ACTION_TYPE_CTRL_SET] = HandleSetLockControls, [ACTION_TYPE_CTRL_LOCK] = HandleSetLockControls, [ACTION_TYPE_UNSUPPORTED_LEGACY] = HandleUnsupportedLegacy, [ACTION_TYPE_PRIVATE] = HandlePrivate, }; /* Ensure to not miss `xkb_action_type` updates */ static_assert(ACTION_TYPE_INTERNAL == 18 && ACTION_TYPE_INTERNAL + 1 == _ACTION_TYPE_NUM_ENTRIES, "Missing action type"); /***====================================================================***/ bool HandleActionDef(struct xkb_context *ctx, enum xkb_keymap_format format, ActionsInfo *info, const struct xkb_mod_set *mods, ExprDef *def, union xkb_action *action) { if (def->common.type != STMT_EXPR_ACTION_DECL) { log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Expected an action definition, found %s\n", stmt_type_to_string(def->common.type)); return false; } const char *action_name = xkb_atom_text(ctx, def->action.name); enum xkb_action_type handler_type; if (!stringToActionType(action_name, &handler_type)) { log_err(ctx, XKB_ERROR_UNKNOWN_ACTION_TYPE, "Unknown action %s\n", action_name); return false; } /* * Get the default values for this action type, as modified by * statements such as: * latchMods.clearLocks = True; */ *action = info->actions[handler_type]; if (handler_type == ACTION_TYPE_UNSUPPORTED_LEGACY) { log_warn(ctx, XKB_WARNING_UNSUPPORTED_LEGACY_ACTION, "Unsupported legacy action type \"%s\".\n", action_name); /* * Degrade to an uneffective supported action type. * Fields will still be processed with the original action type. */ action->type = ACTION_TYPE_NONE; /* FIXME: Degrading to NoAction() has the following drawbacks: * - It disables overwriting a previous action. * - It enables interpretations. */ } /* * Now change the action properties as specified for this * particular instance, e.g. "modifiers" and "clearLocks" in: * SetMods(modifiers=Alt,clearLocks); */ for (ExprDef *arg = def->action.args; arg != NULL; arg = (ExprDef *) arg->common.next) { const ExprDef *value; ExprDef *field, *arrayRtrn; const char *elemRtrn, *fieldRtrn; if (arg->common.type == STMT_EXPR_ASSIGN) { field = arg->binary.left; value = arg->binary.right; } else if (arg->common.type == STMT_EXPR_NOT || arg->common.type == STMT_EXPR_INVERT) { field = arg->unary.child; value = (const ExprDef *) &constFalse; } else { field = arg; value = (const ExprDef *) &constTrue; } if (!ExprResolveLhs(ctx, field, &elemRtrn, &fieldRtrn, &arrayRtrn)) return false; if (elemRtrn) { log_err(ctx, XKB_ERROR_GLOBAL_DEFAULTS_WRONG_SCOPE, "Cannot change defaults in an action definition; " "Ignoring attempt to change \"%s.%s\".\n", elemRtrn, fieldRtrn); return false; } enum action_field fieldNdx; if (!stringToField(fieldRtrn, &fieldNdx)) { log_err(ctx, XKB_ERROR_INVALID_ACTION_FIELD, "Unknown field name %s\n", fieldRtrn); return false; } if (!handleAction[handler_type](ctx, format, mods, action, fieldNdx, arrayRtrn, value)) return false; } return true; } bool SetDefaultActionField(struct xkb_context *ctx, enum xkb_keymap_format format, ActionsInfo *info, struct xkb_mod_set *mods, const char *elem, const char *field, ExprDef *array_ndx, ExprDef *value, enum merge_mode merge) { enum xkb_action_type action; if (!stringToActionType(elem, &action)) { log_err(ctx, XKB_ERROR_UNKNOWN_ACTION_TYPE, "Unknown action %s\n", elem); return false; } enum action_field action_field; if (!stringToField(field, &action_field)) { log_err(ctx, XKB_ERROR_INVALID_ACTION_FIELD, "\"%s\" is not a legal field name\n", field); return false; } union xkb_action* const into = &info->actions[action]; /* Initialize with current defaults to enable comparison, see aftwerwards */ union xkb_action from = *into; /* Parse action */ if (!handleAction[action](ctx, format, mods, &from, action_field, array_ndx, value)) return false; /* * Merge action with its corresponding default * * NOTE: Contrary to other items, actions do not have a “defined” field, so * we fallback to compare all the actions fields. The drawback is that it * overmatches, as even setting an *explicit* default value for the first * time (and different from the “factory” default) would *always* display a * warning. So we guard the logging with a high verbosity, as best effort * mitigation. */ if (!action_equal(into, &from)) { const bool replace = (merge != MERGE_AUGMENT); log_vrb(ctx, XKB_LOG_VERBOSITY_VERBOSE, XKB_LOG_MESSAGE_NO_ID, "Conflicting field \"%s\" for default action \"%s\"; " "Using %s, ignore %s\n", fieldText(action_field), ActionTypeText(action), (replace ? "from" : "into"), (replace ? "into" : "from")); if (replace) *into = from; } return true; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/action.h000066400000000000000000000026651510033435100225540ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #pragma once #include "config.h" #include "ast.h" #include "keymap.h" /* * This struct contains the default values which every new action * (e.g. in an interpret statement) starts off with. It can be * modified within the files (see calls to SetDefaultActionField). */ typedef struct { union xkb_action actions[_ACTION_TYPE_NUM_ENTRIES]; } ActionsInfo; void InitActionsInfo(ActionsInfo *info); bool HandleActionDef(struct xkb_context *ctx, enum xkb_keymap_format format, ActionsInfo *info, const struct xkb_mod_set *mods, ExprDef *def, union xkb_action *action); bool SetDefaultActionField(struct xkb_context *ctx, enum xkb_keymap_format format, ActionsInfo *info, struct xkb_mod_set *mods, const char *elem, const char *field, ExprDef *array_ndx, ExprDef *value, enum merge_mode merge); static inline bool isModsUnLockOnPressSupported(enum xkb_keymap_format format) { /* Lax bound */ return format >= XKB_KEYMAP_FORMAT_TEXT_V2; } static inline bool isGroupLockOnReleaseSupported(enum xkb_keymap_format format) { /* Lax bound */ return format >= XKB_KEYMAP_FORMAT_TEXT_V2; } static inline bool isModsLatchOnPressSupported(enum xkb_keymap_format format) { /* Lax bound */ return format >= XKB_KEYMAP_FORMAT_TEXT_V2; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/ast-build.c000066400000000000000000000500141510033435100231450ustar00rootroot00000000000000/* * For HPND * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT * * Author: Daniel Stone * Author: Ran Benita */ #include "config.h" #include #include "xkbcommon/xkbcommon-keysyms.h" #include "messages-codes.h" #include "xkbcomp-priv.h" #include "ast.h" #include "ast-build.h" #include "include.h" #include "keysym.h" #include "utf8-decoding.h" static ExprDef * ExprCreate(enum stmt_type op) { ExprDef *expr = malloc(sizeof(*expr)); if (!expr) return NULL; expr->common.type = op; expr->common.next = NULL; return expr; } ExprDef * ExprCreateString(xkb_atom_t str) { ExprDef *expr = ExprCreate(STMT_EXPR_STRING_LITERAL); if (!expr) return NULL; expr->string.str = str; return expr; } ExprDef * ExprCreateInteger(int64_t ival) { ExprDef *expr = ExprCreate(STMT_EXPR_INTEGER_LITERAL); if (!expr) return NULL; expr->integer.ival = ival; return expr; } ExprDef * ExprCreateFloat(void) { ExprDef *expr = ExprCreate(STMT_EXPR_FLOAT_LITERAL); if (!expr) return NULL; return expr; } ExprDef * ExprCreateBoolean(bool set) { ExprDef *expr = ExprCreate(STMT_EXPR_BOOLEAN_LITERAL); if (!expr) return NULL; expr->boolean.set = set; return expr; } ExprDef * ExprCreateKeyName(xkb_atom_t key_name) { ExprDef *expr = ExprCreate(STMT_EXPR_KEYNAME_LITERAL); if (!expr) return NULL; expr->key_name.key_name = key_name; return expr; } ExprDef * ExprCreateKeySym(xkb_keysym_t keysym) { ExprDef *expr = ExprCreate(STMT_EXPR_KEYSYM_LITERAL); if (!expr) return NULL; expr->keysym.keysym = keysym; return expr; } ExprDef * ExprCreateIdent(xkb_atom_t ident) { ExprDef *expr = ExprCreate(STMT_EXPR_IDENT); if (!expr) return NULL; expr->ident.ident = ident; return expr; } ExprDef * ExprCreateUnary(enum stmt_type op, ExprDef *child) { ExprDef *expr = ExprCreate(op); if (!expr) return NULL; expr->unary.child = child; return expr; } ExprDef * ExprCreateBinary(enum stmt_type op, ExprDef *left, ExprDef *right) { ExprDef *expr = ExprCreate(op); if (!expr) return NULL; expr->binary.left = left; expr->binary.right = right; return expr; } ExprDef * ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field) { ExprDef *expr = ExprCreate(STMT_EXPR_FIELD_REF); if (!expr) return NULL; expr->field_ref.element = element; expr->field_ref.field = field; return expr; } ExprDef * ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry) { ExprDef *expr = ExprCreate(STMT_EXPR_ARRAY_REF); if (!expr) return NULL; expr->array_ref.element = element; expr->array_ref.field = field; expr->array_ref.entry = entry; return expr; } ExprDef * ExprEmptyList(void) { return ExprCreate(STMT_EXPR_EMPTY_LIST); } ExprDef * ExprCreateAction(xkb_atom_t name, ExprDef *args) { ExprDef *expr = ExprCreate(STMT_EXPR_ACTION_DECL); if (!expr) return NULL; expr->action.name = name; expr->action.args = args; return expr; } ExprDef * ExprCreateActionList(ExprDef *actions) { ExprDef *expr = ExprCreate(STMT_EXPR_ACTION_LIST); if (!expr) return NULL; expr->actions.actions = actions; return expr; } ExprDef * ExprCreateKeySymList(xkb_keysym_t sym) { ExprDef *expr = ExprCreate(STMT_EXPR_KEYSYM_LIST); if (!expr) return NULL; darray_init(expr->keysym_list.syms); if (sym == XKB_KEY_NoSymbol) { /* Discard NoSymbol */ } else { darray_append(expr->keysym_list.syms, sym); } return expr; } ExprDef * ExprAppendKeySymList(ExprDef *expr, xkb_keysym_t sym) { if (sym == XKB_KEY_NoSymbol) { /* Discard NoSymbol */ } else { darray_append(expr->keysym_list.syms, sym); } return expr; } ExprDef * ExprKeySymListAppendString(struct scanner *scanner, ExprDef *expr, const char *string) { /* TODO: use strnlen with max len = 4 * MAX_KEYSYMS_LIST_LENGTH */ const size_t len = strlen(string); size_t idx = 0; size_t idx_cp = 1; while (idx < len) { size_t count = 0; uint32_t cp = utf8_next_code_point(string + idx, len - idx, &count); if (cp == INVALID_UTF8_CODE_POINT) { scanner_err(scanner, XKB_ERROR_INVALID_FILE_ENCODING, "Cannot convert string to keysyms: " "Invalid UTF-8 encoding starting at byte position %zu " "(code point position: %zu).", idx + 1, idx_cp); goto error; } const xkb_keysym_t sym = xkb_utf32_to_keysym(cp); if (sym == XKB_KEY_NoSymbol) { scanner_err(scanner, XKB_LOG_MESSAGE_NO_ID, "Cannot convert string to keysyms: Unicode code point " "U+04%"PRIX32" has no keysym equivalent" "(byte position: %zu, code point position: %zu).", cp, idx + 1, idx_cp); goto error; } darray_append(expr->keysym_list.syms, sym); idx += count; idx_cp++; } assert(string[idx] == '\0'); return expr; error: FreeStmt((ParseCommon*) expr); return NULL; } xkb_keysym_t KeysymParseString(struct scanner *scanner, const char *string) { const size_t len = strlen(string); if (len == 0) { scanner_err(scanner, XKB_LOG_MESSAGE_NO_ID, "Cannot convert string to single keysym: empty string."); return XKB_KEY_NoSymbol; } size_t count = 0; const uint32_t cp = utf8_next_code_point(string, len, &count); if (cp == INVALID_UTF8_CODE_POINT) { scanner_err(scanner, XKB_ERROR_INVALID_FILE_ENCODING, "Cannot convert string to single keysym: " "Invalid UTF-8 encoding."); return XKB_KEY_NoSymbol; } else if (count != len) { scanner_err(scanner, XKB_ERROR_INVALID_FILE_ENCODING, "Cannot convert string to single keysym: " "Expected a single Unicode code point, got: \"%s\".", string); return XKB_KEY_NoSymbol; } const xkb_keysym_t sym = xkb_utf32_to_keysym(cp); if (sym == XKB_KEY_NoSymbol) { scanner_err(scanner, XKB_LOG_MESSAGE_NO_ID, "Cannot convert string to single keysym: Unicode " "code point U+%04"PRIX32" has no keysym equivalent.", cp); } return sym; } KeycodeDef * KeycodeCreate(xkb_atom_t name, int64_t value) { KeycodeDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_KEYCODE; def->common.next = NULL; def->name = name; def->value = value; return def; } KeyAliasDef * KeyAliasCreate(xkb_atom_t alias, xkb_atom_t real) { KeyAliasDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_ALIAS; def->common.next = NULL; def->alias = alias; def->real = real; return def; } VModDef * VModCreate(xkb_atom_t name, ExprDef *value) { VModDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_VMOD; def->common.next = NULL; def->name = name; def->value = value; return def; } VarDef * VarCreate(ExprDef *name, ExprDef *value) { VarDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_VAR; def->common.next = NULL; def->name = name; def->value = value; return def; } VarDef * BoolVarCreate(xkb_atom_t ident, bool set) { ExprDef *name, *value; VarDef *def; if (!(name = ExprCreateIdent(ident))) { return NULL; } if (!(value = ExprCreateBoolean(set))) { FreeStmt((ParseCommon *) name); return NULL; } if (!(def = VarCreate(name, value))) { FreeStmt((ParseCommon *) name); FreeStmt((ParseCommon *) value); return NULL; } return def; } InterpDef * InterpCreate(xkb_keysym_t sym, ExprDef *match) { InterpDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_INTERP; def->common.next = NULL; def->sym = sym; def->match = match; def->def = NULL; return def; } KeyTypeDef * KeyTypeCreate(xkb_atom_t name, VarDef *body) { KeyTypeDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_TYPE; def->common.next = NULL; def->merge = MERGE_DEFAULT; def->name = name; def->body = body; return def; } SymbolsDef * SymbolsCreate(xkb_atom_t keyName, VarDef *symbols) { SymbolsDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_SYMBOLS; def->common.next = NULL; def->merge = MERGE_DEFAULT; def->keyName = keyName; def->symbols = symbols; return def; } GroupCompatDef * GroupCompatCreate(int64_t group, ExprDef *val) { GroupCompatDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_GROUP_COMPAT; def->common.next = NULL; def->merge = MERGE_DEFAULT; def->group = group; def->def = val; return def; } ModMapDef * ModMapCreate(xkb_atom_t modifier, ExprDef *keys) { ModMapDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_MODMAP; def->common.next = NULL; def->merge = MERGE_DEFAULT; def->modifier = modifier; def->keys = keys; return def; } LedMapDef * LedMapCreate(xkb_atom_t name, VarDef *body) { LedMapDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_LED_MAP; def->common.next = NULL; def->merge = MERGE_DEFAULT; def->name = name; def->body = body; return def; } LedNameDef * LedNameCreate(int64_t ndx, ExprDef *name, bool virtual) { LedNameDef *def = malloc(sizeof(*def)); if (!def) return NULL; def->common.type = STMT_LED_NAME; def->common.next = NULL; def->merge = MERGE_DEFAULT; def->ndx = ndx; def->name = name; def->virtual = virtual; return def; } static void FreeInclude(IncludeStmt *incl); IncludeStmt * IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge) { IncludeStmt *incl, *first; char *stmt, *tmp; char nextop; incl = first = NULL; tmp = str; stmt = strdup_safe(str); while (tmp && *tmp) { char *file = NULL, *map = NULL, *extra_data = NULL; if (!ParseIncludeMap(&tmp, &file, &map, &nextop, &extra_data)) goto err; /* * Given an RMLVO (here layout) like 'us,,fr', the rules parser * will give out something like 'pc+us+:2+fr:3+inet(evdev)'. * We should just skip the ':2' in this case and leave it to the * appropriate section to deal with the empty group. */ if (isempty(file)) { free(file); free(map); free(extra_data); continue; } if (first == NULL) { first = incl = malloc(sizeof(*first)); } else { incl->next_incl = malloc(sizeof(*first)); incl = incl->next_incl; } if (!incl) { free(file); free(map); free(extra_data); break; } incl->common.type = STMT_INCLUDE; incl->common.next = NULL; incl->merge = merge; incl->stmt = NULL; incl->file = file; incl->map = map; incl->modifier = extra_data; incl->next_incl = NULL; switch (nextop) { case MERGE_AUGMENT_PREFIX: merge = MERGE_AUGMENT; break; case MERGE_REPLACE_PREFIX: merge = MERGE_REPLACE; break; default: merge = MERGE_OVERRIDE; } } if (first) first->stmt = stmt; else free(stmt); return first; err: log_err(ctx, XKB_ERROR_INVALID_INCLUDE_STATEMENT, "Illegal include statement \"%s\"; Ignored\n", stmt); FreeInclude(first); free(stmt); return NULL; } XkbFile * XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs, enum xkb_map_flags flags) { XkbFile *file; file = calloc(1, sizeof(*file)); if (!file) return NULL; XkbEscapeMapName(name); file->file_type = type; file->name = name; file->defs = defs; file->flags = flags; return file; } XkbFile * XkbFileFromComponents(struct xkb_context *ctx, const struct xkb_component_names *kkctgs) { char *const components[] = { kkctgs->keycodes, kkctgs->types, kkctgs->compatibility, kkctgs->symbols, }; enum xkb_file_type type; IncludeStmt *include = NULL; XkbFile *file = NULL; ParseCommon *defs = NULL, *defsLast = NULL; for (type = FIRST_KEYMAP_FILE_TYPE; type <= LAST_KEYMAP_FILE_TYPE; type++) { include = IncludeCreate(ctx, components[type], MERGE_DEFAULT); if (!include) goto err; file = XkbFileCreate(type, NULL, (ParseCommon *) include, 0); if (!file) { FreeInclude(include); goto err; } if (!defs) defsLast = defs = &file->common; else defsLast = defsLast->next = &file->common; } file = XkbFileCreate(FILE_TYPE_KEYMAP, NULL, defs, 0); if (!file) goto err; return file; err: FreeXkbFile((XkbFile *) defs); return NULL; } static void FreeInclude(IncludeStmt *incl) { IncludeStmt *next; while (incl) { next = incl->next_incl; free(incl->file); free(incl->map); free(incl->modifier); free(incl->stmt); free(incl); incl = next; } } void FreeStmt(ParseCommon *stmt) { ParseCommon *next; while (stmt) { next = stmt->next; switch (stmt->type) { case STMT_INCLUDE: FreeInclude((IncludeStmt *) stmt); /* stmt is already free'd here. */ stmt = NULL; break; case STMT_EXPR_NEGATE: case STMT_EXPR_UNARY_PLUS: case STMT_EXPR_NOT: case STMT_EXPR_INVERT: FreeStmt((ParseCommon *) ((ExprUnary *) stmt)->child); break; case STMT_EXPR_DIVIDE: case STMT_EXPR_ADD: case STMT_EXPR_SUBTRACT: case STMT_EXPR_MULTIPLY: case STMT_EXPR_ASSIGN: FreeStmt((ParseCommon *) ((ExprBinary *) stmt)->left); FreeStmt((ParseCommon *) ((ExprBinary *) stmt)->right); break; case STMT_EXPR_ACTION_DECL: FreeStmt((ParseCommon *) ((ExprAction *) stmt)->args); break; case STMT_EXPR_ACTION_LIST: FreeStmt((ParseCommon *) ((ExprActionList *) stmt)->actions); break; case STMT_EXPR_ARRAY_REF: FreeStmt((ParseCommon *) ((ExprArrayRef *) stmt)->entry); break; case STMT_EXPR_KEYSYM_LIST: darray_free(((ExprKeysymList *) stmt)->syms); break; case STMT_VAR: FreeStmt((ParseCommon *) ((VarDef *) stmt)->name); FreeStmt((ParseCommon *) ((VarDef *) stmt)->value); break; case STMT_TYPE: FreeStmt((ParseCommon *) ((KeyTypeDef *) stmt)->body); break; case STMT_INTERP: FreeStmt((ParseCommon *) ((InterpDef *) stmt)->match); FreeStmt((ParseCommon *) ((InterpDef *) stmt)->def); break; case STMT_VMOD: FreeStmt((ParseCommon *) ((VModDef *) stmt)->value); break; case STMT_SYMBOLS: FreeStmt((ParseCommon *) ((SymbolsDef *) stmt)->symbols); break; case STMT_MODMAP: FreeStmt((ParseCommon *) ((ModMapDef *) stmt)->keys); break; case STMT_GROUP_COMPAT: FreeStmt((ParseCommon *) ((GroupCompatDef *) stmt)->def); break; case STMT_LED_MAP: FreeStmt((ParseCommon *) ((LedMapDef *) stmt)->body); break; case STMT_LED_NAME: FreeStmt((ParseCommon *) ((LedNameDef *) stmt)->name); break; default: break; } free(stmt); stmt = next; } } void FreeXkbFile(XkbFile *file) { XkbFile *next; while (file) { next = (XkbFile *) file->common.next; switch (file->file_type) { case FILE_TYPE_KEYMAP: FreeXkbFile((XkbFile *) file->defs); break; case FILE_TYPE_TYPES: case FILE_TYPE_COMPAT: case FILE_TYPE_SYMBOLS: case FILE_TYPE_KEYCODES: case FILE_TYPE_GEOMETRY: FreeStmt(file->defs); break; default: break; } free(file->name); free(file); file = next; } } static const char *xkb_file_type_strings[_FILE_TYPE_NUM_ENTRIES] = { [FILE_TYPE_KEYCODES] = "xkb_keycodes", [FILE_TYPE_TYPES] = "xkb_types", [FILE_TYPE_COMPAT] = "xkb_compatibility", [FILE_TYPE_SYMBOLS] = "xkb_symbols", [FILE_TYPE_GEOMETRY] = "xkb_geometry", [FILE_TYPE_KEYMAP] = "xkb_keymap", [FILE_TYPE_RULES] = "rules", }; const char * xkb_file_type_to_string(enum xkb_file_type type) { if (type >= _FILE_TYPE_NUM_ENTRIES) return "unknown"; return xkb_file_type_strings[type]; } static const char *stmt_type_strings[_STMT_NUM_VALUES] = { [STMT_UNKNOWN] = "unknown statement", [STMT_INCLUDE] = "include statement", [STMT_KEYCODE] = "key name definition", [STMT_ALIAS] = "key alias definition", [STMT_EXPR_STRING_LITERAL] = "string literal expression", [STMT_EXPR_INTEGER_LITERAL] = "integer literal expression", [STMT_EXPR_FLOAT_LITERAL] = "float literal expression", [STMT_EXPR_BOOLEAN_LITERAL] = "boolean literal expression", [STMT_EXPR_KEYNAME_LITERAL] = "key name expression", [STMT_EXPR_KEYSYM_LITERAL] = "keysym expression", [STMT_EXPR_IDENT] = "identifier expression", [STMT_EXPR_ACTION_DECL] = "action declaration expression", [STMT_EXPR_FIELD_REF] = "field reference expression", [STMT_EXPR_ARRAY_REF] = "array reference expression", [STMT_EXPR_EMPTY_LIST] = "empty list expression", [STMT_EXPR_KEYSYM_LIST] = "keysym list expression", [STMT_EXPR_ACTION_LIST] = "action list expression", [STMT_EXPR_ADD] = "addition expression", [STMT_EXPR_SUBTRACT] = "substraction expression", [STMT_EXPR_MULTIPLY] = "multiplication expression", [STMT_EXPR_DIVIDE] = "division expression", [STMT_EXPR_ASSIGN] = "assignment expression", [STMT_EXPR_NOT] = "logical negation expression", [STMT_EXPR_NEGATE] = "arithmetic negation expression", [STMT_EXPR_INVERT] = "bitwise inversion expression", [STMT_EXPR_UNARY_PLUS] = "unary plus expression", [STMT_VAR] = "variable definition", [STMT_TYPE] = "key type definition", [STMT_INTERP] = "symbol interpretation definition", [STMT_VMOD] = "virtual modifiers definition", [STMT_SYMBOLS] = "key symbols definition", [STMT_MODMAP] = "modifier map declaration", [STMT_GROUP_COMPAT] = "group declaration", [STMT_LED_MAP] = "indicator map declaration", [STMT_LED_NAME] = "indicator name declaration", }; const char * stmt_type_to_string(enum stmt_type type) { if (type >= _STMT_NUM_VALUES) return NULL; return stmt_type_strings[type]; } char stmt_type_to_operator_char(enum stmt_type type) { switch (type) { case STMT_EXPR_ADD: return '+'; case STMT_EXPR_SUBTRACT: return '-'; case STMT_EXPR_MULTIPLY: return '*'; case STMT_EXPR_DIVIDE: return '/'; case STMT_EXPR_NOT: return '!'; case STMT_EXPR_NEGATE: return '-'; case STMT_EXPR_INVERT: return '~'; case STMT_EXPR_UNARY_PLUS: return '+'; default: return '\0'; } } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/ast-build.h000066400000000000000000000042701510033435100231550ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #pragma once #include "config.h" #include "ast.h" #include "scanner-utils.h" ExprDef * ExprCreateString(xkb_atom_t str); ExprDef * ExprCreateInteger(int64_t ival); ExprDef * ExprCreateFloat(void); ExprDef * ExprCreateBoolean(bool set); ExprDef * ExprCreateKeyName(xkb_atom_t key_name); ExprDef * ExprCreateKeySym(xkb_keysym_t keysym); ExprDef * ExprCreateIdent(xkb_atom_t ident); ExprDef * ExprCreateUnary(enum stmt_type op, ExprDef *child); ExprDef * ExprCreateBinary(enum stmt_type op, ExprDef *left, ExprDef *right); ExprDef * ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field); ExprDef * ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry); ExprDef * ExprEmptyList(void); ExprDef * ExprCreateAction(xkb_atom_t name, ExprDef *args); ExprDef * ExprCreateActionList(ExprDef *actions); ExprDef * ExprCreateKeySymList(xkb_keysym_t sym); ExprDef * ExprAppendKeySymList(ExprDef *list, xkb_keysym_t sym); ExprDef * ExprKeySymListAppendString(struct scanner *param, ExprDef *expr, const char *string); xkb_keysym_t KeysymParseString(struct scanner *scanner, const char *string); KeycodeDef * KeycodeCreate(xkb_atom_t name, int64_t value); KeyAliasDef * KeyAliasCreate(xkb_atom_t alias, xkb_atom_t real); VModDef * VModCreate(xkb_atom_t name, ExprDef *value); VarDef * VarCreate(ExprDef *name, ExprDef *value); VarDef * BoolVarCreate(xkb_atom_t ident, bool set); InterpDef * InterpCreate(xkb_keysym_t sym, ExprDef *match); KeyTypeDef * KeyTypeCreate(xkb_atom_t name, VarDef *body); SymbolsDef * SymbolsCreate(xkb_atom_t keyName, VarDef *symbols); GroupCompatDef * GroupCompatCreate(int64_t group, ExprDef *def); ModMapDef * ModMapCreate(xkb_atom_t modifier, ExprDef *keys); LedMapDef * LedMapCreate(xkb_atom_t name, VarDef *body); LedNameDef * LedNameCreate(int64_t ndx, ExprDef *name, bool virtual); IncludeStmt * IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge); XkbFile * XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs, enum xkb_map_flags flags); void FreeStmt(ParseCommon *stmt); xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/ast.h000066400000000000000000000142311510033435100220560ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT */ #pragma once #include "config.h" #include "xkbcommon/xkbcommon.h" #include "atom.h" #include "darray.h" enum xkb_file_type { /* Component files, by order of compilation. */ FILE_TYPE_KEYCODES = 0, FILE_TYPE_TYPES = 1, FILE_TYPE_COMPAT = 2, FILE_TYPE_SYMBOLS = 3, /* File types which must be found in a keymap file. */ FIRST_KEYMAP_FILE_TYPE = FILE_TYPE_KEYCODES, LAST_KEYMAP_FILE_TYPE = FILE_TYPE_SYMBOLS, /* Geometry is not compiled any more. */ FILE_TYPE_GEOMETRY = 4, /* A top level file which includes the above files. */ FILE_TYPE_KEYMAP, /* This one doesn't mix with the others, but useful here as well. */ FILE_TYPE_RULES, _FILE_TYPE_NUM_ENTRIES, FILE_TYPE_INVALID = _FILE_TYPE_NUM_ENTRIES }; enum stmt_type { STMT_UNKNOWN = 0, STMT_INCLUDE, STMT_KEYCODE, STMT_ALIAS, STMT_EXPR_STRING_LITERAL, STMT_EXPR_INTEGER_LITERAL, STMT_EXPR_FLOAT_LITERAL, STMT_EXPR_BOOLEAN_LITERAL, STMT_EXPR_KEYNAME_LITERAL, STMT_EXPR_KEYSYM_LITERAL, STMT_EXPR_IDENT, STMT_EXPR_ACTION_DECL, STMT_EXPR_FIELD_REF, STMT_EXPR_ARRAY_REF, /* Needed because of the ambiguity between keysym and action empty lists */ STMT_EXPR_EMPTY_LIST, STMT_EXPR_KEYSYM_LIST, STMT_EXPR_ACTION_LIST, STMT_EXPR_ADD, STMT_EXPR_SUBTRACT, STMT_EXPR_MULTIPLY, STMT_EXPR_DIVIDE, STMT_EXPR_ASSIGN, STMT_EXPR_NOT, STMT_EXPR_NEGATE, STMT_EXPR_INVERT, STMT_EXPR_UNARY_PLUS, STMT_VAR, STMT_TYPE, STMT_INTERP, STMT_VMOD, STMT_SYMBOLS, STMT_MODMAP, STMT_GROUP_COMPAT, STMT_LED_MAP, STMT_LED_NAME, _STMT_NUM_VALUES }; enum merge_mode { MERGE_DEFAULT, MERGE_AUGMENT, MERGE_OVERRIDE, MERGE_REPLACE, _MERGE_MODE_NUM_ENTRIES, }; const char * xkb_file_type_to_string(enum xkb_file_type type); const char * stmt_type_to_string(enum stmt_type type); char stmt_type_to_operator_char(enum stmt_type type); typedef struct _ParseCommon { struct _ParseCommon *next; enum stmt_type type; } ParseCommon; typedef struct _IncludeStmt { ParseCommon common; enum merge_mode merge; char *stmt; char *file; char *map; char *modifier; struct _IncludeStmt *next_incl; } IncludeStmt; typedef union ExprDef ExprDef; typedef struct { ParseCommon common; xkb_atom_t ident; } ExprIdent; typedef struct { ParseCommon common; xkb_atom_t str; } ExprString; typedef struct { ParseCommon common; bool set; } ExprBoolean; typedef struct { ParseCommon common; int64_t ival; } ExprInteger; typedef struct { ParseCommon common; /* We don't support floats, but we still represnt them in the AST, in * order to provide proper error messages. */ } ExprFloat; typedef struct { ParseCommon common; xkb_atom_t key_name; } ExprKeyName; typedef struct { ParseCommon common; /* Keysyms are resolved early, so this might contain `NoSymbol` in case of * failure, to enable error recovery. */ xkb_keysym_t keysym; } ExprKeySym; typedef struct { ParseCommon common; ExprDef *left; ExprDef *right; } ExprBinary; typedef struct { ParseCommon common; ExprDef *child; } ExprUnary; typedef struct { ParseCommon common; xkb_atom_t element; xkb_atom_t field; } ExprFieldRef; typedef struct { ParseCommon common; xkb_atom_t element; xkb_atom_t field; ExprDef *entry; } ExprArrayRef; typedef struct { ParseCommon common; xkb_atom_t name; ExprDef *args; } ExprAction; typedef struct { ParseCommon common; /* List of actions for a single level. */ ExprDef *actions; } ExprActionList; typedef struct { ParseCommon common; /* List of keysym for a single level. */ darray(xkb_keysym_t) syms; } ExprKeysymList; union ExprDef { ParseCommon common; ExprIdent ident; ExprString string; ExprBoolean boolean; ExprInteger integer; ExprKeyName key_name; ExprKeySym keysym; ExprBinary binary; ExprUnary unary; ExprFieldRef field_ref; ExprArrayRef array_ref; ExprAction action; ExprActionList actions; ExprKeysymList keysym_list; }; typedef struct { ParseCommon common; enum merge_mode merge; ExprDef *name; ExprDef *value; } VarDef; typedef struct { ParseCommon common; enum merge_mode merge; xkb_atom_t name; ExprDef *value; } VModDef; typedef struct { ParseCommon common; enum merge_mode merge; xkb_atom_t name; int64_t value; } KeycodeDef; typedef struct { ParseCommon common; enum merge_mode merge; xkb_atom_t alias; xkb_atom_t real; } KeyAliasDef; typedef struct { ParseCommon common; enum merge_mode merge; xkb_atom_t name; VarDef *body; } KeyTypeDef; typedef struct { ParseCommon common; enum merge_mode merge; xkb_atom_t keyName; VarDef *symbols; } SymbolsDef; typedef struct { ParseCommon common; enum merge_mode merge; // NOTE: Can also be “None”, rather than a modifier name. xkb_atom_t modifier; ExprDef *keys; } ModMapDef; typedef struct { ParseCommon common; enum merge_mode merge; int64_t group; ExprDef *def; } GroupCompatDef; typedef struct { ParseCommon common; enum merge_mode merge; xkb_keysym_t sym; ExprDef *match; VarDef *def; } InterpDef; typedef struct { ParseCommon common; enum merge_mode merge; int64_t ndx; ExprDef *name; bool virtual; } LedNameDef; typedef struct { ParseCommon common; enum merge_mode merge; xkb_atom_t name; VarDef *body; } LedMapDef; enum xkb_map_flags { MAP_IS_DEFAULT = (1 << 0), MAP_IS_PARTIAL = (1 << 1), MAP_IS_HIDDEN = (1 << 2), MAP_HAS_ALPHANUMERIC = (1 << 3), MAP_HAS_MODIFIER = (1 << 4), MAP_HAS_KEYPAD = (1 << 5), MAP_HAS_FN = (1 << 6), MAP_IS_ALTGR = (1 << 7), }; typedef struct { ParseCommon common; enum xkb_file_type file_type; char *name; ParseCommon *defs; enum xkb_map_flags flags; } XkbFile; xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/compat.c000066400000000000000000000762741510033435100225640ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "darray.h" #include "keymap.h" #include "xkbcomp-priv.h" #include "ast.h" #include "action.h" #include "expr.h" #include "include.h" #include "text.h" #include "vmod.h" #include "util-mem.h" enum si_field { SI_FIELD_VIRTUAL_MOD = (1 << 0), SI_FIELD_ACTION = (1 << 1), SI_FIELD_AUTO_REPEAT = (1 << 2), SI_FIELD_LEVEL_ONE_ONLY = (1 << 3), }; typedef struct { enum si_field defined; enum merge_mode merge; struct xkb_sym_interpret interp; } SymInterpInfo; enum led_field { LED_FIELD_MODS = (1 << 0), LED_FIELD_GROUPS = (1 << 1), LED_FIELD_CTRLS = (1 << 2), }; typedef struct { enum led_field defined; enum merge_mode merge; struct xkb_led led; } LedInfo; typedef struct { char *name; int errorCount; unsigned int include_depth; SymInterpInfo default_interp; darray(SymInterpInfo) interps; LedInfo default_led; LedInfo leds[XKB_MAX_LEDS]; xkb_led_index_t num_leds; ActionsInfo default_actions; struct xkb_mod_set mods; enum xkb_keymap_format format; struct xkb_context *ctx; } CompatInfo; static const char * siText(SymInterpInfo *si, CompatInfo *info) { char *buf = xkb_context_get_buffer(info->ctx, 128); if (si == &info->default_interp) return "default"; snprintf(buf, 128, "%s+%s(%s)", KeysymText(info->ctx, si->interp.sym), SIMatchText(si->interp.match), ModMaskText(info->ctx, MOD_BOTH, &info->mods, si->interp.mods)); return buf; } static inline bool ReportSINotArray(CompatInfo *info, SymInterpInfo *si, const char *field) { return ReportNotArray(info->ctx, "symbol interpretation", field, siText(si, info)); } static inline bool ReportSIBadType(CompatInfo *info, SymInterpInfo *si, const char *field, const char *wanted) { return ReportBadType(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE, "symbol interpretation", field, siText(si, info), wanted); } static const char* LEDText(CompatInfo *info, LedInfo *ledi) { if (ledi == &info->default_led) { assert(xkb_atom_text(info->ctx, ledi->led.name) == NULL); return "default"; } else { assert(xkb_atom_text(info->ctx, ledi->led.name) != NULL); return xkb_atom_text(info->ctx, ledi->led.name); } } static inline bool ReportLedBadType(CompatInfo *info, LedInfo *ledi, const char *field, const char *wanted) { return ReportBadType(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE, "indicator map", field, LEDText(info, ledi), wanted); } static inline bool ReportLedNotArray(CompatInfo *info, LedInfo *ledi, const char *field) { return ReportNotArray(info->ctx, "indicator map", field, LEDText(info, ledi)); } static inline void InitInterp(SymInterpInfo *info) { info->merge = MERGE_DEFAULT; /* Unused */ info->interp.virtual_mod = XKB_MOD_INVALID; } static inline void InitLED(LedInfo *info) { info->merge = MERGE_DEFAULT; /* Unused */ } static void InitCompatInfo(CompatInfo *info, struct xkb_context *ctx, unsigned int include_depth, enum xkb_keymap_format format, const struct xkb_mod_set *mods) { memset(info, 0, sizeof(*info)); info->ctx = ctx; info->format = format; info->include_depth = include_depth; InitActionsInfo(&info->default_actions); InitVMods(&info->mods, mods, include_depth > 0); InitInterp(&info->default_interp); InitLED(&info->default_led); } static void ClearCompatInfo(CompatInfo *info) { free(info->name); darray_free(info->interps); } static SymInterpInfo * FindMatchingInterp(CompatInfo *info, SymInterpInfo *new) { SymInterpInfo *old; darray_foreach(old, info->interps) if (old->interp.sym == new->interp.sym && old->interp.mods == new->interp.mods && old->interp.match == new->interp.match) return old; return NULL; } static bool UseNewInterpField(enum si_field field, enum si_field old, enum si_field new, bool clobber, bool report, enum si_field *collide) { if (!(old & field)) return (new & field); if (new & field) { if (report) *collide |= field; return clobber; } return false; } static bool MergeInterp(CompatInfo *info, SymInterpInfo *old, SymInterpInfo *new, bool same_file) { const bool clobber = (new->merge != MERGE_AUGMENT); const int verbosity = xkb_context_get_log_verbosity(info->ctx); const bool report = (same_file && verbosity > 0) || verbosity > 9; enum si_field collide = 0; if (new->merge == MERGE_REPLACE) { if (report) log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple definitions for \"%s\"; " "Earlier interpretation ignored\n", siText(new, info)); *old = *new; return true; } if (UseNewInterpField(SI_FIELD_VIRTUAL_MOD, old->defined, new->defined, clobber, report, &collide)) { old->interp.virtual_mod = new->interp.virtual_mod; old->defined |= SI_FIELD_VIRTUAL_MOD; } if (UseNewInterpField(SI_FIELD_ACTION, old->defined, new->defined, clobber, report, &collide)) { if (old->interp.num_actions > 1) { free(old->interp.a.actions); } old->interp.num_actions = new->interp.num_actions; if (new->interp.num_actions > 1) { old->interp.a.actions = new->interp.a.actions; new->interp.a.action = (union xkb_action) { .type = ACTION_TYPE_NONE }; new->interp.num_actions = 0; } else { old->interp.a.action = new->interp.a.action; } old->defined |= SI_FIELD_ACTION; } if (UseNewInterpField(SI_FIELD_AUTO_REPEAT, old->defined, new->defined, clobber, report, &collide)) { old->interp.repeat = new->interp.repeat; old->defined |= SI_FIELD_AUTO_REPEAT; } if (UseNewInterpField(SI_FIELD_LEVEL_ONE_ONLY, old->defined, new->defined, clobber, report, &collide)) { old->interp.level_one_only = new->interp.level_one_only; old->defined |= SI_FIELD_LEVEL_ONE_ONLY; } if (collide) { log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple interpretations of \"%s\"; " "Using %s definition for duplicate fields\n", siText(old, info), (clobber ? "last" : "first")); } return true; } static bool AddInterp(CompatInfo *info, SymInterpInfo *new, bool same_file) { SymInterpInfo *old = FindMatchingInterp(info, new); if (old) return MergeInterp(info, old, new, same_file); darray_append(info->interps, *new); return true; } /***====================================================================***/ static bool ResolveStateAndPredicate(ExprDef *expr, enum xkb_match_operation *pred_rtrn, xkb_mod_mask_t *mods_rtrn, CompatInfo *info) { if (expr == NULL) { *pred_rtrn = MATCH_ANY_OR_NONE; *mods_rtrn = MOD_REAL_MASK_ALL; return true; } *pred_rtrn = MATCH_EXACTLY; if (expr->common.type == STMT_EXPR_ACTION_DECL) { const char *pred_txt = xkb_atom_text(info->ctx, expr->action.name); unsigned int pred = 0; if (!LookupString(symInterpretMatchMaskNames, pred_txt, &pred) || !expr->action.args || expr->action.args->common.next) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Illegal modifier predicate \"%s\"; Ignored\n", pred_txt); return false; } *pred_rtrn = (enum xkb_match_operation) pred; expr = expr->action.args; } else if (expr->common.type == STMT_EXPR_IDENT) { const char *pred_txt = xkb_atom_text(info->ctx, expr->ident.ident); if (pred_txt && istreq(pred_txt, "any")) { *pred_rtrn = MATCH_ANY; *mods_rtrn = MOD_REAL_MASK_ALL; return true; } } return ExprResolveModMask(info->ctx, expr, MOD_REAL, &info->mods, mods_rtrn); } /***====================================================================***/ static bool UseNewLEDField(enum led_field field, enum led_field old, enum led_field new, bool clobber, bool report, enum led_field *collide) { if (!(old & field)) return (new & field); if (new & field) { if (report) *collide |= field; return clobber; } return false; } static bool MergeLedMap(CompatInfo *info, LedInfo *old, LedInfo *new, bool same_file) { enum led_field collide; const bool clobber = (new->merge != MERGE_AUGMENT); const int verbosity = xkb_context_get_log_verbosity(info->ctx); const bool report = (same_file && verbosity > 0) || verbosity > 9; if (old->led.mods.mods == new->led.mods.mods && old->led.groups == new->led.groups && old->led.ctrls == new->led.ctrls && old->led.which_mods == new->led.which_mods && old->led.which_groups == new->led.which_groups) { old->defined |= new->defined; return true; } if (new->merge == MERGE_REPLACE) { if (report) log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Map for indicator %s redefined; " "Earlier definition ignored\n", LEDText(info, old)); *old = *new; return true; } collide = 0; if (UseNewLEDField(LED_FIELD_MODS, old->defined, new->defined, clobber, report, &collide)) { old->led.which_mods = new->led.which_mods; old->led.mods = new->led.mods; old->defined |= LED_FIELD_MODS; } if (UseNewLEDField(LED_FIELD_GROUPS, old->defined, new->defined, clobber, report, &collide)) { old->led.which_groups = new->led.which_groups; old->led.groups = new->led.groups; old->defined |= LED_FIELD_GROUPS; } if (UseNewLEDField(LED_FIELD_CTRLS, old->defined, new->defined, clobber, report, &collide)) { old->led.ctrls = new->led.ctrls; old->defined |= LED_FIELD_CTRLS; } if (collide) { log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Map for indicator %s redefined; " "Using %s definition for duplicate fields\n", LEDText(info, old), (clobber ? "last" : "first")); } return true; } static bool AddLedMap(CompatInfo *info, LedInfo *new, bool same_file) { for (xkb_led_index_t i = 0; i < info->num_leds; i++) { LedInfo *old = &info->leds[i]; if (old->led.name != new->led.name) continue; return MergeLedMap(info, old, new, same_file); } if (info->num_leds >= XKB_MAX_LEDS) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Too many LEDs defined (maximum %u)\n", XKB_MAX_LEDS); return false; } info->leds[info->num_leds++] = *new; return true; } static void MergeIncludedCompatMaps(CompatInfo *into, CompatInfo *from, enum merge_mode merge) { if (from->errorCount > 0) { into->errorCount += from->errorCount; return; } MergeModSets(into->ctx, &into->mods, &from->mods, merge); if (into->name == NULL) { into->name = steal(&from->name); } if (darray_empty(into->interps)) { into->interps = from->interps; darray_init(from->interps); } else { SymInterpInfo *si; darray_foreach(si, from->interps) { si->merge = merge; if (!AddInterp(into, si, false)) into->errorCount++; } } if (into->num_leds == 0) { memcpy(into->leds, from->leds, sizeof(*from->leds) * from->num_leds); into->num_leds = from->num_leds; from->num_leds = 0; } else { for (xkb_led_index_t i = 0; i < from->num_leds; i++) { LedInfo *ledi = &from->leds[i]; ledi->merge = merge; if (!AddLedMap(into, ledi, false)) into->errorCount++; } } } static void HandleCompatMapFile(CompatInfo *info, XkbFile *file); static bool HandleIncludeCompatMap(CompatInfo *info, IncludeStmt *include) { CompatInfo included; if (ExceedsIncludeMaxDepth(info->ctx, info->include_depth)) { info->errorCount += 10; return false; } InitCompatInfo(&included, info->ctx, info->include_depth + 1, info->format, &info->mods); included.name = steal(&include->stmt); for (IncludeStmt *stmt = include; stmt; stmt = stmt->next_incl) { CompatInfo next_incl; XkbFile *file; char path[PATH_MAX]; file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_COMPAT, path, sizeof(path)); if (!file) { info->errorCount += 10; ClearCompatInfo(&included); return false; } InitCompatInfo(&next_incl, info->ctx, info->include_depth + 1, info->format, &included.mods); next_incl.default_interp = info->default_interp; next_incl.default_led = info->default_led; HandleCompatMapFile(&next_incl, file); MergeIncludedCompatMaps(&included, &next_incl, stmt->merge); ClearCompatInfo(&next_incl); FreeXkbFile(file); } MergeIncludedCompatMaps(info, &included, include->merge); ClearCompatInfo(&included); return (info->errorCount == 0); } static bool SetInterpField(CompatInfo *info, SymInterpInfo *si, const char *field, ExprDef *arrayNdx, ExprDef *value) { if (istreq(field, "action")) { if (arrayNdx) return ReportSINotArray(info, si, field); if (value->common.type == STMT_EXPR_ACTION_LIST) { unsigned int num_actions = 0; for (ExprDef *act = value->actions.actions; act; act = (ExprDef *) act->common.next) num_actions++; if (num_actions > MAX_ACTIONS_PER_LEVEL) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Interpret %s has too many actions; " "expected max %u, got: %u\n", siText(si, info), MAX_ACTIONS_PER_LEVEL, num_actions); return false; } si->interp.num_actions = 0; si->interp.a.action.type = ACTION_TYPE_NONE; /* Parse actions and add only defined actions */ darray(union xkb_action) actions = darray_new(); for (ExprDef *act = value->actions.actions; act; act = (ExprDef *) act->common.next) { union xkb_action toAct = { 0 }; if (!HandleActionDef(info->ctx, info->format, &info->default_actions, &info->mods, act, &toAct)) { darray_free(actions); return false; } if (toAct.type == ACTION_TYPE_NONE) { /* Drop action */ } else if (likely(num_actions == 1)) { /* Only one action: do not allocate */ si->interp.num_actions = 1; si->interp.a.action = toAct; } else { darray_append(actions, toAct); } } switch (darray_size(actions)) { case 0: /* No action or exactly one action: already processed */ assert(si->interp.num_actions <= 1); break; case 1: /* One action: some actions were dropped */ si->interp.num_actions = 1; si->interp.a.action = darray_item(actions, 1); darray_free(actions); break; default: /* Multiple actions; no NoAction() left */ darray_shrink(actions); si->interp.num_actions = (xkb_action_count_t) darray_size(actions); darray_steal(actions, &si->interp.a.actions, NULL); } } else if (HandleActionDef(info->ctx, info->format, &info->default_actions, &info->mods, value, &si->interp.a.action)) si->interp.num_actions = (si->interp.a.action.type != ACTION_TYPE_NONE); else return false; si->defined |= SI_FIELD_ACTION; } else if (istreq(field, "virtualmodifier") || istreq(field, "virtualmod")) { if (arrayNdx) return ReportSINotArray(info, si, field); xkb_mod_index_t ndx = 0; if (!ExprResolveMod(info->ctx, value, MOD_VIRT, &info->mods, &ndx)) return ReportSIBadType(info, si, field, "virtual modifier"); si->interp.virtual_mod = ndx; si->defined |= SI_FIELD_VIRTUAL_MOD; } else if (istreq(field, "repeat")) { bool set = false; if (arrayNdx) return ReportSINotArray(info, si, field); if (!ExprResolveBoolean(info->ctx, value, &set)) return ReportSIBadType(info, si, field, "boolean"); si->interp.repeat = set; si->defined |= SI_FIELD_AUTO_REPEAT; } else if (istreq(field, "locking")) { log_dbg(info->ctx, XKB_LOG_MESSAGE_NO_ID, "The \"locking\" field in symbol interpretation is unsupported; " "Ignored\n"); } else if (istreq(field, "usemodmap") || istreq(field, "usemodmapmods")) { uint32_t val = 0; if (arrayNdx) return ReportSINotArray(info, si, field); if (!ExprResolveEnum(info->ctx, value, &val, useModMapValueNames)) return ReportSIBadType(info, si, field, "level specification"); si->interp.level_one_only = val; si->defined |= SI_FIELD_LEVEL_ONE_ONLY; } else { return ReportBadField(info->ctx, "symbol interpretation", field, siText(si, info)); } return true; } static bool SetLedMapField(CompatInfo *info, LedInfo *ledi, const char *field, ExprDef *arrayNdx, ExprDef *value) { bool ok = true; if (istreq(field, "modifiers") || istreq(field, "mods")) { if (arrayNdx) return ReportLedNotArray(info, ledi, field); if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods, &ledi->led.mods.mods)) return ReportLedBadType(info, ledi, field, "modifier mask"); ledi->defined |= LED_FIELD_MODS; } else if (istreq(field, "groups")) { uint32_t mask = 0; if (arrayNdx) return ReportLedNotArray(info, ledi, field); const xkb_layout_index_t max_groups = format_max_groups(info->format); if (!ExprResolveGroupMask(info->ctx, max_groups, value, &mask)) return ReportLedBadType(info, ledi, field, "group mask"); ledi->led.groups = mask; ledi->defined |= LED_FIELD_GROUPS; } else if (istreq(field, "controls") || istreq(field, "ctrls")) { uint32_t mask = 0; if (arrayNdx) return ReportLedNotArray(info, ledi, field); if (!ExprResolveMask(info->ctx, value, &mask, ctrlMaskNames)) return ReportLedBadType(info, ledi, field, "controls mask"); ledi->led.ctrls = mask; ledi->defined |= LED_FIELD_CTRLS; } else if (istreq(field, "allowexplicit")) { log_dbg(info->ctx, XKB_LOG_MESSAGE_NO_ID, "The \"allowExplicit\" field in indicator statements is unsupported; " "Ignored\n"); } else if (istreq(field, "whichmodstate") || istreq(field, "whichmodifierstate")) { uint32_t mask = 0; if (arrayNdx) return ReportLedNotArray(info, ledi, field); if (!ExprResolveMask(info->ctx, value, &mask, modComponentMaskNames)) return ReportLedBadType(info, ledi, field, "mask of modifier state components"); ledi->led.which_mods = mask; } else if (istreq(field, "whichgroupstate")) { uint32_t mask = 0; if (arrayNdx) return ReportLedNotArray(info, ledi, field); if (!ExprResolveMask(info->ctx, value, &mask, groupComponentMaskNames)) return ReportLedBadType(info, ledi, field, "mask of group state components"); ledi->led.which_groups = mask; } else if (istreq(field, "driveskbd") || istreq(field, "driveskeyboard") || istreq(field, "leddriveskbd") || istreq(field, "leddriveskeyboard") || istreq(field, "indicatordriveskbd") || istreq(field, "indicatordriveskeyboard")) { log_dbg(info->ctx, XKB_LOG_MESSAGE_NO_ID, "The \"%s\" field in indicator statements is unsupported; " "Ignored\n", field); } else if (istreq(field, "index")) { /* Users should see this, it might cause unexpected behavior. */ log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "The \"index\" field in indicator statements is unsupported; " "Ignored\n"); } else { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Unknown field \"%s\" in map for %s indicator; " "Definition ignored\n", field, LEDText(info, ledi)); ok = false; } return ok; } static bool HandleGlobalVar(CompatInfo *info, VarDef *stmt) { const char *elem, *field; ExprDef *ndx; bool ret; if (!ExprResolveLhs(info->ctx, stmt->name, &elem, &field, &ndx)) ret = false; else if (elem && istreq(elem, "interpret")) { SymInterpInfo temp = {0}; InitInterp(&temp); /* Do not replace the whole interpret, only the current field */ temp.merge = (temp.merge == MERGE_REPLACE) ? MERGE_OVERRIDE : stmt->merge; ret = SetInterpField(info, &temp, field, ndx, stmt->value); MergeInterp(info, &info->default_interp, &temp, true); } else if (elem && istreq(elem, "indicator")) { LedInfo temp = {0}; InitLED(&temp); /* Do not replace the whole LED, only the current field */ temp.merge = (temp.merge == MERGE_REPLACE) ? MERGE_OVERRIDE : stmt->merge; ret = SetLedMapField(info, &temp, field, ndx, stmt->value); MergeLedMap(info, &info->default_led, &temp, true); } else if (elem) { ret = SetDefaultActionField(info->ctx, info->format, &info->default_actions, &info->mods, elem, field, ndx, stmt->value, stmt->merge); } else { log_err(info->ctx, XKB_ERROR_UNKNOWN_DEFAULT_FIELD, "Default defined for unknown field \"%s\"; Ignored\n", field); return false; } return ret; } static bool HandleInterpBody(CompatInfo *info, VarDef *def, SymInterpInfo *si) { bool ok = true; const char *elem, *field; ExprDef *arrayNdx; for (; def; def = (VarDef *) def->common.next) { ok = ExprResolveLhs(info->ctx, def->name, &elem, &field, &arrayNdx); if (!ok) continue; if (elem) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Cannot set a global default value for \"%s\" element from " "within an interpret statement; " "Move assignment to \"%s.%s\" to the global file scope\n", elem, elem, field); ok = false; continue; } ok = SetInterpField(info, si, field, arrayNdx, def->value); } return ok; } static bool HandleInterpDef(CompatInfo *info, InterpDef *def) { enum xkb_match_operation pred; xkb_mod_mask_t mods; SymInterpInfo si; if (!ResolveStateAndPredicate(def->match, &pred, &mods, info)) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Couldn't determine matching modifiers; " "Symbol interpretation ignored\n"); return false; } si = info->default_interp; si.merge = def->merge; si.interp.sym = def->sym; si.interp.match = pred; si.interp.mods = mods; if (!HandleInterpBody(info, def->def, &si)) { info->errorCount++; return false; } if (!AddInterp(info, &si, true)) { info->errorCount++; return false; } return true; } static bool HandleLedMapDef(CompatInfo *info, LedMapDef *def) { LedInfo ledi; VarDef *var; bool ok; ledi = info->default_led; ledi.merge = def->merge; ledi.led.name = def->name; ok = true; for (var = def->body; var != NULL; var = (VarDef *) var->common.next) { const char *elem, *field; ExprDef *arrayNdx; if (!ExprResolveLhs(info->ctx, var->name, &elem, &field, &arrayNdx)) { ok = false; continue; } if (elem) { log_err(info->ctx, XKB_ERROR_GLOBAL_DEFAULTS_WRONG_SCOPE, "Cannot set defaults for \"%s\" element in indicator map; " "Assignment to %s.%s ignored\n", elem, elem, field); ok = false; } else { ok = SetLedMapField(info, &ledi, field, arrayNdx, var->value) && ok; } } if (ok) return AddLedMap(info, &ledi, true); return false; } static void HandleCompatMapFile(CompatInfo *info, XkbFile *file) { bool ok; free(info->name); info->name = strdup_safe(file->name); for (ParseCommon *stmt = file->defs; stmt; stmt = stmt->next) { switch (stmt->type) { case STMT_INCLUDE: ok = HandleIncludeCompatMap(info, (IncludeStmt *) stmt); break; case STMT_INTERP: ok = HandleInterpDef(info, (InterpDef *) stmt); break; case STMT_GROUP_COMPAT: log_dbg(info->ctx, XKB_LOG_MESSAGE_NO_ID, "The \"group\" statement in compat is unsupported; " "Ignored\n"); ok = true; break; case STMT_LED_MAP: ok = HandleLedMapDef(info, (LedMapDef *) stmt); break; case STMT_VAR: ok = HandleGlobalVar(info, (VarDef *) stmt); break; case STMT_VMOD: ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt); break; default: log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Compat files may not include other types; " "Ignoring %s\n", stmt_type_to_string(stmt->type)); ok = false; break; } if (!ok) info->errorCount++; if (info->errorCount > 10) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Abandoning compatibility map \"%s\"\n", safe_map_name(file)); break; } } } /* Temporary struct for CopyInterps. */ struct collect { darray(struct xkb_sym_interpret) sym_interprets; }; static void CopyInterps(CompatInfo *info, bool needSymbol, enum xkb_match_operation pred, struct collect *collect) { SymInterpInfo *si; darray_foreach(si, info->interps) if (si->interp.match == pred && (si->interp.sym != XKB_KEY_NoSymbol) == needSymbol) darray_append(collect->sym_interprets, si->interp); } static void CopyLedMapDefsToKeymap(struct xkb_keymap *keymap, CompatInfo *info) { for (xkb_led_index_t idx = 0; idx < info->num_leds; idx++) { LedInfo *ledi = &info->leds[idx]; xkb_led_index_t i; struct xkb_led *led; /* * Find the LED with the given name, if it was already declared * in keycodes. */ xkb_leds_enumerate(i, led, keymap) if (led->name == ledi->led.name) break; /* Not previously declared; create it with next free index. */ if (i >= keymap->num_leds) { log_dbg(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Indicator name \"%s\" was not declared in the keycodes " "section; Adding new indicator\n", LEDText(info, ledi)); xkb_leds_enumerate(i, led, keymap) if (led->name == XKB_ATOM_NONE) break; if (i >= keymap->num_leds) { /* Not place to put it; ignore. */ if (i >= XKB_MAX_LEDS) { log_err(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Too many indicators (maximum is %u); " "Indicator name \"%s\" ignored\n", XKB_MAX_LEDS, LEDText(info, ledi)); continue; } /* Add a new LED. */ led = &keymap->leds[keymap->num_leds++]; } } *led = ledi->led; if (led->groups != 0 && led->which_groups == 0) led->which_groups = XKB_STATE_LAYOUT_EFFECTIVE; if (led->mods.mods != 0 && led->which_mods == 0) led->which_mods = XKB_STATE_MODS_EFFECTIVE; } } static bool CopyCompatToKeymap(struct xkb_keymap *keymap, CompatInfo *info) { keymap->compat_section_name = strdup_safe(info->name); XkbEscapeMapName(keymap->compat_section_name); keymap->mods = info->mods; if (!darray_empty(info->interps)) { struct collect collect; darray_init(collect.sym_interprets); /* Most specific to least specific. */ CopyInterps(info, true, MATCH_EXACTLY, &collect); CopyInterps(info, true, MATCH_ALL, &collect); CopyInterps(info, true, MATCH_NONE, &collect); CopyInterps(info, true, MATCH_ANY, &collect); CopyInterps(info, true, MATCH_ANY_OR_NONE, &collect); CopyInterps(info, false, MATCH_EXACTLY, &collect); CopyInterps(info, false, MATCH_ALL, &collect); CopyInterps(info, false, MATCH_NONE, &collect); CopyInterps(info, false, MATCH_ANY, &collect); CopyInterps(info, false, MATCH_ANY_OR_NONE, &collect); darray_steal(collect.sym_interprets, &keymap->sym_interprets, &keymap->num_sym_interprets); } CopyLedMapDefsToKeymap(keymap, info); return true; } bool CompileCompatMap(XkbFile *file, struct xkb_keymap *keymap) { CompatInfo info; InitCompatInfo(&info, keymap->ctx, 0, keymap->format, &keymap->mods); if (file != NULL) HandleCompatMapFile(&info, file); if (info.errorCount != 0) goto err_info; if (!CopyCompatToKeymap(keymap, &info)) goto err_info; ClearCompatInfo(&info); return true; err_info: ClearCompatInfo(&info); return false; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/expr.c000066400000000000000000000553441510033435100222520ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #include "config.h" #include #include "messages-codes.h" #include "xkbcomp-priv.h" #include "text.h" #include "expr.h" #include "keysym.h" #include "xkbcomp/ast.h" #include "utils.h" #include "utils-numbers.h" #include "utils-checked-arithmetic.h" typedef bool (*IdentLookupFunc)(struct xkb_context *ctx, const void *priv, xkb_atom_t field, uint32_t *val_rtrn); bool ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr, const char **elem_rtrn, const char **field_rtrn, ExprDef **index_rtrn) { switch (expr->common.type) { case STMT_EXPR_IDENT: *elem_rtrn = NULL; *field_rtrn = xkb_atom_text(ctx, expr->ident.ident); *index_rtrn = NULL; return (*field_rtrn != NULL); case STMT_EXPR_FIELD_REF: *elem_rtrn = xkb_atom_text(ctx, expr->field_ref.element); *field_rtrn = xkb_atom_text(ctx, expr->field_ref.field); *index_rtrn = NULL; return (*elem_rtrn != NULL && *field_rtrn != NULL); case STMT_EXPR_ARRAY_REF: *elem_rtrn = xkb_atom_text(ctx, expr->array_ref.element); *field_rtrn = xkb_atom_text(ctx, expr->array_ref.field); *index_rtrn = expr->array_ref.entry; if (expr->array_ref.element != XKB_ATOM_NONE && *elem_rtrn == NULL) return false; if (*field_rtrn == NULL) return false; return true; default: break; } log_wsgo(ctx, XKB_ERROR_INVALID_XKB_SYNTAX, "Unexpected operator %d in ResolveLhs\n", expr->common.type); return false; } static bool SimpleLookup(struct xkb_context *ctx, const void *priv, xkb_atom_t field, uint32_t *val_rtrn) { if (!priv || field == XKB_ATOM_NONE) return false; const char *str = xkb_atom_text(ctx, field); for (const LookupEntry *entry = priv; entry && entry->name; entry++) { if (istreq(str, entry->name)) { *val_rtrn = entry->value; return true; } } return false; } struct named_integer_pattern { const char *prefix; size_t prefix_length; uint32_t min; uint32_t max; const LookupEntry *entries; bool is_mask; enum xkb_message_code error_id; }; /* Parse a number expressed with the pattern `` */ static bool NamedIntegerPatternLookup(struct xkb_context *ctx, const void *priv, xkb_atom_t field, uint32_t *val_rtrn) { if (!priv || field == XKB_ATOM_NONE) return false; const char * const str = xkb_atom_text(ctx, field); const struct named_integer_pattern * const pattern = priv; const int count = (istrneq(str, pattern->prefix, pattern->prefix_length)) ? parse_dec_to_uint32_t(str + pattern->prefix_length, SIZE_MAX, val_rtrn) : 0; if (count > 0 && *(str + pattern->prefix_length + count) == '\0') { if (*val_rtrn < pattern->min || *val_rtrn > pattern->max) { log_err(ctx, pattern->error_id, "%s index %"PRIu32" is out of range (%"PRIu32"..%"PRIu32")\n", pattern->prefix, *val_rtrn, pattern->min, pattern->max); return false; } if (pattern->is_mask) { /* Compute mask (bit 0 = min index) */ assert(*val_rtrn - pattern->min < 32); *val_rtrn = UINT32_C(1) << (*val_rtrn - pattern->min); } return true; } else { return ( pattern->entries && SimpleLookup(ctx, pattern->entries, field, val_rtrn) ); } } /* Data passed in the *priv argument for LookupModMask. */ typedef struct { const struct xkb_mod_set *mods; enum mod_type mod_type; } LookupModMaskPriv; static bool LookupModMask(struct xkb_context *ctx, const void *priv, xkb_atom_t field, xkb_mod_mask_t *val_rtrn) { const char *str = xkb_atom_text(ctx, field); if (!str) return false; if (istreq(str, "all")) { *val_rtrn = MOD_REAL_MASK_ALL; return true; } if (istreq(str, "none")) { *val_rtrn = 0; return true; } const LookupModMaskPriv *arg = priv; const struct xkb_mod_set *mods = arg->mods; const enum mod_type mod_type = arg->mod_type; const xkb_mod_index_t ndx = XkbModNameToIndex(mods, field, mod_type); if (ndx == XKB_MOD_INVALID) return false; *val_rtrn = (UINT32_C(1) << ndx); return true; } bool ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, bool *set_rtrn) { bool ok = false; const char *ident; switch (expr->common.type) { case STMT_EXPR_BOOLEAN_LITERAL: *set_rtrn = expr->boolean.set; return true; case STMT_EXPR_STRING_LITERAL: case STMT_EXPR_INTEGER_LITERAL: case STMT_EXPR_FLOAT_LITERAL: case STMT_EXPR_KEYNAME_LITERAL: case STMT_EXPR_KEYSYM_LITERAL: log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Found %s where boolean was expected\n", stmt_type_to_string(expr->common.type)); return false; case STMT_EXPR_IDENT: ident = xkb_atom_text(ctx, expr->ident.ident); if (ident) { if (istreq(ident, "true") || istreq(ident, "yes") || istreq(ident, "on")) { *set_rtrn = true; return true; } else if (istreq(ident, "false") || istreq(ident, "no") || istreq(ident, "off")) { *set_rtrn = false; return true; } } log_err(ctx, XKB_ERROR_INVALID_IDENTIFIER, "Identifier \"%s\" of type boolean is unknown\n", ident); return false; case STMT_EXPR_FIELD_REF: log_err(ctx, XKB_ERROR_INVALID_EXPRESSION_TYPE, "Default \"%s.%s\" of type boolean is unknown\n", xkb_atom_text(ctx, expr->field_ref.element), xkb_atom_text(ctx, expr->field_ref.field)); return false; case STMT_EXPR_INVERT: case STMT_EXPR_NOT: ok = ExprResolveBoolean(ctx, expr->unary.child, set_rtrn); if (ok) *set_rtrn = !*set_rtrn; return ok; case STMT_EXPR_ADD: case STMT_EXPR_SUBTRACT: case STMT_EXPR_MULTIPLY: case STMT_EXPR_DIVIDE: case STMT_EXPR_ASSIGN: case STMT_EXPR_NEGATE: case STMT_EXPR_UNARY_PLUS: case STMT_EXPR_EMPTY_LIST: case STMT_EXPR_ACTION_DECL: case STMT_EXPR_ACTION_LIST: case STMT_EXPR_KEYSYM_LIST: log_err(ctx, XKB_ERROR_INVALID_OPERATION, "%s of boolean values not permitted\n", stmt_type_to_string(expr->common.type)); break; default: log_wsgo(ctx, XKB_ERROR_UNKNOWN_OPERATOR, "Unknown operator %d in ResolveBoolean\n", expr->common.type); break; } return false; } static bool ExprResolveIntegerLookup(struct xkb_context *ctx, const ExprDef *expr, int64_t *val_rtrn, IdentLookupFunc lookup, const void *lookupPriv) { bool ok = false; int64_t l = 0, r = 0; uint32_t u = 0; ExprDef *left, *right; switch (expr->common.type) { case STMT_EXPR_INTEGER_LITERAL: *val_rtrn = expr->integer.ival; return true; case STMT_EXPR_STRING_LITERAL: case STMT_EXPR_FLOAT_LITERAL: case STMT_EXPR_BOOLEAN_LITERAL: case STMT_EXPR_KEYNAME_LITERAL: case STMT_EXPR_KEYSYM_LITERAL: log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Found %s where an int was expected\n", stmt_type_to_string(expr->common.type)); return false; case STMT_EXPR_IDENT: if (lookup) ok = lookup(ctx, lookupPriv, expr->ident.ident, &u); if (!ok) log_err(ctx, XKB_ERROR_INVALID_IDENTIFIER, "Identifier \"%s\" of type int is unknown\n", xkb_atom_text(ctx, expr->ident.ident)); else *val_rtrn = (int64_t) u; return ok; case STMT_EXPR_FIELD_REF: log_err(ctx, XKB_ERROR_INVALID_EXPRESSION_TYPE, "Default \"%s.%s\" of type int is unknown\n", xkb_atom_text(ctx, expr->field_ref.element), xkb_atom_text(ctx, expr->field_ref.field)); return false; case STMT_EXPR_ADD: case STMT_EXPR_SUBTRACT: case STMT_EXPR_MULTIPLY: case STMT_EXPR_DIVIDE: left = expr->binary.left; right = expr->binary.right; if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv) || !ExprResolveIntegerLookup(ctx, right, &r, lookup, lookupPriv)) return false; switch (expr->common.type) { case STMT_EXPR_ADD: if (ckd_add(val_rtrn, l, r)) { log_err(ctx, XKB_ERROR_INTEGER_OVERFLOW, "Addition %"PRId64" + %"PRId64" has an invalid " "mathematical result: %"PRId64"\n", l, r, *val_rtrn); return false; } break; case STMT_EXPR_SUBTRACT: if (ckd_sub(val_rtrn, l, r)) { log_err(ctx, XKB_ERROR_INTEGER_OVERFLOW, "Substraction %"PRId64" - %"PRId64" has an invalid " "mathematical result: %"PRId64"\n", l, r, *val_rtrn); return false; } break; case STMT_EXPR_MULTIPLY: if (ckd_mul(val_rtrn, l, r)) { log_err(ctx, XKB_ERROR_INTEGER_OVERFLOW, "Multiplication %"PRId64" * %"PRId64" has an invalid " "mathematical result: %"PRId64"\n", l, r, *val_rtrn); return false; } break; case STMT_EXPR_DIVIDE: if (r == 0) { log_err(ctx, XKB_ERROR_INVALID_OPERATION, "Cannot divide by zero: %"PRId64" / %"PRId64"\n", l, r); return false; } *val_rtrn = l / r; break; default: log_err(ctx, XKB_ERROR_INVALID_OPERATION, "%s of integers not permitted\n", stmt_type_to_string(expr->common.type)); return false; } return true; case STMT_EXPR_ASSIGN: log_wsgo(ctx, XKB_ERROR_INVALID_OPERATION, "Assignment operator not implemented yet\n"); break; case STMT_EXPR_NOT: log_err(ctx, XKB_ERROR_INVALID_OPERATION, "The ! operator cannot be applied to an integer\n"); return false; case STMT_EXPR_INVERT: case STMT_EXPR_NEGATE: left = expr->unary.child; if (!ExprResolveIntegerLookup(ctx, left, &l, lookup, lookupPriv)) return false; *val_rtrn = (expr->common.type == STMT_EXPR_NEGATE ? -l : ~l); return true; case STMT_EXPR_UNARY_PLUS: left = expr->unary.child; return ExprResolveIntegerLookup(ctx, left, val_rtrn, lookup, lookupPriv); default: log_wsgo(ctx, XKB_ERROR_UNKNOWN_OPERATOR, "Unknown operator %d in ResolveInteger\n", expr->common.type); break; } return false; } bool ExprResolveInteger(struct xkb_context *ctx, const ExprDef *expr, int64_t *val_rtrn) { return ExprResolveIntegerLookup(ctx, expr, val_rtrn, NULL, NULL); } bool ExprResolveGroup(struct xkb_context *ctx, xkb_layout_index_t max_groups, const ExprDef *expr, xkb_layout_index_t *group_rtrn) { const struct named_integer_pattern group_name_pattern = { /* Prefix is title-cased, because it is also used in error messages */ .prefix = "Group", .prefix_length = sizeof("Group") - 1, .min = 1, .max = max_groups, .is_mask = false, .entries = NULL, .error_id = XKB_ERROR_UNSUPPORTED_GROUP_INDEX, }; int64_t result = 0; if (!ExprResolveIntegerLookup(ctx, expr, &result, NamedIntegerPatternLookup, &group_name_pattern)) return false; if (result < 1 || result > max_groups) { log_err(ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Group index %"PRId64" is out of range (1..%"PRIu32")\n", result, max_groups); return false; } *group_rtrn = (xkb_layout_index_t) result; return true; } bool ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr, xkb_level_index_t *level_rtrn) { static const struct named_integer_pattern level_name_pattern = { /* Prefix is title-cased, because it is also used in error messages */ .prefix = "Level", .prefix_length = sizeof("Level") - 1, .min = 1, .max = XKB_LEVEL_MAX_IMPL, .is_mask = false, .entries = NULL, .error_id = XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL, }; int64_t result = 0; if (!ExprResolveIntegerLookup(ctx, expr, &result, NamedIntegerPatternLookup, &level_name_pattern)) return false; if (result < 1 || result > XKB_LEVEL_MAX_IMPL) { log_err(ctx, XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL, "Shift level %"PRId64" is out of range (1..%u)\n", result, XKB_LEVEL_MAX_IMPL); return false; } /* Level is zero-indexed from now on. */ *level_rtrn = (xkb_level_index_t) (result - 1); return true; } bool ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int64_t *btn_rtrn) { return ExprResolveIntegerLookup(ctx, expr, btn_rtrn, SimpleLookup, buttonNames); } bool ExprResolveString(struct xkb_context *ctx, const ExprDef *expr, xkb_atom_t *val_rtrn) { switch (expr->common.type) { case STMT_EXPR_STRING_LITERAL: *val_rtrn = expr->string.str; return true; case STMT_EXPR_INTEGER_LITERAL: case STMT_EXPR_FLOAT_LITERAL: case STMT_EXPR_BOOLEAN_LITERAL: case STMT_EXPR_KEYNAME_LITERAL: case STMT_EXPR_KEYSYM_LITERAL: log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Found %s, expected a string\n", stmt_type_to_string(expr->common.type)); return false; case STMT_EXPR_IDENT: log_err(ctx, XKB_ERROR_INVALID_IDENTIFIER, "Identifier \"%s\" of type string not found\n", xkb_atom_text(ctx, expr->ident.ident)); return false; case STMT_EXPR_FIELD_REF: log_err(ctx, XKB_ERROR_INVALID_EXPRESSION_TYPE, "Default \"%s.%s\" of type string not found\n", xkb_atom_text(ctx, expr->field_ref.element), xkb_atom_text(ctx, expr->field_ref.field)); return false; case STMT_EXPR_ADD: case STMT_EXPR_SUBTRACT: case STMT_EXPR_MULTIPLY: case STMT_EXPR_DIVIDE: case STMT_EXPR_ASSIGN: case STMT_EXPR_NEGATE: case STMT_EXPR_INVERT: case STMT_EXPR_NOT: case STMT_EXPR_UNARY_PLUS: case STMT_EXPR_EMPTY_LIST: case STMT_EXPR_ACTION_DECL: case STMT_EXPR_ACTION_LIST: case STMT_EXPR_KEYSYM_LIST: log_err(ctx, XKB_ERROR_INVALID_XKB_SYNTAX, "%s of strings not permitted\n", stmt_type_to_string(expr->common.type)); return false; default: log_wsgo(ctx, XKB_ERROR_UNKNOWN_OPERATOR, "Unknown operator %d in ResolveString\n", expr->common.type); break; } return false; } bool ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr, uint32_t *val_rtrn, const LookupEntry *values) { if (expr->common.type != STMT_EXPR_IDENT) { log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Found a %s where an enumerated value was expected\n", stmt_type_to_string(expr->common.type)); return false; } if (!SimpleLookup(ctx, values, expr->ident.ident, val_rtrn)) { log_err(ctx, XKB_ERROR_INVALID_IDENTIFIER, "Illegal identifier %s; expected one of:\n", xkb_atom_text(ctx, expr->ident.ident)); while (values && values->name) { log_err(ctx, XKB_ERROR_INVALID_IDENTIFIER, "\t%s\n", values->name); values++; } return false; } return true; } static bool ExprResolveMaskLookup(struct xkb_context *ctx, const ExprDef *expr, uint32_t *val_rtrn, IdentLookupFunc lookup, const void *lookupPriv) { bool ok = false; uint32_t l = 0, r = 0; int64_t v = 0; ExprDef *left, *right; const char *bogus = NULL; switch (expr->common.type) { case STMT_EXPR_INTEGER_LITERAL: if (expr->integer.ival < 0 || expr->integer.ival > UINT32_MAX) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Mask %s%#"PRIxMAX" is out of range (0..%#"PRIx32")\n", expr->integer.ival < 0 ? "-" : "", imaxabs(expr->integer.ival), UINT32_MAX); return false; } *val_rtrn = (uint32_t) expr->integer.ival; return true; case STMT_EXPR_STRING_LITERAL: case STMT_EXPR_FLOAT_LITERAL: case STMT_EXPR_BOOLEAN_LITERAL: case STMT_EXPR_KEYNAME_LITERAL: case STMT_EXPR_KEYSYM_LITERAL: log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Found %s where a mask was expected\n", stmt_type_to_string(expr->common.type)); return false; case STMT_EXPR_IDENT: ok = lookup(ctx, lookupPriv, expr->ident.ident, val_rtrn); if (!ok) log_err(ctx, XKB_ERROR_INVALID_IDENTIFIER, "Identifier \"%s\" of type int is unknown\n", xkb_atom_text(ctx, expr->ident.ident)); return ok; case STMT_EXPR_FIELD_REF: log_err(ctx, XKB_ERROR_INVALID_EXPRESSION_TYPE, "Default \"%s.%s\" of type int is unknown\n", xkb_atom_text(ctx, expr->field_ref.element), xkb_atom_text(ctx, expr->field_ref.field)); return false; case STMT_EXPR_ARRAY_REF: bogus = "array reference"; /* fallthrough */ case STMT_EXPR_ACTION_DECL: if (bogus == NULL) bogus = "function use"; log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Unexpected %s in mask expression; Expression Ignored\n", bogus); return false; case STMT_EXPR_ADD: case STMT_EXPR_SUBTRACT: case STMT_EXPR_MULTIPLY: case STMT_EXPR_DIVIDE: left = expr->binary.left; right = expr->binary.right; if (!ExprResolveMaskLookup(ctx, left, &l, lookup, lookupPriv) || !ExprResolveMaskLookup(ctx, right, &r, lookup, lookupPriv)) return false; switch (expr->common.type) { case STMT_EXPR_ADD: *val_rtrn = l | r; break; case STMT_EXPR_SUBTRACT: *val_rtrn = l & (~r); break; case STMT_EXPR_MULTIPLY: case STMT_EXPR_DIVIDE: log_err(ctx, XKB_ERROR_INVALID_OPERATION, "Cannot %s masks; Illegal operation ignored\n", (expr->common.type == STMT_EXPR_DIVIDE ? "divide" : "multiply")); return false; default: break; } return true; case STMT_EXPR_ASSIGN: log_wsgo(ctx, XKB_ERROR_INVALID_OPERATION, "Assignment operator not implemented yet\n"); break; case STMT_EXPR_INVERT: left = expr->unary.child; if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv)) return false; if (v < 0 || v > UINT32_MAX) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Mask %s%#"PRIxMAX" is out of range (0..%#"PRIx32")\n", v < 0 ? "-" : "", imaxabs(v), UINT32_MAX); return false; } *val_rtrn = ~(uint32_t) v; return true; case STMT_EXPR_UNARY_PLUS: case STMT_EXPR_NEGATE: case STMT_EXPR_NOT: left = expr->unary.child; if (!ExprResolveIntegerLookup(ctx, left, &v, lookup, lookupPriv)) return false; log_err(ctx, XKB_ERROR_INVALID_OPERATION, "The '%c' unary operator cannot be used with a mask\n", stmt_type_to_operator_char(expr->common.type)); return false; default: log_wsgo(ctx, XKB_ERROR_UNKNOWN_OPERATOR, "Unknown operator type %d in ResolveMask\n", expr->common.type); break; } return false; } bool ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr, uint32_t *mask_rtrn, const LookupEntry *values) { return ExprResolveMaskLookup(ctx, expr, mask_rtrn, SimpleLookup, values); } bool ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr, enum mod_type mod_type, const struct xkb_mod_set *mods, xkb_mod_mask_t *mask_rtrn) { LookupModMaskPriv priv = { .mods = mods, .mod_type = mod_type }; return ExprResolveMaskLookup(ctx, expr, mask_rtrn, LookupModMask, &priv); } bool ExprResolveMod(struct xkb_context *ctx, const ExprDef *def, enum mod_type mod_type, const struct xkb_mod_set *mods, xkb_mod_index_t *ndx_rtrn) { if (def->common.type != STMT_EXPR_IDENT) { log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Cannot resolve virtual modifier: " "found %s where a virtual modifier name was expected\n", stmt_type_to_string(def->common.type)); return false; } xkb_atom_t name = def->ident.ident; xkb_mod_index_t ndx = XkbModNameToIndex(mods, name, mod_type); if (ndx == XKB_MOD_INVALID) { log_err(ctx, XKB_ERROR_UNDECLARED_VIRTUAL_MODIFIER, "Cannot resolve virtual modifier: " "\"%s\" was not previously declared\n", xkb_atom_text(ctx, name)); return false; } *ndx_rtrn = ndx; return true; } bool ExprResolveGroupMask(struct xkb_context *ctx, xkb_layout_index_t max_groups, const ExprDef *expr, xkb_layout_index_t *group_rtrn) { const struct named_integer_pattern group_name_pattern = { /* Prefix is title-cased, because it is also used in error messages */ .prefix = "Group", .prefix_length = sizeof("Group") - 1, .min = 1, .max = max_groups, .is_mask = true, .entries = groupMaskNames, .error_id = XKB_ERROR_UNSUPPORTED_GROUP_INDEX }; return ExprResolveMaskLookup(ctx, expr, group_rtrn, NamedIntegerPatternLookup, &group_name_pattern); } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/expr.h000066400000000000000000000035521510033435100222510ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #pragma once #include "config.h" #include "xkbcommon/xkbcommon.h" #include "ast.h" #include "keymap.h" #include "text.h" bool ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr, const char **elem_rtrn, const char **field_rtrn, ExprDef **index_rtrn); bool ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr, enum mod_type mod_type, const struct xkb_mod_set *mods, xkb_mod_mask_t *mask_rtrn); bool ExprResolveMod(struct xkb_context *ctx, const ExprDef *def, enum mod_type mod_type, const struct xkb_mod_set *mods, xkb_mod_index_t *ndx_rtrn); bool ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, bool *set_rtrn); bool ExprResolveInteger(struct xkb_context *ctx, const ExprDef *expr, int64_t *val_rtrn); bool ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr, xkb_level_index_t *level_rtrn); bool ExprResolveGroup(struct xkb_context *ctx, xkb_layout_index_t max_groups, const ExprDef *expr, xkb_layout_index_t *group_rtrn); bool ExprResolveGroupMask(struct xkb_context *ctx, xkb_layout_index_t max_groups, const ExprDef *expr, xkb_layout_index_t *group_rtrn); bool ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, int64_t *btn_rtrn); bool ExprResolveString(struct xkb_context *ctx, const ExprDef *expr, xkb_atom_t *val_rtrn); bool ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr, uint32_t *val_rtrn, const LookupEntry *values); bool ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr, uint32_t *mask_rtrn, const LookupEntry *values); xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/include.c000066400000000000000000000414011510033435100227040ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT */ #include "config.h" #include #include #include #include #include "messages-codes.h" #include "utils.h" #include "xkbcomp-priv.h" #include "include.h" #include "scanner-utils.h" #include "utils-paths.h" /** * Parse an include statement. Each call returns a file name, along with * (possibly) a specific map in the file, an explicit group designator, and * the separator from the next file, used to determine the merge mode. * * @param str_inout Input statement, modified in-place. Should be passed in * repeatedly. If str_inout is NULL, the parsing has completed. * * @param file_rtrn Set to the name of the include file to be used. Combined * with an enum xkb_file_type, this determines which file to look for in the * include path. * * @param map_rtrn Set to the string between '(' and ')', if any. This will * result in the compilation of a specific named map within the file (e.g. * xkb_symbols "basic" { ... }) , as opposed to the default map of the file. * * @param nextop_rtrn Set to the next operation in the complete statement, * which is '\0' if it's the last file or '+' or '|' or '^' if there are more. * Separating the files with '+' sets the merge mode to `MERGE_MODE_OVERRIDE`, * while '|' sets the merge mode to `MERGE_MODE_AUGMENT` and '^' sets the merge * mode to `MERGE_REPLACE`. * * @param extra_data Set to the string after ':', if any. Currently the * extra data is only used for setting an explicit group index for a symbols * file. * * @return true if parsing was successful, false for an illegal string. * * Example: "evdev+aliases(qwerty):2" * str_inout = "aliases(qwerty):2" * file_rtrn = "evdev" * map_rtrn = NULL * nextop_retrn = "+" * extra_data = NULL * * 2nd run with "aliases(qwerty):2" * str_inout = NULL * file_rtrn = "aliases" * map_rtrn = "qwerty" * nextop_retrn = "" * extra_data = "2" * */ bool ParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn, char *nextop_rtrn, char **extra_data) { char *tmp, *str, *next; str = *str_inout; /* * Find the position in the string where the next file is included, * if there is more than one left in the statement. */ next = strpbrk(str, MERGE_MODE_PREFIXES); if (next) { /* Got more files, this function will be called again. */ *nextop_rtrn = *next; /* Separate the string, for strchr etc. to work on this file only. */ *next++ = '\0'; } else { /* This is the last file in this statement, won't be called again. */ *nextop_rtrn = '\0'; next = NULL; } /* * Search for the explicit group designator, if any. If it's there, * it goes after the file name and map. */ tmp = strchr(str, ':'); if (tmp != NULL) { *tmp++ = '\0'; *extra_data = strdup(tmp); } else { *extra_data = NULL; } /* Look for a map, if any. */ tmp = strchr(str, '('); if (tmp == NULL) { /* No map. */ *file_rtrn = strdup(str); *map_rtrn = NULL; } else if (str[0] == '(') { /* Map without file - invalid. */ free(*extra_data); return false; } else { /* Got a map; separate the file and the map for the strdup's. */ *tmp++ = '\0'; *file_rtrn = strdup(str); str = tmp; tmp = strchr(str, ')'); if (tmp == NULL || tmp[1] != '\0') { free(*file_rtrn); free(*extra_data); return false; } *tmp++ = '\0'; *map_rtrn = strdup(str); } /* Set up the next file for the next call, if any. */ if (*nextop_rtrn == '\0') *str_inout = NULL; else if (is_merge_mode_prefix(*nextop_rtrn)) *str_inout = next; else return false; return true; } static const char *xkb_file_type_include_dirs[_FILE_TYPE_NUM_ENTRIES] = { [FILE_TYPE_KEYCODES] = "keycodes", [FILE_TYPE_TYPES] = "types", [FILE_TYPE_COMPAT] = "compat", [FILE_TYPE_SYMBOLS] = "symbols", [FILE_TYPE_GEOMETRY] = "geometry", [FILE_TYPE_KEYMAP] = "keymap", [FILE_TYPE_RULES] = "rules", }; /** * Return the xkb directory based on the type. */ static const char * DirectoryForInclude(enum xkb_file_type type) { if (type >= _FILE_TYPE_NUM_ENTRIES) return ""; return xkb_file_type_include_dirs[type]; } static void LogIncludePaths(struct xkb_context *ctx) { if (xkb_context_num_include_paths(ctx) > 0) { log_err(ctx, XKB_ERROR_INCLUDED_FILE_NOT_FOUND, "%u include paths searched:\n", xkb_context_num_include_paths(ctx)); for (unsigned int i = 0; i < xkb_context_num_include_paths(ctx); i++) log_err(ctx, XKB_ERROR_INCLUDED_FILE_NOT_FOUND, "\t%s\n", xkb_context_include_path_get(ctx, i)); } else { log_err(ctx, XKB_ERROR_INCLUDED_FILE_NOT_FOUND, "There are no include paths to search\n"); } if (xkb_context_num_failed_include_paths(ctx) > 0) { log_err(ctx, XKB_ERROR_INCLUDED_FILE_NOT_FOUND, "%u include paths could not be added:\n", xkb_context_num_failed_include_paths(ctx)); for (darray_size_t i = 0; i < xkb_context_num_failed_include_paths(ctx); i++) log_err(ctx, XKB_ERROR_INCLUDED_FILE_NOT_FOUND, "\t%s\n", xkb_context_failed_include_path_get(ctx, i)); } } static size_t expand_percent(struct xkb_context *ctx, const char* parent_file_name, const char* typeDir, char *buf, size_t buf_size, const char *name, size_t name_len) { struct scanner s; scanner_init(&s, ctx, name, name_len, parent_file_name, NULL); s.buf_pos = 0; while (!scanner_eof(&s) && !scanner_eol(&s)) { if (scanner_chr(&s, '%')) { if (scanner_chr(&s, '%')) { scanner_buf_append(&s, '%'); } else if (scanner_chr(&s, 'H')) { const char *home = xkb_context_getenv(ctx, "HOME"); if (!home) { scanner_err(&s, XKB_LOG_MESSAGE_NO_ID, "%%H was used in an include statement, but the " "HOME environment variable is not set"); return 0; } if (!scanner_buf_appends(&s, home)) { scanner_err(&s, XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "include path after expanding %%H is too long"); return 0; } } else if (scanner_chr(&s, 'S')) { const char *default_root = xkb_context_include_path_get_system_path(ctx); if (!scanner_buf_appends(&s, default_root) || !scanner_buf_append(&s, '/') || !scanner_buf_appends(&s, typeDir)) { scanner_err(&s, XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "include path after expanding %%S is too long"); return 0; } } else if (scanner_chr(&s, 'E')) { const char *default_root = xkb_context_include_path_get_extra_path(ctx); if (!scanner_buf_appends(&s, default_root) || !scanner_buf_append(&s, '/') || !scanner_buf_appends(&s, typeDir)) { scanner_err(&s, XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "include path after expanding %%E is too long"); return 0; } } else { scanner_err(&s, XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "unknown %% format (%c) in include statement", scanner_peek(&s)); return 0; } } else { scanner_buf_append(&s, scanner_next(&s)); } } if (!scanner_buf_append(&s, '\0')) { scanner_err(&s, XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "include path is too long; max: %zu", sizeof(s.buf)); return 0; } if (unlikely(s.buf_pos > buf_size)) { scanner_err(&s, XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "include path is too long: %zu > %zu", s.buf_pos, buf_size); return 0; } memcpy(buf, s.buf, s.buf_pos); return s.buf_pos; } ssize_t expand_path(struct xkb_context *ctx, const char* parent_file_name, const char *name, size_t name_len, enum xkb_file_type type, char *buf, size_t buf_size) { /* Detect %-expansion */ size_t k; for (k = 0; k < name_len; k++) { if (name[k] == '%') { goto expand; } } return 0; expand: /* Process %-expansion */ /* Copy prefix (usual case: k == 0) */ if (unlikely(k >= buf_size)) { log_err(ctx, XKB_ERROR_INVALID_PATH, "Path is too long: %zu > %zu, " "got raw path: %.*s\n", k, buf_size, (unsigned int) name_len, name); return -1; } memcpy(buf, name, k); /* Proceed to %-expansion */ const char *typeDir = DirectoryForInclude(type); size_t count = expand_percent(ctx, parent_file_name, typeDir, buf + k, buf_size - k, name + k, name_len - k); if (!count) return -1; count += k; assert(buf[count - 1] == '\0'); return (ssize_t) count - 1; } /** * Return an open file handle to the first file (counting from offset) with the * given name in the include paths, starting at the offset. * * offset must be zero the first time this is called and is set to the index the * file was found. Call again with offset+1 to keep searching through the * include paths. * * If this function returns NULL, no more files are available. */ FILE * FindFileInXkbPath(struct xkb_context *ctx, const char* parent_file_name, const char *name, size_t name_len, enum xkb_file_type type, char *buf, size_t buf_size, unsigned int *offset) { /* We do not handle absolute paths here */ assert(!is_absolute_path(name)); FILE *file = NULL; char *name_buffer = NULL; const char *typeDir = DirectoryForInclude(type); for (unsigned int i = *offset; i < xkb_context_num_include_paths(ctx); i++) { if (!snprintf_safe(buf, buf_size, "%s/%s/%.*s", xkb_context_include_path_get(ctx, i), typeDir, (unsigned int) name_len, name)) { log_err(ctx, XKB_ERROR_INVALID_PATH, "Path is too long: expected max length of %zu, " "got: %s/%s/%.*s\n", buf_size, xkb_context_include_path_get(ctx, i), typeDir, (unsigned int) name_len, name); continue; } file = fopen(buf, "rb"); if (file) { *offset = i; goto out; } } /* We only print warnings if we can’t find the file on the first lookup */ if (*offset == 0) { log_err(ctx, XKB_ERROR_INCLUDED_FILE_NOT_FOUND, "Couldn't find file \"%s/%.*s\" in include paths\n", typeDir, (unsigned int) name_len, name); LogIncludePaths(ctx); } out: free(name_buffer); return file; } bool ExceedsIncludeMaxDepth(struct xkb_context *ctx, unsigned int include_depth) { if (include_depth >= INCLUDE_MAX_DEPTH) { log_err(ctx, XKB_ERROR_RECURSIVE_INCLUDE, "Exceeded include depth threshold (%u)", INCLUDE_MAX_DEPTH); return true; } else { return false; } } XkbFile * ProcessIncludeFile(struct xkb_context *ctx, const IncludeStmt *stmt, enum xkb_file_type file_type, char *path, size_t path_size) { /* * Resolve include statement: * - Explicit map name: look for an *exact match* only. * - Default map: look for an *explicit default* map (i.e. tagged with * `default`: exact match), else fallback to the first *implicit* default * map (weak match). */ XkbFile *xkb_file = NULL; /* Exact match */ XkbFile *candidate = NULL; /* Weak match */ const char *stmt_file = stmt->file; size_t stmt_file_len = strlen(stmt_file); /* Process %-expansion, if any */ // FIXME: use parent file name instead of “(unknow)”. const ssize_t expanded = expand_path(ctx, "(unknown)", stmt_file, stmt_file_len, file_type, path, path_size); if (expanded < 0) { /* Error */ return NULL; } else if (expanded > 0) { /* %-expanded */ stmt_file = path; stmt_file_len = (size_t) expanded; assert(stmt_file[stmt_file_len] == '\0'); } /* Lookup the first candidate */ FILE* file; unsigned int offset = 0; const bool absolute_path = is_absolute_path(stmt_file); if (absolute_path) { /* Absolute path: no need for lookup in XKB paths */ assert(stmt_file[stmt_file_len] == '\0'); file = fopen(stmt_file, "rb"); } else { /* Relative path: lookup the first XKB path */ if (unlikely(expanded)) { /* * Relative path after expansion * * Unlikely to happen, because %-expansion is meant to use absolute * paths. Considering that: * - we do not resolve paths before expansion, leading to unexpected * result here; * - we need the buffer afterwards, but it currently contains the * expanded path; * - this is an edge case; * we simply make the lookup fail. */ file = NULL; } else { // FIXME: use parent file name instead of “(unknow)”. file = FindFileInXkbPath(ctx, "(unknown)", stmt_file, stmt_file_len, file_type, path, path_size, &offset); } } while (file) { xkb_file = XkbParseFile(ctx, file, stmt->file, stmt->map); fclose(file); if (xkb_file) { if (xkb_file->file_type != file_type) { log_err(ctx, XKB_ERROR_INVALID_INCLUDED_FILE, "Include file of wrong type (expected %s, got %s); " "Include file \"%s\" ignored\n", xkb_file_type_to_string(file_type), xkb_file_type_to_string(xkb_file->file_type), stmt->file); FreeXkbFile(xkb_file); xkb_file = NULL; } else if (stmt->map || (xkb_file->flags && MAP_IS_DEFAULT)) { /* * Exact match: explicit map name or explicit default map. * Lookup stops here. */ break; } else if (!candidate) { /* * Weak match: looking for an explicit default map, but found * only the first *implicit* default map (e.g. first map of the * file). Use as fallback, but keep looking for an exact match. */ candidate = xkb_file; xkb_file = NULL; } else { /* * Weak match, but we already have a previous candidate. * Keep looking for an exact match. */ FreeXkbFile(xkb_file); xkb_file = NULL; } } if (absolute_path) { /* There is no point to search further if the path is absolute */ break; } offset++; file = FindFileInXkbPath(ctx, "(unknown)", stmt_file, stmt_file_len, file_type, path, path_size, &offset); } if (!xkb_file) { /* No exact match: use weak match, if any */ xkb_file = candidate; } else { /* Found exact match: discard weak match, if any */ FreeXkbFile(candidate); } if (!xkb_file) { if (stmt->map) log_err(ctx, XKB_ERROR_INVALID_INCLUDED_FILE, "Couldn't process include statement for '%s(%s)'\n", stmt->file, stmt->map); else log_err(ctx, XKB_ERROR_INVALID_INCLUDED_FILE, "Couldn't process include statement for '%s'\n", stmt->file); } return xkb_file; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/include.h000066400000000000000000000027201510033435100227120ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #pragma once #include "config.h" #include "ast.h" #include "utils.h" /* Reasonable threshold, with plenty of margin for keymaps in the wild */ #define INCLUDE_MAX_DEPTH 15 #define MERGE_OVERRIDE_PREFIX '+' #define MERGE_AUGMENT_PREFIX '|' #define MERGE_REPLACE_PREFIX '^' #define MERGE_DEFAULT_PREFIX MERGE_OVERRIDE_PREFIX #define is_merge_mode_prefix(ch) \ ((ch) == MERGE_OVERRIDE_PREFIX || (ch) == MERGE_AUGMENT_PREFIX || \ (ch) == MERGE_REPLACE_PREFIX) static const char MERGE_MODE_PREFIXES[] = { MERGE_OVERRIDE_PREFIX, MERGE_AUGMENT_PREFIX, MERGE_REPLACE_PREFIX, 0 }; bool ParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn, char *nextop_rtrn, char **extra_data); ssize_t expand_path(struct xkb_context *ctx, const char* parent_file_name, const char *name, size_t name_len, enum xkb_file_type type, char *buf, size_t buf_size); FILE * FindFileInXkbPath(struct xkb_context *ctx, const char* parent_file_name, const char *name, size_t name_len, enum xkb_file_type type, char *buf, size_t buf_size, unsigned int *offset); bool ExceedsIncludeMaxDepth(struct xkb_context *ctx, unsigned int include_depth); XkbFile * ProcessIncludeFile(struct xkb_context *ctx, const IncludeStmt *stmt, enum xkb_file_type file_type, char *path, size_t path_size); xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/keycodes.c000066400000000000000000001025741510033435100231000ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #include "config.h" #include #include #include #include #include #include "context.h" #include "messages-codes.h" #include "xkbcommon/xkbcommon.h" #include "xkbcomp-priv.h" #include "atom.h" #include "darray.h" #include "keymap.h" #include "text.h" #include "expr.h" #include "include.h" #include "util-mem.h" typedef struct { xkb_keycode_t keycode; xkb_atom_t name; } HighKeycodeEntry; typedef struct { /** Minimum keycode */ xkb_keycode_t min; /** * keycode -> name mapping, stored contiguously * keycode <= XKB_KEYCODE_MAX_CONTIGUOUS */ darray(xkb_atom_t) low; /** * keycode -> name mapping, sorted entries, possibly noncontiguous keycodes * keycode > XKB_KEYCODE_MAX_CONTIGUOUS */ darray(HighKeycodeEntry) high; /** * name -> keycode mapping */ darray(KeycodeMatch) names; } KeycodeStore; static inline void keycode_store_init(KeycodeStore *store) { darray_init(store->low); darray_init(store->high); darray_init(store->names); static_assert(XKB_KEYCODE_INVALID > XKB_KEYCODE_MAX, "Hey, you can't be changing stuff like that!"); store->min = XKB_KEYCODE_INVALID; } static inline void keycode_store_free(KeycodeStore *store) { darray_free(store->low); darray_free(store->high); darray_free(store->names); } static inline void keycode_store_update_key(KeycodeStore *store, KeycodeMatch match, xkb_atom_t name) { if (unlikely(!match.found || match.is_alias)) { return; } else if (match.key.low) { /* assume valid index */ assert(match.key.index < darray_size(store->low)); darray_item(store->low, match.key.index) = name; } else { /* assume valid index */ assert(match.key.index < darray_size(store->high)); darray_item(store->high, match.key.index).name = name; } /* Names lookup */ if (name >= darray_size(store->names)) { darray_resize0(store->names, name + 1); } darray_item(store->names, name) = match; } static bool keycode_store_insert_key(KeycodeStore *store, xkb_keycode_t kc, xkb_atom_t name) { if (name >= darray_size(store->names)) { darray_resize0(store->names, name + 1); } if (kc <= XKB_KEYCODE_MAX_CONTIGUOUS) { /* Low keycode */ if (kc >= (xkb_keycode_t) darray_size(store->low)) darray_resize0(store->low, kc + 1); darray_item(store->low, kc) = name; if (kc < store->min) store->min = kc; darray_item(store->names, name) = (KeycodeMatch) { .key = { .found = true, .low = true, .is_alias = false, .index = kc } }; } else { /* High keycode: insert into a sorted list */ const darray_size_t idx = darray_size(store->high); if (idx && darray_item(store->high, idx - 1).keycode > kc) { /* * Slow path: need to sort the keys. Since we maintain the list * sorted, we simply need to look for the insertion index. */ darray_size_t lower = 0; darray_size_t upper = idx; while (lower < upper) { const darray_size_t mid = lower + (upper - 1 - lower) / 2; const HighKeycodeEntry * const entry = &darray_item(store->high, mid); if (entry->keycode < kc) { lower = mid + 1; } else if (entry->keycode > kc) { upper = mid; } else { /* Unreachable: there is no repetition in the list */ assert(entry->keycode != kc); } } assert(lower < idx); assert(darray_item(store->high, lower).keycode > kc); /* Update references to entries that will be moved */ HighKeycodeEntry *entry; darray_foreach_from(entry, store->high, lower) { darray_item(store->names, entry->name).key.index++; } darray_insert(store->high, lower, (HighKeycodeEntry){.keycode = kc, .name = name}); darray_item(store->names, name) = (KeycodeMatch) { .key = { .found = true, .low = false, .is_alias = false, .index = lower } }; } else { /* Fast path: no need to sort */ darray_append(store->high, (HighKeycodeEntry){.keycode = kc, .name = name}); darray_item(store->names, name) = (KeycodeMatch) { .key = { .found = true, .low = false, .is_alias = false, .index = idx } }; } if (darray_empty(store->low)) store->min = darray_item(store->high, 0).keycode; } return true; } static inline bool keycode_store_insert_alias(KeycodeStore *store, xkb_atom_t alias, xkb_atom_t real) { if (alias >= darray_size(store->names)) { darray_resize0(store->names, alias + 1); } darray_item(store->names, alias) = (KeycodeMatch) { .alias = { .found = true, .is_alias = true, .real = real } }; return true; } static inline bool keycode_store_update_alias(KeycodeStore *store, xkb_atom_t alias, xkb_atom_t real) { darray_item(store->names, alias).alias.real = real; return true; } static inline void keycode_store_delete_name(const KeycodeStore *store, xkb_atom_t name) { darray_item(store->names, name).found = false; } static void keycode_store_delete_key(KeycodeStore *store, const KeycodeMatch match) { if (unlikely(!match.found || match.is_alias)) { return; } else if (match.key.low) { /* assume valid index */ assert(match.key.index < darray_size(store->low)); darray_item(store->names, darray_item(store->low, match.key.index)).found = false; if (match.key.index + 1u == darray_size(store->low)) { /* Highest low keycode: shrink */ if (store->min == match.key.index) { /* No low keycode left */ darray_size(store->low) = 0; } else { /* Look for previous defined low keycode */ for (darray_size_t idx = match.key.index; idx > 0; idx--) { if (darray_item(store->low, idx - 1) != XKB_ATOM_NONE) { darray_size(store->low) = idx; break; } } } } else { /* Lower keycode: reset */ darray_item(store->low, match.key.index) = XKB_ATOM_NONE; } } else { assert(match.key.index < darray_size(store->high)); /* assume valid index */ darray_item(store->names, darray_item(store->high, match.key.index).name).found = false; darray_remove(store->high, match.key.index); /* Update LUT indexes of high codes after the deleted one, if any */ KeycodeMatch *entry; darray_foreach(entry, store->names) { if (entry->found && !entry->is_alias && !entry->key.low && entry->key.index > match.key.index) { entry->key.index--; } } } /* Update bounds */ if (darray_empty(store->low)) { store->min = (darray_empty(store->high)) ? XKB_KEYCODE_INVALID : darray_item(store->high, 0).keycode; } else { for (xkb_keycode_t kc = store->min; kc < darray_size(store->low); kc++) { if (darray_item(store->low, kc) != XKB_ATOM_NONE) { store->min = kc; break; } } } } static inline xkb_keycode_t keycode_store_get_keycode(const KeycodeStore *store, KeycodeMatch match) { if (!match.found || match.is_alias) { return XKB_KEYCODE_INVALID; } else if (match.key.low) { /* assume valid index */ assert(match.key.index < darray_size(store->low)); return (xkb_keycode_t) match.key.index; } else { /* assume valid index */ assert(match.key.index < darray_size(store->high)); return darray_item(store->high, match.key.index).keycode; } } static inline xkb_atom_t keycode_store_get_key_name(const KeycodeStore *store, KeycodeMatch match) { if (!match.found || match.is_alias) { return XKB_ATOM_NONE; } else if (match.key.low) { /* assume valid index */ assert(match.key.index < darray_size(store->low)); return darray_item(store->low, match.key.index); } else { /* assume valid index */ assert(match.key.index < darray_size(store->high)); return darray_item(store->high, match.key.index).name; } } static KeycodeMatch keycode_store_lookup_keycode(const KeycodeStore *store, xkb_keycode_t kc) { /* Low keycodes */ if (kc < (xkb_keycode_t) darray_size(store->low)) { return (KeycodeMatch) { .key = { .found = true, .low = true, .is_alias = false, .index = kc } }; } else if (kc <= XKB_KEYCODE_MAX_CONTIGUOUS) { return (KeycodeMatch) { .found = false }; } /* High keycodes: use binary search */ darray_size_t lower = 0; darray_size_t upper = darray_size(store->high); while (lower < upper) { const darray_size_t mid = lower + (upper - 1 - lower) / 2; HighKeycodeEntry * const entry = &darray_item(store->high, mid); if (entry->keycode < kc) { lower = mid + 1; } else if (entry->keycode > kc) { upper = mid; } else { return (KeycodeMatch) { .key = { .found = true, .low = false, .is_alias = false, .index = mid } }; } } return (KeycodeMatch) { .found = false }; } static KeycodeMatch keycode_store_lookup_name(const KeycodeStore *store, xkb_atom_t name) { if (name >= darray_size(store->names)) { return (KeycodeMatch) { .found = false, .is_alias = false }; } else { return darray_item(store->names, name); } } /***====================================================================***/ typedef struct { enum merge_mode merge; xkb_atom_t name; } LedNameInfo; typedef struct { char *name; int errorCount; unsigned int include_depth; KeycodeStore keycodes; LedNameInfo led_names[XKB_MAX_LEDS]; xkb_led_index_t num_led_names; struct xkb_context *ctx; } KeyNamesInfo; /***====================================================================***/ static LedNameInfo * FindLedByName(KeyNamesInfo *info, xkb_atom_t name, xkb_led_index_t *idx_out) { for (xkb_led_index_t idx = 0; idx < info->num_led_names; idx++) { LedNameInfo *ledi = &info->led_names[idx]; if (ledi->name == name) { *idx_out = idx; return ledi; } } return NULL; } static bool AddLedName(KeyNamesInfo *info, bool same_file, LedNameInfo *new, xkb_led_index_t new_idx, bool report) { xkb_led_index_t old_idx; LedNameInfo *old; const bool replace = (new->merge != MERGE_AUGMENT); /* Check if LED with the same name already exists. */ old = FindLedByName(info, new->name, &old_idx); if (old) { if (old_idx == new_idx) { if (report) log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple indicators named \"%s\"; " "Identical definitions ignored\n", xkb_atom_text(info->ctx, new->name)); return true; } if (report) { xkb_led_index_t use = (replace ? new_idx + 1 : old_idx + 1); xkb_led_index_t ignore = (replace ? old_idx + 1 : new_idx + 1); log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple indicators named %s; Using %u, ignoring %u\n", xkb_atom_text(info->ctx, new->name), use, ignore); } if (replace) { /* Unset previous */ old->name = XKB_ATOM_NONE; } else { return true; } } if (new_idx >= info->num_led_names) info->num_led_names = new_idx + 1; /* Check if LED with the same index already exists. */ old = &info->led_names[new_idx]; if (old->name != XKB_ATOM_NONE) { if (report) { const xkb_atom_t use = (replace ? new->name : old->name); const xkb_atom_t ignore = (replace ? old->name : new->name); log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple names for indicator %u; " "Using %s, ignoring %s\n", new_idx + 1, xkb_atom_text(info->ctx, use), xkb_atom_text(info->ctx, ignore)); } if (replace) *old = *new; return true; } *old = *new; return true; } static void ClearKeyNamesInfo(KeyNamesInfo *info) { free(info->name); keycode_store_free(&info->keycodes); } static void InitKeyNamesInfo(KeyNamesInfo *info, struct xkb_context *ctx, unsigned int include_depth) { memset(info, 0, sizeof(*info)); info->ctx = ctx; info->include_depth = include_depth; keycode_store_init(&info->keycodes); } static bool AddKeyName(KeyNamesInfo *info, xkb_keycode_t kc, xkb_atom_t name, enum merge_mode merge, bool report) { #ifdef NDEBUG const #endif KeycodeMatch match_name = keycode_store_lookup_name(&info->keycodes, name); if (match_name.found) { const bool clobber = (merge != MERGE_AUGMENT); if (match_name.is_alias) { /* * There is already an alias with this name. * * Contrary to Xorg’s xkbcomp, keys and aliases share the same * namespace. So we need to resolve name conflicts as they arise, * while xkbcomp will resolve them just before copying aliases into * the keymap. */ if (report) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_NAME, "Key name %s already assigned to an alias; " "Using %s, ignoring %s\n", KeyNameText(info->ctx, name), (clobber ? "key" : "alias"), (clobber ? "alias" : "key")); } if (clobber) { /* * Override the alias. If there is a conflict with the keycode * afterwards, the old key entry will be also overriden thanks * to “clobber”. */ keycode_store_delete_name(&info->keycodes, name); #ifndef NDEBUG match_name.found = false; #endif } else { return true; } } else { const xkb_keycode_t old_kc = keycode_store_get_keycode(&info->keycodes, match_name); assert(old_kc != XKB_KEYCODE_INVALID); if (old_kc != kc) { /* There is already a different key with this name. */ if (report) { const xkb_keycode_t use = (clobber) ? kc : old_kc; const xkb_keycode_t ignore = (clobber) ? old_kc : kc; log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_NAME, "Key name %s assigned to multiple keys; " "Using %"PRIu32", ignoring %"PRIu32"\n", KeyNameText(info->ctx, name), use, ignore); } if (clobber) { /* Remove conflicting key name mapping */ keycode_store_delete_key(&info->keycodes, match_name); } else { return true; } } } } const KeycodeMatch match_kc = keycode_store_lookup_keycode(&info->keycodes, kc); const xkb_atom_t old_name = keycode_store_get_key_name(&info->keycodes, match_kc); if (old_name != XKB_ATOM_NONE) { /* There is already a key with this keycode. */ if (old_name == name) { assert(keycode_store_get_keycode(&info->keycodes, match_name) == kc); if (report) log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple identical key name definitions; " "Later occurrences of \"%s = %"PRIu32"\" ignored\n", KeyNameText(info->ctx, old_name), kc); return true; } const bool clobber = (merge != MERGE_AUGMENT); if (report) { const char* const kname = KeyNameText(info->ctx, name); const char* const old_kname = KeyNameText(info->ctx, old_name); const char* const use = (clobber) ? kname : old_kname; const char* const ignore = (clobber) ? old_kname : kname; log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple names for keycode %"PRIu32"; " "Using %s, ignoring %s\n", kc, use, ignore); } if (clobber) { keycode_store_delete_name(&info->keycodes, old_name); keycode_store_update_key(&info->keycodes, match_kc, name); } } else { /* No previous keycode */ if (!keycode_store_insert_key(&info->keycodes, kc, name)) { log_err(info->ctx, XKB_ERROR_ALLOCATION_ERROR, "Cannot add keycode\n"); return false; } } return true; } /***====================================================================***/ static bool HandleAliasDef(KeyNamesInfo *info, const KeyAliasDef *def, bool report); static void MergeKeycodeStores(KeyNamesInfo *into, KeyNamesInfo *from, enum merge_mode merge, bool report) { if (darray_empty(into->keycodes.low) && darray_empty(into->keycodes.high) && darray_empty(into->keycodes.names)) { /* Fast path: steal “from” */ into->keycodes = from->keycodes; darray_init(from->keycodes.low); darray_init(from->keycodes.high); darray_init(from->keycodes.names); } else { /* Slow path: check for conflicts */ /* Low keycodes */ for (xkb_keycode_t kc = from->keycodes.min; kc < (xkb_keycode_t) darray_size(from->keycodes.low); kc++) { /* Skip undefined keycodes */ const xkb_atom_t name = darray_item(from->keycodes.low, kc); if (name == XKB_ATOM_NONE) continue; if (!AddKeyName(into, kc, name, merge, report)) into->errorCount++; } /* High keycodes */ const HighKeycodeEntry *new; darray_foreach(new, from->keycodes.high) { assert(new->name != XKB_ATOM_NONE); if (!AddKeyName(into, new->keycode, new->name, merge, report)) into->errorCount++; } /* Aliases. */ KeycodeMatch *match; xkb_atom_t alias; darray_enumerate(alias, match, from->keycodes.names) { if (!match->found || !match->is_alias) continue; const KeyAliasDef def = { .merge = merge, .alias = alias, .real = match->alias.real }; if (!HandleAliasDef(into, &def, report)) into->errorCount++; } } } static void MergeIncludedKeycodes(KeyNamesInfo *into, KeyNamesInfo *from, enum merge_mode merge, bool report) { if (from->errorCount > 0) { into->errorCount += from->errorCount; return; } if (into->name == NULL) { into->name = steal(&from->name); } /* Merge key names. */ MergeKeycodeStores(into, from, merge, report); /* Merge LED names. */ if (into->num_led_names == 0) { memcpy(into->led_names, from->led_names, sizeof(*from->led_names) * from->num_led_names); into->num_led_names = from->num_led_names; from->num_led_names = 0; } else { for (xkb_led_index_t idx = 0; idx < from->num_led_names; idx++) { LedNameInfo *ledi = &from->led_names[idx]; if (ledi->name == XKB_ATOM_NONE) continue; ledi->merge = merge; if (!AddLedName(into, false, ledi, idx, report)) into->errorCount++; } } } static void HandleKeycodesFile(KeyNamesInfo *info, XkbFile *file); static bool HandleIncludeKeycodes(KeyNamesInfo *info, IncludeStmt *include, bool report) { KeyNamesInfo included; if (ExceedsIncludeMaxDepth(info->ctx, info->include_depth)) { info->errorCount += 10; return false; } InitKeyNamesInfo(&included, info->ctx, 0 /* unused */); included.name = steal(&include->stmt); for (IncludeStmt *stmt = include; stmt; stmt = stmt->next_incl) { KeyNamesInfo next_incl; XkbFile *file; char path[PATH_MAX]; file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_KEYCODES, path, sizeof(path)); if (!file) { info->errorCount += 10; ClearKeyNamesInfo(&included); return false; } InitKeyNamesInfo(&next_incl, info->ctx, info->include_depth + 1); HandleKeycodesFile(&next_incl, file); MergeIncludedKeycodes(&included, &next_incl, stmt->merge, report); ClearKeyNamesInfo(&next_incl); FreeXkbFile(file); } MergeIncludedKeycodes(info, &included, include->merge, report); ClearKeyNamesInfo(&included); return (info->errorCount == 0); } static bool HandleKeycodeDef(KeyNamesInfo *info, KeycodeDef *stmt, bool report) { if (stmt->value < 0 || stmt->value > XKB_KEYCODE_MAX) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Illegal keycode %"PRId64": must be between 0..%u; " "Key ignored\n", stmt->value, XKB_KEYCODE_MAX); return false; } return AddKeyName(info, (xkb_keycode_t) stmt->value, stmt->name, stmt->merge, report); } static bool HandleAliasDef(KeyNamesInfo *info, const KeyAliasDef *def, bool report) { const KeycodeMatch match_name = keycode_store_lookup_name(&info->keycodes, def->alias); if (match_name.found) { const bool clobber = (def->merge != MERGE_AUGMENT); if (match_name.is_alias) { if (def->real == match_name.alias.real) { if (report) log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_NAME, "Alias of %s for %s declared more than once; " "First definition ignored\n", KeyNameText(info->ctx, def->alias), KeyNameText(info->ctx, def->real)); } else { const xkb_atom_t use = (clobber) ? def->real : match_name.alias.real; const xkb_atom_t ignore = (clobber) ? match_name.alias.real : def->real; if (report) log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_NAME, "Multiple definitions for alias %s; " "Using %s, ignoring %s\n", KeyNameText(info->ctx, def->alias), KeyNameText(info->ctx, use), KeyNameText(info->ctx, ignore)); keycode_store_update_alias(&info->keycodes, def->alias, use); } return true; } else { /* There is already a real key with this name. * * Contrary to Xorg’s xkbcomp, keys and aliases share the same * namespace. So we need to resolve name conflicts as they arise, * while xkbcomp will resolve them just before copying aliases into * the keymap. * * Also contrary to xkbcomp, we enable aliases to override keys. */ if (report) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_NAME, "Alias name %s already assigned to a real key; " "Using %s, ignoring %s\n", KeyNameText(info->ctx, def->alias), (clobber ? "alias" : "key"), (clobber ? "key" : "alias")); } if (clobber) { /* * Note that we override the key even if the alias is proved * invalid afterwards. This would be a bug in the keycodes * files or rules, not libxkbcommon. */ keycode_store_delete_key(&info->keycodes, match_name); } else { return true; } } } return keycode_store_insert_alias(&info->keycodes, def->alias, def->real); } static bool HandleKeyNameVar(KeyNamesInfo *info, VarDef *stmt) { const char *elem, *field; ExprDef *arrayNdx; if (!ExprResolveLhs(info->ctx, stmt->name, &elem, &field, &arrayNdx)) return false; if (elem) { log_err(info->ctx, XKB_ERROR_GLOBAL_DEFAULTS_WRONG_SCOPE, "Cannot set global defaults for \"%s\" element; " "Assignment to \"%s.%s\" ignored\n", elem, elem, field); return false; } if (!istreq(field, "minimum") && !istreq(field, "maximum")) { log_err(info->ctx, XKB_ERROR_UNKNOWN_DEFAULT_FIELD, "Default defined for unknown field \"%s\"; Ignored\n", field); return false; } /* We ignore explicit min/max statements, we always use computed. */ return true; } static bool HandleLedNameDef(KeyNamesInfo *info, LedNameDef *def, bool report) { if (def->ndx < 1 || def->ndx > XKB_MAX_LEDS) { info->errorCount++; log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Illegal indicator index (%"PRId64") specified; " "must be between 1 .. %u; Ignored\n", def->ndx, XKB_MAX_LEDS); return false; } xkb_atom_t name = XKB_ATOM_NONE; if (!ExprResolveString(info->ctx, def->name, &name)) { char buf[20]; snprintf(buf, sizeof(buf), "%"PRId64, def->ndx); info->errorCount++; return ReportBadType(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE, "indicator", "name", buf, "string"); } LedNameInfo ledi = {.merge = def->merge, .name = name}; return AddLedName(info, true, &ledi, (xkb_led_index_t) def->ndx - 1, report); } static void HandleKeycodesFile(KeyNamesInfo *info, XkbFile *file) { bool ok; /* Conflicts in the same file probably require more attention than conflicts * with included files. */ const int verbosity = xkb_context_get_log_verbosity(info->ctx); const bool report_same_file = verbosity > 0; const bool report_include = verbosity > 7; free(info->name); info->name = strdup_safe(file->name); for (ParseCommon *stmt = file->defs; stmt; stmt = stmt->next) { switch (stmt->type) { case STMT_INCLUDE: ok = HandleIncludeKeycodes(info, (IncludeStmt *) stmt, report_include); break; case STMT_KEYCODE: ok = HandleKeycodeDef(info, (KeycodeDef *) stmt, report_same_file); break; case STMT_ALIAS: ok = HandleAliasDef(info, (KeyAliasDef *) stmt, report_same_file); break; case STMT_VAR: ok = HandleKeyNameVar(info, (VarDef *) stmt); break; case STMT_LED_NAME: ok = HandleLedNameDef(info, (LedNameDef *) stmt, report_same_file); break; default: log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Keycode files may define key and indicator names only; " "Ignoring %s\n", stmt_type_to_string(stmt->type)); ok = false; break; } if (!ok) info->errorCount++; if (info->errorCount > 10) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Abandoning keycodes file \"%s\"\n", safe_map_name(file)); break; } } } /***====================================================================***/ static bool CopyKeyNamesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info) { if (darray_empty(info->keycodes.low) && darray_empty(info->keycodes.high)) { /* If the keymap has no keys, let’s just use the safest pair we know. */ assert(info->keycodes.min == XKB_KEYCODE_INVALID); keymap->min_key_code = 8; static_assert(255 < XKB_KEYCODE_MAX_CONTIGUOUS, ""); keymap->max_key_code = 255; keymap->num_keys = keymap->num_keys_low = keymap->max_key_code + 1; } else { assert(info->keycodes.min <= XKB_KEYCODE_MAX); keymap->min_key_code = info->keycodes.min; keymap->max_key_code = (darray_empty(info->keycodes.high)) ? darray_size(info->keycodes.low) - 1 : darray_item( info->keycodes.high, darray_size(info->keycodes.high) - 1 ).keycode; keymap->num_keys_low = darray_size(info->keycodes.low); keymap->num_keys = keymap->num_keys_low + darray_size(info->keycodes.high); } struct xkb_key * const keys = calloc(keymap->num_keys, sizeof(*keys)); if (!keys) { keymap->num_keys = 0; keymap->min_key_code = keymap->max_key_code = XKB_KEYCODE_INVALID; return false; } /* Low keycodes */ for (xkb_keycode_t kc = keymap->min_key_code; kc < keymap->num_keys_low; kc++) keys[kc].keycode = kc; for (xkb_keycode_t kc = info->keycodes.min; kc < (xkb_keycode_t) darray_size(info->keycodes.low); kc++) keys[kc].name = darray_item(info->keycodes.low, kc); /* High keycodes */ xkb_keycode_t idx = keymap->num_keys_low; /* First high keycode index */ const HighKeycodeEntry *entry; darray_foreach(entry, info->keycodes.high) { assert(entry->name != XKB_ATOM_NONE); keys[idx].keycode = entry->keycode; keys[idx].name = entry->name; idx++; } keymap->keys = keys; return true; } static bool CopyKeycodeNameLUT(struct xkb_keymap *keymap, KeyNamesInfo *info) { KeycodeMatch *match; xkb_atom_t name; darray_enumerate(name, match, info->keycodes.names) { if (!match->found) continue; if (match->is_alias) { /* * Do some sanity checking on the aliases. We can’t do it before * because keys and their aliases may be added out-of-order. */ /* Check that ->real is a key. */ const KeycodeMatch match_real = keycode_store_lookup_name(&info->keycodes, match->alias.real); if (!match_real.found) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_DETAILED, XKB_WARNING_UNDEFINED_KEYCODE, "Attempt to alias %s to non-existent key %s; Ignored\n", KeyNameText(info->ctx, name), KeyNameText(info->ctx, match->alias.real)); match->found = false; continue; } assert(!match_real.is_alias); } else if (!match->key.low) { /* Update to final index in keymap::keys */ match->key.index += keymap->num_keys_low; } } darray_shrink(info->keycodes.names); keymap->num_key_names = darray_size(info->keycodes.names); darray_steal(info->keycodes.names, &keymap->key_names, NULL); darray_init(info->keycodes.names); return true; } static bool CopyLedNamesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info) { keymap->num_leds = info->num_led_names; for (xkb_led_index_t idx = 0; idx < info->num_led_names; idx++) { LedNameInfo *ledi = &info->led_names[idx]; if (ledi->name == XKB_ATOM_NONE) continue; keymap->leds[idx].name = ledi->name; } return true; } static bool CopyKeyNamesInfoToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info) { /* This function trashes keymap on error, but that's OK. */ if (!CopyKeyNamesToKeymap(keymap, info) || !CopyKeycodeNameLUT(keymap, info) || !CopyLedNamesToKeymap(keymap, info)) return false; keymap->keycodes_section_name = strdup_safe(info->name); XkbEscapeMapName(keymap->keycodes_section_name); return true; } /***====================================================================***/ bool CompileKeycodes(XkbFile *file, struct xkb_keymap *keymap) { KeyNamesInfo info; InitKeyNamesInfo(&info, keymap->ctx, 0); if (file != NULL) HandleKeycodesFile(&info, file); if (info.errorCount != 0) goto err_info; if (!CopyKeyNamesInfoToKeymap(keymap, &info)) goto err_info; ClearKeyNamesInfo(&info); return true; err_info: ClearKeyNamesInfo(&info); return false; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/keymap-dump.c000066400000000000000000001137401510033435100235200ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Intel Corporation * * SPDX-License-Identifier: HPND AND MIT * * Author: Daniel Stone */ #include "config.h" #include #include #include "xkbcommon/xkbcommon-keysyms.h" #include "xkbcommon/xkbcommon.h" #include "keymap.h" #include "action.h" #include "messages-codes.h" #include "xkbcomp-priv.h" #include "text.h" #define BUF_CHUNK_SIZE 4096 struct buf { char *buf; size_t size; size_t alloc; }; #define xkb_abs(n) _Generic((n), \ int: abs, \ long int: labs, \ default: llabs )((n)) static bool do_realloc(struct buf *buf, size_t at_least) { buf->alloc += BUF_CHUNK_SIZE; if (at_least >= BUF_CHUNK_SIZE) buf->alloc += at_least; char *const new = realloc(buf->buf, buf->alloc); if (!new) return false; buf->buf = new; return true; } ATTR_PRINTF(2, 3) static bool check_write_buf(struct buf *buf, const char *fmt, ...) { va_list args; int printed; size_t available; available = buf->alloc - buf->size; /* Try to write to the buffer and get the required min size (without the * final null byte). * C11 states that if `available` is 0, then the pointer may be null. */ assert(buf->buf || available == 0); va_start(args, fmt); printed = vsnprintf(buf->buf ? buf->buf + buf->size : buf->buf, available, fmt, args); va_end(args); if (printed < 0) { /* Some error */ goto err; } else if ((size_t) printed >= available) { /* Not enough space: need to realloc */ if (!do_realloc(buf, printed + 1)) goto err; /* The buffer has enough space now. */ available = buf->alloc - buf->size; assert(buf->buf && (size_t) printed < available); va_start(args, fmt); printed = vsnprintf(buf->buf + buf->size, available, fmt, args); va_end(args); if (printed < 0 || (size_t) printed >= available) goto err; } buf->size += printed; return true; err: free(buf->buf); buf->buf = NULL; return false; } #define write_buf(buf, ...) do { \ if (!check_write_buf(buf, __VA_ARGS__)) \ return false; \ } while (0) static bool check_copy_to_buf(struct buf *buf, const char* source, size_t len) { if (len == 0) return true; const size_t available = buf->alloc - buf->size; if (len >= available) { /* len + 1 (terminating NULL) */ if (!do_realloc(buf, len + 1)) { free(buf->buf); buf->buf = NULL; return false; } } memcpy(buf->buf + buf->size, source, len); buf->size += len; /* Append NULL byte */ buf->buf[buf->size] = '\0'; return true; } #define copy_to_buf_len(buf, source, len) do { \ if (!check_copy_to_buf(buf, source, len)) \ return false; \ } while (0) #define copy_to_buf(buf, source) \ copy_to_buf_len(buf, source, sizeof(source) - 1) static bool check_write_string_literal(struct buf *buf, const char* string) { copy_to_buf(buf, "\""); /* Write chunks, separated by characters requiring escape sequence */ size_t pending_start = 0; size_t current = 0; char escape_buffer[] = {'\\', '0', '0', '0', '0'}; for (; string[current] != '\0'; current++) { uint8_t escape_len; switch (string[current]) { case '\n': /* `\n` would break strings */ escape_buffer[1] = 'n'; escape_len = 2; break; case '\\': /* `\` would create escape sequences */ escape_buffer[1] = '\\'; escape_len = 2; break; default: /* * Handle `"` (would break strings) and ASCII control characters * with an octal escape sequence. Xorg xkbcomp does not parse the * escape sequence `\"` nor xkbcommon < 1.9.0, so in order to be * backward compatible we must use the octal escape sequence in * xkbcomp style `\0nnn` with *4* digits: * * 1. To be compatible with Xorg xkbcomp. * 2. To avoid issues with the next char: e.g. "\00427" should not * be emitted as "\427" nor "\0427". * * Note that xkbcommon < 1.9.0 will still not parse this correctly, * although it will not raise an error: e.g. the escape for `"`, * `\0042`, would be parsed as `\004` + `2`. */ if (unlikely((unsigned char)string[current] < 0x20U || string[current] == '"')) { escape_buffer[1] = '0'; escape_buffer[2] = '0'; escape_buffer[3] = (char)('0' + (string[current] >> 3)); escape_buffer[4] = (char)('0' + (string[current] & 0x7)); escape_len = 5; } else { /* Expand the chunk */ continue; } } /* Write pending chunk */ assert(current >= pending_start); copy_to_buf_len(buf, string + pending_start, current - pending_start); /* Write escape sequence */ copy_to_buf_len(buf, escape_buffer, escape_len); pending_start = current + 1; } /* Write remaining chunk */ assert(current >= pending_start); copy_to_buf_len(buf, string + pending_start, current - pending_start); copy_to_buf(buf, "\""); return true; } #define write_buf_string_literal(buf, string) do { \ if (!check_write_string_literal(buf, string)) \ return false; \ } while (0) static bool write_vmods(struct xkb_keymap *keymap, enum xkb_keymap_format format, struct buf *buf) { const struct xkb_mod *mod; xkb_mod_index_t vmod = 0; bool has_some = false; xkb_vmods_enumerate(vmod, mod, &keymap->mods) { if (!has_some) { copy_to_buf(buf, "\tvirtual_modifiers "); has_some = true; } else { copy_to_buf(buf, ","); } write_buf(buf, "%s", xkb_atom_text(keymap->ctx, mod->name)); /* * Ensure to always honor explicit mappings when auto canonical vmods * is enabled, so that parsing/serializing can round-trip. This is not * required when the feature is disabled (keymap format v1). * * If the auto feature is enabled, `virtual_modifiers M;` will assign * a canonical mapping > 0xff to `M` if there is no further explicit/ * implicit mapping for `M`. * * On the contrary, `virtual_modifiers M = none;` prevents the auto * mapping of `M`. So if the auto feature is enabled and there is no * further explicit/implicit mapping for `M`, then the mapping of `M` * will remain unchanged: `none`. It must be serialized to an explicit * mapping to prevent triggering the auto canonical mapping presented * above. */ const bool auto_canonical_mods = (format >= XKB_KEYMAP_FORMAT_TEXT_V2); if ((keymap->mods.explicit_vmods & (UINT32_C(1) << vmod)) && (auto_canonical_mods || mod->mapping != 0)) { /* * Explicit non-default mapping * NOTE: we can only pretty-print *real* modifiers in this context. */ write_buf(buf, "=%s", ModMaskText(keymap->ctx, MOD_REAL, &keymap->mods, mod->mapping)); } } if (has_some) copy_to_buf(buf, ";\n\n"); return true; } static bool write_keycodes(struct xkb_keymap *keymap, bool pretty, struct buf *buf) { const struct xkb_key *key; xkb_led_index_t idx; const struct xkb_led *led; if (keymap->keycodes_section_name) write_buf(buf, "xkb_keycodes \"%s\" {\n", keymap->keycodes_section_name); else copy_to_buf(buf, "xkb_keycodes {\n"); /* xkbcomp and X11 really want to see keymaps with a minimum of 8, and * a maximum of at least 255, else XWayland really starts hating life. * If this is a problem and people really need strictly bounded keymaps, * we should probably control this with a flag. */ write_buf(buf, "\tminimum = %"PRIu32";\n", MIN(keymap->min_key_code, 8)); write_buf(buf, "\tmaximum = %"PRIu32";\n", MAX(keymap->max_key_code, 255)); xkb_keys_foreach(key, keymap) { if (key->name == XKB_ATOM_NONE) continue; if (pretty) write_buf(buf, "\t%-20s", KeyNameText(keymap->ctx, key->name)); else write_buf(buf, "\t%s", KeyNameText(keymap->ctx, key->name)); write_buf(buf, " = %"PRIu32";\n", key->keycode); } xkb_leds_enumerate(idx, led, keymap) if (led->name != XKB_ATOM_NONE) { write_buf(buf, "\tindicator %u = ", idx + 1); write_buf_string_literal(buf, xkb_atom_text(keymap->ctx, led->name)); copy_to_buf(buf, ";\n"); } for (darray_size_t i = 0; i < keymap->num_key_aliases; i++) { if (pretty) write_buf(buf, "\talias %-14s", KeyNameText(keymap->ctx, keymap->key_aliases[i].alias)); else write_buf(buf, "\talias %s", KeyNameText(keymap->ctx, keymap->key_aliases[i].alias)); write_buf(buf, " = %s;\n", KeyNameText(keymap->ctx, keymap->key_aliases[i].real)); } copy_to_buf(buf, "};\n\n"); return true; } static bool write_types(struct xkb_keymap *keymap, enum xkb_keymap_format format, bool drop_unused, struct buf *buf) { if (keymap->types_section_name) write_buf(buf, "xkb_types \"%s\" {\n", keymap->types_section_name); else copy_to_buf(buf, "xkb_types {\n"); if (!write_vmods(keymap, format, buf)) return false; for (darray_size_t i = 0; i < keymap->num_types; i++) { const struct xkb_key_type * const type = &keymap->types[i]; if (!type->required && drop_unused) continue; copy_to_buf(buf, "\ttype "); write_buf_string_literal(buf, xkb_atom_text(keymap->ctx, type->name)); copy_to_buf(buf, " {\n"); write_buf(buf, "\t\tmodifiers= %s;\n", ModMaskText(keymap->ctx, MOD_BOTH, &keymap->mods, type->mods.mods)); for (darray_size_t j = 0; j < type->num_entries; j++) { const char *str; const struct xkb_key_type_entry *entry = &type->entries[j]; /* * Printing level 1 entries is redundant, it's the default, * unless there's preserve info. */ if (entry->level == 0 && entry->preserve.mods == 0) continue; str = ModMaskText(keymap->ctx, MOD_BOTH, &keymap->mods, entry->mods.mods); write_buf(buf, "\t\tmap[%s]= %"PRIu32";\n", str, entry->level + 1); if (entry->preserve.mods) write_buf(buf, "\t\tpreserve[%s]= %s;\n", str, ModMaskText(keymap->ctx, MOD_BOTH, &keymap->mods, entry->preserve.mods)); } for (xkb_level_index_t n = 0; n < type->num_level_names; n++) if (type->level_names[n]) { write_buf(buf, "\t\tlevel_name[%"PRIu32"]= ", n + 1); write_buf_string_literal( buf, xkb_atom_text(keymap->ctx, type->level_names[n])); copy_to_buf(buf, ";\n"); } copy_to_buf(buf, "\t};\n"); } copy_to_buf(buf, "};\n\n"); return true; } static bool write_led_map(struct xkb_keymap *keymap, struct buf *buf, const struct xkb_led *led) { copy_to_buf(buf, "\tindicator "); write_buf_string_literal(buf, xkb_atom_text(keymap->ctx, led->name)); copy_to_buf(buf, " {\n"); if (led->which_groups) { if (led->which_groups != XKB_STATE_LAYOUT_EFFECTIVE) { write_buf(buf, "\t\twhichGroupState= %s;\n", LedStateMaskText(keymap->ctx, groupComponentMaskNames, led->which_groups)); } write_buf(buf, "\t\tgroups= 0x%02x;\n", led->groups); } if (led->which_mods) { if (led->which_mods != XKB_STATE_MODS_EFFECTIVE) { write_buf(buf, "\t\twhichModState= %s;\n", LedStateMaskText(keymap->ctx, modComponentMaskNames, led->which_mods)); } write_buf(buf, "\t\tmodifiers= %s;\n", ModMaskText(keymap->ctx, MOD_BOTH, &keymap->mods, led->mods.mods)); } if (led->ctrls) { write_buf(buf, "\t\tcontrols= %s;\n", ControlMaskText(keymap->ctx, led->ctrls)); } copy_to_buf(buf, "\t};\n"); return true; } static const char * affect_lock_text(enum xkb_action_flags flags, bool show_both) { switch (flags & (ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK)) { case 0: return show_both ? ",affect=both" : ""; case ACTION_LOCK_NO_UNLOCK: return ",affect=lock"; case ACTION_LOCK_NO_LOCK: return ",affect=unlock"; case ACTION_LOCK_NO_LOCK | ACTION_LOCK_NO_UNLOCK: return ",affect=neither"; default: return ""; } } #define SYMBOL_PADDING 15 #define ACTION_PADDING 30 static bool write_action(struct xkb_keymap *keymap, enum xkb_keymap_format format, xkb_layout_index_t max_groups, struct buf *buf, const union xkb_action *action, const char *prefix, const char *suffix) { const char *type; const char *args = NULL; if (!prefix) prefix = ""; if (!suffix) suffix = ""; type = ActionTypeText(action->type); switch (action->type) { case ACTION_TYPE_MOD_SET: case ACTION_TYPE_MOD_LATCH: case ACTION_TYPE_MOD_LOCK: if (action->mods.flags & ACTION_MODS_LOOKUP_MODMAP) args = "modMapMods"; else args = ModMaskText(keymap->ctx, MOD_BOTH, &keymap->mods, action->mods.mods.mods); bool unlockOnPress = (action->mods.flags & ACTION_UNLOCK_ON_PRESS); if (unlockOnPress && !isModsUnLockOnPressSupported(format)) { log_err(keymap->ctx, XKB_ERROR_INCOMPATIBLE_KEYMAP_TEXT_FORMAT, "Cannot use \"%s(unlockOnPress=true)\" in keymap format %d\n", ActionTypeText(action->type), format); unlockOnPress = false; } bool latchOnPress = action->type == ACTION_TYPE_MOD_LATCH && (action->group.flags & ACTION_LATCH_ON_PRESS); if (latchOnPress && !isModsLatchOnPressSupported(format)) { log_err(keymap->ctx, XKB_ERROR_INCOMPATIBLE_KEYMAP_TEXT_FORMAT, "Cannot use \"LatchMods(latchOnPress=true)\" " "in keymap format %d\n", format); latchOnPress = false; } write_buf(buf, "%s%s(modifiers=%s%s%s%s%s%s)%s", prefix, type, args, (action->type != ACTION_TYPE_MOD_LOCK && (action->mods.flags & ACTION_LOCK_CLEAR)) ? ",clearLocks" : "", (action->type != ACTION_TYPE_MOD_LOCK && (action->mods.flags & ACTION_LATCH_TO_LOCK)) ? ",latchToLock" : "", (action->type == ACTION_TYPE_MOD_LOCK) ? affect_lock_text(action->mods.flags, false) : "", (unlockOnPress) ? ",unlockOnPress" : "", (latchOnPress) ? ",latchOnPress" : "", suffix); break; case ACTION_TYPE_GROUP_SET: case ACTION_TYPE_GROUP_LATCH: case ACTION_TYPE_GROUP_LOCK: if ((uint32_t) xkb_abs(action->group.group) < (max_groups + !(action->group.flags & ACTION_ABSOLUTE_SWITCH))) { bool lockOnRelease = action->type == ACTION_TYPE_GROUP_LOCK && (action->group.flags & ACTION_LOCK_ON_RELEASE); if (lockOnRelease && !isGroupLockOnReleaseSupported(format)) { log_err(keymap->ctx, XKB_ERROR_INCOMPATIBLE_KEYMAP_TEXT_FORMAT, "Cannot use \"GroupLock(lockOnRelease=true)\" " "in keymap format %d\n", format); lockOnRelease = false; } write_buf(buf, "%s%s(group=%s%"PRId32"%s%s%s)%s", prefix, type, (!(action->group.flags & ACTION_ABSOLUTE_SWITCH) && action->group.group > 0) ? "+" : "", (action->group.flags & ACTION_ABSOLUTE_SWITCH) ? action->group.group + 1 : action->group.group, (action->type != ACTION_TYPE_GROUP_LOCK && (action->group.flags & ACTION_LOCK_CLEAR)) ? ",clearLocks" : "", (action->type != ACTION_TYPE_GROUP_LOCK && (action->group.flags & ACTION_LATCH_TO_LOCK)) ? ",latchToLock" : "", (lockOnRelease) ? ",lockOnRelease" : "", suffix); } else { /* Unsupported group index: degrade to VoidAction() */ goto void_action; } break; case ACTION_TYPE_TERMINATE: write_buf(buf, "%s%s()%s", prefix, type, suffix); break; case ACTION_TYPE_PTR_MOVE: write_buf(buf, "%s%s(x=%s%d,y=%s%d%s)%s", prefix, type, (!(action->ptr.flags & ACTION_ABSOLUTE_X) && action->ptr.x >= 0) ? "+" : "", action->ptr.x, (!(action->ptr.flags & ACTION_ABSOLUTE_Y) && action->ptr.y >= 0) ? "+" : "", action->ptr.y, (action->ptr.flags & ACTION_ACCEL) ? "" : ",!accel", suffix); break; case ACTION_TYPE_PTR_LOCK: args = affect_lock_text(action->btn.flags, true); /* fallthrough */ case ACTION_TYPE_PTR_BUTTON: write_buf(buf, "%s%s(button=", prefix, type); if (action->btn.button > 0 && action->btn.button <= 5) write_buf(buf, "%u", action->btn.button); else copy_to_buf(buf, "default"); if (action->btn.count) write_buf(buf, ",count=%u", action->btn.count); if (args) write_buf(buf, "%s", args); write_buf(buf, ")%s", suffix); break; case ACTION_TYPE_PTR_DEFAULT: write_buf(buf, "%s%s(", prefix, type); write_buf(buf, "affect=button,button=%s%d", (!(action->dflt.flags & ACTION_ABSOLUTE_SWITCH) && action->dflt.value >= 0) ? "+" : "", action->dflt.value); write_buf(buf, ")%s", suffix); break; case ACTION_TYPE_SWITCH_VT: write_buf(buf, "%s%s(screen=%s%d,%ssame)%s", prefix, type, (!(action->screen.flags & ACTION_ABSOLUTE_SWITCH) && action->screen.screen >= 0) ? "+" : "", action->screen.screen, (action->screen.flags & ACTION_SAME_SCREEN) ? "" : "!", suffix); break; case ACTION_TYPE_CTRL_SET: case ACTION_TYPE_CTRL_LOCK: write_buf(buf, "%s%s(controls=%s%s)%s", prefix, type, ControlMaskText(keymap->ctx, action->ctrls.ctrls), (action->type == ACTION_TYPE_CTRL_LOCK) ? affect_lock_text(action->ctrls.flags, false) : "", suffix); break; case ACTION_TYPE_NONE: write_buf(buf, "%sNoAction()%s", prefix, suffix); break; case ACTION_TYPE_VOID: void_action: /* * VoidAction() is a libxkbcommon extension. * Use LockControls as a backward-compatible fallback. * We cannot serialize it to `NoAction()`, as it would be dropped in * e.g. the context of multiple actions. * We better not use `Private` either, because it could still be * interpreted by X11. */ if (format == XKB_KEYMAP_FORMAT_TEXT_V1) write_buf(buf, "%sLockControls(controls=none,affect=neither)%s", prefix, suffix); else write_buf(buf, "%sVoidAction()%s", prefix, suffix); break; default: {} /* Label followed by declaration requires C23 */ /* Ensure to not miss `xkb_action_type` updates */ static_assert(ACTION_TYPE_INTERNAL == 18 && ACTION_TYPE_INTERNAL + 1 == _ACTION_TYPE_NUM_ENTRIES, "Missing action type"); /* Unsupported legacy actions should have degraded to NoAction */ assert(action->type != ACTION_TYPE_UNSUPPORTED_LEGACY); write_buf(buf, "%s%s(type=0x%02x,data[0]=0x%02x,data[1]=0x%02x,data[2]=0x%02x,data[3]=0x%02x,data[4]=0x%02x,data[5]=0x%02x,data[6]=0x%02x)%s", prefix, type, action->type, action->priv.data[0], action->priv.data[1], action->priv.data[2], action->priv.data[3], action->priv.data[4], action->priv.data[5], action->priv.data[6], suffix); break; } return true; } static const union xkb_action void_actions[] = { { .type = ACTION_TYPE_VOID } }; static bool write_actions(struct xkb_keymap *keymap, enum xkb_keymap_format format, xkb_layout_index_t max_groups, struct buf *buf, struct buf *buf2, const struct xkb_key *key, xkb_layout_index_t group) { static const union xkb_action noAction = { .type = ACTION_TYPE_NONE }; for (xkb_level_index_t level = 0; level < XkbKeyNumLevels(key, group); level++) { if (level != 0) copy_to_buf(buf, ", "); const union xkb_action *actions = NULL; xkb_action_count_t count = xkb_keymap_key_get_actions_by_level( keymap, key, group, level, &actions ); if (count > 1 && format < XKB_KEYMAP_FORMAT_TEXT_V2) { /* V1: Degrade multiple actions to VoidAction() */ actions = void_actions; count = 1; log_err(keymap->ctx, XKB_ERROR_INCOMPATIBLE_KEYMAP_TEXT_FORMAT, "Cannot serialize multiple actions per level " "in keymap format %d; degrade to VoidAction()\n", format); } buf2->size = 0; if (count == 0) { if (!write_action(keymap, format, max_groups, buf2, &noAction, NULL, NULL)) return false; write_buf(buf, "%*s", ACTION_PADDING, buf2->buf); } else if (count == 1) { if (!write_action(keymap, format, max_groups, buf2, &(actions[0]), NULL, NULL)) return false; write_buf(buf, "%*s", ACTION_PADDING, buf2->buf); } else { copy_to_buf(buf2, "{ "); for (xkb_action_count_t k = 0; k < count; k++) { if (k != 0) copy_to_buf(buf2, ", "); size_t old_size = buf2->size; if (!write_action(keymap, format, max_groups, buf2, &(actions[k]), NULL, NULL)) return false; /* Check if padding is necessary */ if (buf2->size >= old_size + ACTION_PADDING) continue; /* Compute and write padding, then write the action again */ const int padding = (int)(old_size + ACTION_PADDING - buf2->size); buf2->size = old_size; write_buf(buf2, "%*s", padding, ""); if (!write_action(keymap, format, max_groups, buf2, &(actions[k]), NULL, NULL)) return false; } copy_to_buf(buf2, " }"); write_buf(buf, "%*s", ACTION_PADDING, buf2->buf); } } return true; } static bool write_compat(struct xkb_keymap *keymap, enum xkb_keymap_format format, xkb_layout_index_t max_groups, bool drop_unused, bool pretty, struct buf *buf) { const struct xkb_led *led; if (keymap->compat_section_name) write_buf(buf, "xkb_compatibility \"%s\" {\n", keymap->compat_section_name); else copy_to_buf(buf, "xkb_compatibility {\n"); if (!write_vmods(keymap, format, buf)) return false; copy_to_buf(buf, "\tinterpret.useModMapMods= AnyLevel;\n"); copy_to_buf(buf, "\tinterpret.repeat= False;\n"); /* xkbcomp requires at least one interpret entry. */ const darray_size_t num_sym_interprets = keymap->num_sym_interprets ? keymap->num_sym_interprets : 1; const struct xkb_sym_interpret* const sym_interprets = keymap->num_sym_interprets ? keymap->sym_interprets : &default_interpret; for (darray_size_t i = 0; i < num_sym_interprets; i++) { const struct xkb_sym_interpret *si = &sym_interprets[i]; if (!si->required && drop_unused) continue; if (pretty || !si->sym) { write_buf(buf, "\tinterpret %s+%s(%s) {", si->sym ? KeysymText(keymap->ctx, si->sym) : "Any", SIMatchText(si->match), ModMaskText(keymap->ctx, MOD_BOTH, &keymap->mods, si->mods)); } else { write_buf(buf, "\tinterpret 0x%"PRIx32"+%s(%s) {", si->sym, SIMatchText(si->match), ModMaskText(keymap->ctx, MOD_BOTH, &keymap->mods, si->mods)); } bool has_explicit_properties = false; if (si->virtual_mod != XKB_MOD_INVALID) { write_buf(buf, "\n\t\tvirtualModifier= %s;", ModIndexText(keymap->ctx, &keymap->mods, si->virtual_mod)); has_explicit_properties = true; } if (si->level_one_only) { copy_to_buf(buf, "\n\t\tuseModMapMods=level1;"); has_explicit_properties = true; } if (si->repeat) { copy_to_buf(buf, "\n\t\trepeat= True;"); has_explicit_properties = true; } const union xkb_action *action = NULL; xkb_action_count_t action_count = si->num_actions; if (action_count <= 1) { action = &si->a.action; } else if (format < XKB_KEYMAP_FORMAT_TEXT_V2) { /* V1: Degrade multiple actions to VoidAction() */ action = &void_actions[0]; action_count = 1; log_err(keymap->ctx, XKB_ERROR_INCOMPATIBLE_KEYMAP_TEXT_FORMAT, "Cannot serialize multiple actions per level " "in keymap format %d; degrade to VoidAction()\n", format); } if (action_count > 1) { copy_to_buf(buf, "\n\t\taction= {"); const char suffix[] = ", "; for (xkb_action_count_t k = 0; k < si->num_actions; k++) { if (!write_action(keymap, format, max_groups, buf, &si->a.actions[k], "", suffix)) return false; } buf->size -= sizeof(suffix) - 1; /* trailing comma */ copy_to_buf(buf, "};"); has_explicit_properties = true; } else if (action_count == 1) { if (!write_action(keymap, format, max_groups, buf, action, "\n\t\taction= ", ";")) return false; has_explicit_properties = true; } write_buf(buf, (has_explicit_properties ? "\n\t};\n" /* Empty interpret is a syntax error in xkbcomp, so * use a dummy entry */ : "\n\t\taction= NoAction();\n\t};\n")); } xkb_leds_foreach(led, keymap) if (led->which_groups || led->groups || led->which_mods || led->mods.mods || led->ctrls) if (!write_led_map(keymap, buf, led)) return false; copy_to_buf(buf, "};\n\n"); return true; } static bool write_keysyms(struct xkb_keymap *keymap, struct buf *buf, struct buf *buf2, const struct xkb_key *key, xkb_layout_index_t group, bool pretty, bool show_actions) { const unsigned int padding = (pretty) ? ((show_actions) ? ACTION_PADDING : SYMBOL_PADDING) : 0; for (xkb_level_index_t level = 0; level < XkbKeyNumLevels(key, group); level++) { const xkb_keysym_t *syms; int num_syms; if (level != 0) copy_to_buf(buf, ", "); num_syms = xkb_keymap_key_get_syms_by_level(keymap, key->keycode, group, level, &syms); const xkb_keysym_t no_symbol = XKB_KEY_NoSymbol; if (num_syms == 0) { num_syms = 1; syms = &no_symbol; } /* * NOTE: Use `NoSymbol` even without pretty output, for compatibility * with xkbcomp and libxkbcommon < 1.12 */ if (num_syms == 1) { if (pretty || syms[0] == XKB_KEY_NoSymbol) write_buf(buf, "%*s", padding, KeysymText(keymap->ctx, syms[0])); else write_buf(buf, "0x%"PRIx32, syms[0]); } else { if (pretty) { buf2->size = 0; copy_to_buf(buf2, "{ "); for (int s = 0; s < num_syms; s++) { if (s != 0) copy_to_buf(buf2, ", "); write_buf(buf2, "%*s", (show_actions ? padding : 0), KeysymText(keymap->ctx, syms[s])); } copy_to_buf(buf2, " }"); write_buf(buf, "%*s", padding, buf2->buf); } else { copy_to_buf(buf, "{"); for (int s = 0; s < num_syms; s++) { if (s != 0) copy_to_buf(buf, ","); if (syms[s] == XKB_KEY_NoSymbol) copy_to_buf(buf, "NoSymbol"); else write_buf(buf, "0x%"PRIx32, syms[s]); } copy_to_buf(buf, "}"); } } } return true; } static bool write_key(struct xkb_keymap *keymap, enum xkb_keymap_format format, xkb_layout_index_t max_groups, bool pretty, struct buf *buf, struct buf *buf2, const struct xkb_key *key) { bool simple = true; const xkb_layout_index_t num_groups = MIN(key->num_groups, max_groups); if (pretty) write_buf(buf, "\tkey %-20s {", KeyNameText(keymap->ctx, key->name)); else write_buf(buf, "\tkey %s {", KeyNameText(keymap->ctx, key->name)); if (key->explicit & EXPLICIT_TYPES) { simple = false; bool multi_type = false; for (xkb_layout_index_t group = 1; group < num_groups; group++) { if (key->groups[group].type != key->groups[0].type) { multi_type = true; break; } } if (multi_type) { for (xkb_layout_index_t group = 0; group < num_groups; group++) { if (!key->groups[group].explicit_type) continue; const struct xkb_key_type * const type = key->groups[group].type; write_buf(buf, "\n\t\ttype[%"PRIu32"]= ", group + 1); write_buf_string_literal( buf, xkb_atom_text(keymap->ctx, type->name)); copy_to_buf(buf, ","); } } else { const struct xkb_key_type * const type = key->groups[0].type; write_buf(buf, "\n\t\ttype= "); write_buf_string_literal( buf, xkb_atom_text(keymap->ctx, type->name)); copy_to_buf(buf, ","); } } /* * NOTE: we use key->explicit and not key->group[i].explicit_actions, in * order to have X11 and the previous versions of libxkbcommon (without this * group property) parse the keymap as intended, by setting explicitly for * this key all actions in all groups. * * One side effect is that no interpretation will be run on this key anymore, * so we may have to set some extra fields explicitly: repeat, virtualMods. */ const bool show_actions = (key->explicit & EXPLICIT_INTERP); /* If we show actions, interprets are not going to be used to set this * field, so make it explicit. */ if ((key->explicit & EXPLICIT_REPEAT) || show_actions) { if (key->repeats) copy_to_buf(buf, "\n\t\trepeat= Yes,"); else copy_to_buf(buf, "\n\t\trepeat= No,"); } /* If we show actions, interprets are not going to be used to set this * field, so make it explicit. */ if ((key->explicit & EXPLICIT_VMODMAP) || (show_actions && key->vmodmap)) write_buf(buf, "\n\t\tvirtualMods= %s,", ModMaskText(keymap->ctx, MOD_BOTH, &keymap->mods, key->vmodmap)); switch (key->out_of_range_group_action) { case RANGE_SATURATE: copy_to_buf(buf, "\n\t\tgroupsClamp,"); break; case RANGE_REDIRECT: if (key->out_of_range_group_number < num_groups) { /* TODO: Fallback or warning if condition fails? */ write_buf(buf, "\n\t\tgroupsRedirect= %"PRIu32",", key->out_of_range_group_number + 1); } break; default: break; } if (num_groups > 1 || show_actions) simple = false; if (simple) { const bool only_symbols = key->explicit == EXPLICIT_SYMBOLS; if (num_groups == 0) { /* Remove trailing comma */ if (buf->buf[buf->size - 1] == ',') buf->size--; } else { if (!only_symbols) copy_to_buf(buf, "\n\t"); copy_to_buf(buf, "\t[ "); if (!write_keysyms(keymap, buf, buf2, key, 0, pretty, false)) return false; copy_to_buf(buf, " ]"); } write_buf(buf, "%s", (only_symbols ? " };\n" : "\n\t};\n")); } else { assert(num_groups > 0); for (xkb_layout_index_t group = 0; group < num_groups; group++) { if (group != 0) copy_to_buf(buf, ","); write_buf(buf, "\n\t\tsymbols[%"PRIu32"]= [ ", group + 1); if (!write_keysyms(keymap, buf, buf2, key, group, pretty, show_actions)) return false; copy_to_buf(buf, " ]"); if (show_actions) { write_buf(buf, ",\n\t\tactions[%"PRIu32"]= [ ", group + 1); if (!write_actions(keymap, format, max_groups, buf, buf2, key, group)) return false; copy_to_buf(buf, " ]"); } } copy_to_buf(buf, "\n\t};\n"); } return true; } static bool write_symbols(struct xkb_keymap *keymap, enum xkb_keymap_format format, xkb_layout_index_t max_groups, bool pretty, struct buf *buf) { if (keymap->symbols_section_name) write_buf(buf, "xkb_symbols \"%s\" {\n", keymap->symbols_section_name); else copy_to_buf(buf, "xkb_symbols {\n"); const xkb_layout_index_t num_group_names = MIN(keymap->num_group_names, max_groups); bool has_group_names = false; for (xkb_layout_index_t group = 0; group < num_group_names; group++) if (keymap->group_names[group]) { write_buf(buf, "\tname[%"PRIu32"]=", group + 1); write_buf_string_literal( buf, xkb_atom_text(keymap->ctx, keymap->group_names[group])); copy_to_buf(buf, ";\n"); has_group_names = true; } if (has_group_names) copy_to_buf(buf, "\n"); struct buf buf2 = { NULL, 0, 0 }; const struct xkb_key *key; xkb_keys_foreach(key, keymap) { /* Skip keys with no explicit values */ if (key->explicit) { if (!write_key(keymap, format, max_groups, pretty, buf, &buf2, key)) { free(buf2.buf); return false; } } } free(buf2.buf); xkb_mod_index_t i; const struct xkb_mod *mod; xkb_rmods_enumerate(i, mod, &keymap->mods) { bool had_any = false; xkb_keys_foreach(key, keymap) { if (key->modmap & (UINT32_C(1) << i)) { if (!had_any) write_buf(buf, "\tmodifier_map %s { ", xkb_atom_text(keymap->ctx, mod->name)); write_buf(buf, "%s%s", had_any ? ", " : "", KeyNameText(keymap->ctx, key->name)); had_any = true; } } if (had_any) copy_to_buf(buf, " };\n"); } copy_to_buf(buf, "};\n\n"); return true; } static bool write_keymap(struct xkb_keymap *keymap, enum xkb_keymap_format format, enum xkb_keymap_serialize_flags flags, struct buf *buf) { const xkb_layout_index_t max_groups = format_max_groups(format); if (keymap->num_groups > max_groups) { log_err(keymap->ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Cannot serialize %"PRIu32" groups in keymap format %d: " "maximum is %"PRIu32"; discarding unsupported groups\n", keymap->num_groups, format, max_groups); } const bool pretty = !!(flags & XKB_KEYMAP_SERIALIZE_PRETTY); const bool drop_unused = !(flags & XKB_KEYMAP_SERIALIZE_KEEP_UNUSED); return (check_write_buf(buf, "xkb_keymap {\n") && write_keycodes(keymap, pretty, buf) && write_types(keymap, format, drop_unused, buf) && write_compat(keymap, format, max_groups, drop_unused, pretty, buf) && write_symbols(keymap, format, max_groups, pretty, buf) && check_write_buf(buf, "};\n")); } char * text_v1_keymap_get_as_string(struct xkb_keymap *keymap, enum xkb_keymap_format format, enum xkb_keymap_serialize_flags flags) { struct buf buf = { NULL, 0, 0 }; if (!write_keymap(keymap, format, flags, &buf)) { free(buf.buf); return NULL; } return buf.buf; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/keymap-file-iterator.c000066400000000000000000000415341510033435100253220ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "context.h" #include "darray.h" #include "messages-codes.h" #include "utils.h" #include "utils-paths.h" #include "keymap-file-iterator.h" #include "xkbcomp-priv.h" #include "include.h" #include "xkbcomp/ast.h" const char * xkb_file_type_name(enum xkb_file_type type) { if (type > FILE_TYPE_KEYMAP) return "unknown"; static const char *xkb_file_type_strings[_FILE_TYPE_NUM_ENTRIES] = { [FILE_TYPE_KEYCODES] = "keycodes", [FILE_TYPE_TYPES] = "types", [FILE_TYPE_COMPAT] = "compatibility", [FILE_TYPE_SYMBOLS] = "symbols", [FILE_TYPE_GEOMETRY] = "geometry", [FILE_TYPE_KEYMAP] = "keymap", }; return xkb_file_type_strings[type]; } const char * xkb_merge_mode_name(enum merge_mode merge) { if (merge >= _MERGE_MODE_NUM_ENTRIES) return "unknown"; static const char *merge_mode_strings[_MERGE_MODE_NUM_ENTRIES] = { [MERGE_DEFAULT] = "default", [MERGE_AUGMENT] = "augment", [MERGE_OVERRIDE] = "override", [MERGE_REPLACE] = "replace", }; return merge_mode_strings[merge]; } /* Stateful lookup of map flags names */ const char * xkb_map_flags_string_iter(unsigned int *index, enum xkb_map_flags flags) { if (!flags) return NULL; static const struct { enum xkb_map_flags flag; const char *name; } names[] = { { MAP_IS_DEFAULT, "default" }, { MAP_IS_PARTIAL, "partial" }, { MAP_IS_HIDDEN, "hidden" }, { MAP_HAS_ALPHANUMERIC, "alphanumeric" }, { MAP_HAS_MODIFIER, "modifiers" }, { MAP_HAS_KEYPAD, "keypad" }, { MAP_HAS_FN, "fn" }, { MAP_IS_ALTGR, "altgr" }, }; while (*index < ARRAY_SIZE(names)) { if (flags & names[*index].flag) return names[(*index)++].name; (*index)++; } return NULL; }; FILE * xkb_resolve_file(struct xkb_context *ctx, enum xkb_file_type file_type, const char *path, const char *map, char *resolved_path, size_t resolved_path_size, char *resolved_map, size_t resolved_map_size) { unsigned int offset = 0; FILE *file = NULL; /* Exact match */ FILE *candidate = NULL; /* Weak match */ const size_t path_len = strlen(path); const bool absolute_path = is_absolute_path(path); if (absolute_path) { /* Absolute path: no need for lookup in XKB paths */ file = fopen(path, "rb"); } else { /* Relative path: lookup the first XKB path */ file = FindFileInXkbPath(ctx, "(unknown)", path, path_len, file_type, resolved_path, resolved_path_size, &offset); } while (file) { XkbFile * const xkb_file = XkbParseFile(ctx, file, path, map); if (xkb_file) { if (file_type < _FILE_TYPE_NUM_ENTRIES && xkb_file->file_type != file_type) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "File of wrong type (expected %s, got %s); " "file \"%s\" ignored\n", xkb_file_type_to_string(file_type), xkb_file_type_to_string(xkb_file->file_type), (absolute_path ? path : resolved_path)); goto invalid_file; } else if (map || (xkb_file->flags && MAP_IS_DEFAULT)) { /* * Exact match: explicit map name or explicit default map. * Lookup stops in this iteration. */ if (!strcpy_safe(resolved_map, resolved_map_size, (xkb_file->name ? xkb_file->name : ""))) { FreeXkbFile(xkb_file); goto error; } } else if (!candidate) { /* * Weak match: looking for an explicit default map, but found * only the first *implicit* default map (e.g. first map of the * file). Use as fallback, but keep looking for an exact match. */ candidate = file; if (!strcpy_safe(resolved_map, resolved_map_size, (xkb_file->name ? xkb_file->name : ""))) { FreeXkbFile(xkb_file); goto error; } } else { /* * Weak match, but we already have a previous candidate. * Keep looking for an exact match. */ goto invalid_file; } } else { invalid_file: fclose(file); file = NULL; } FreeXkbFile(xkb_file); if (file != NULL || absolute_path) { /* Exact match or absolute path with no further file to search */ break; } offset++; file = FindFileInXkbPath(ctx, "(unknown)", path, path_len, file_type, resolved_path, resolved_path_size, &offset); } if (!file) { /* No exact match: use weak match, if any */ file = candidate; } else if (candidate) { /* Found exact match: discard weak match, if any */ fclose(candidate); } if (absolute_path && file && !strcpy_safe(resolved_path, resolved_path_size, path)) { goto error; } return file; error: log_err(ctx, XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "Cannot copy resolved path or section\n"); fclose(file); return NULL; } void xkb_file_section_init(struct xkb_file_section *section) { darray_init(section->include_groups); darray_init(section->includes); darray_init(section->buffer); darray_append(section->buffer, '\0'); } static void xkb_file_section_reset(struct xkb_file_section *section) { darray_size(section->include_groups) = 0; darray_size(section->includes) = 0; darray_size(section->buffer) = 1; /* keep the dummy string */ } void xkb_file_section_free(struct xkb_file_section *section) { if (!section) return; darray_free(section->include_groups); darray_free(section->includes); darray_free(section->buffer); } static bool xkb_file_section_set_meta_data(struct xkb_context *ctx, struct xkb_file_section *section, const XkbFile *xkb_file) { section->file_type = xkb_file->file_type; section->flags = xkb_file->flags; if (xkb_file->name) { darray_size_t idx = darray_size(section->buffer); darray_append_string0(section->buffer, xkb_file->name); section->name = idx; } else { section->name = 0; } return true; } /** Process a list of include statements */ static bool xkb_file_section_append_includes(struct xkb_context *ctx, enum xkb_file_iterator_flags flags, const char *section_path, struct xkb_file_section *section, enum xkb_file_type file_type, IncludeStmt * include) { struct xkb_file_include_group *group = NULL; /* Note: this will flatten statements such as `include "pc+de"` */ for (IncludeStmt *stmt = include; stmt; stmt = stmt->next_incl) { char buf[PATH_MAX]; /* Parse the included file to check the include validity */ XkbFile *xkb_file = ProcessIncludeFile(ctx, stmt, file_type, buf, sizeof(buf)); const bool valid = (xkb_file != NULL); if (valid || !(flags & XKB_FILE_ITERATOR_FAIL_ON_INCLUDE_ERROR)) { /* Collect the strings of the statement properties */ const darray_size_t path = darray_size(section->buffer); darray_append_string0(section->buffer, buf); const darray_size_t file = darray_size(section->buffer); darray_append_string0(section->buffer, stmt->file); const darray_size_t section_name = (stmt->map != NULL || (valid && xkb_file->name)) ? darray_size(section->buffer) : 0; if (section_name) { darray_append_string0(section->buffer, (stmt->map) ? stmt->map : xkb_file->name); } const darray_size_t modifier = (stmt->modifier) ? darray_size(section->buffer) : 0; if (modifier) { darray_append_string0(section->buffer, stmt->modifier); } const enum xkb_map_flags section_flags = (valid) ? xkb_file->flags : 0; /* Create and append the include statement */ const struct xkb_file_include inc = { .valid = valid, .explicit_section = (stmt->map != NULL), .merge = stmt->merge, .path = path, .file = file, .section = section_name, .modifier = modifier, .flags = section_flags }; const darray_size_t idx = darray_size(section->includes); darray_append(section->includes, inc); /* Update include group */ if (group == NULL) { const darray_size_t group_idx = darray_size(section->include_groups); darray_append( section->include_groups, (struct xkb_file_include_group) {.start = idx, .end = idx} ); group = &darray_item(section->include_groups, group_idx); } else { group->end = idx; } FreeXkbFile(xkb_file); } else { const char * const name = xkb_file_section_get_string(section, section->name); log_err(ctx, XKB_ERROR_INCLUDED_FILE_NOT_FOUND, "%s include failure in: %s%s%s%s\n", xkb_file_type_name(file_type), section_path, (section->name ? " (section: \"": ""), name, (section->name ? "\")": "")); FreeXkbFile(xkb_file); return false; } }; return true; } /* Process the AST of a section */ static bool xkb_file_section_process(struct xkb_context *ctx, enum xkb_file_iterator_flags flags, const char *path, struct xkb_file_section *section, const XkbFile *xkb_file) { bool ok = true; for (ParseCommon *stmt = xkb_file->defs; stmt; stmt = stmt->next) { if (stmt->type == STMT_INCLUDE) { ok = xkb_file_section_append_includes(ctx, flags, path, section, xkb_file->file_type, (IncludeStmt *) stmt); if (!ok) break; } } return ok; } bool xkb_file_section_parse(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum xkb_keymap_format format, enum xkb_keymap_compile_flags compile_flags, unsigned int include_depth, const char *path, const char *map, struct xkb_file_section *section) { if (ExceedsIncludeMaxDepth(ctx, include_depth)) return false; FILE *file = fopen(path, "rb"); if (!file) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Cannot open file: %s\n", path); return false; } XkbFile *xkb_file = XkbParseFile(ctx, file, path, map); fclose(file); if (!xkb_file) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Cannot parse map \"%s\" in file: %s\n", (map ? map : "(no map)"), path); return false; } xkb_file_section_reset(section); const bool no_includes = iterator_flags & XKB_FILE_ITERATOR_NO_INCLUDES; const bool ok = ( xkb_file_section_set_meta_data(ctx, section, xkb_file) && (no_includes || xkb_file_section_process(ctx, iterator_flags, path, section, xkb_file)) ); FreeXkbFile(xkb_file); return ok; } struct xkb_file_iterator * xkb_file_iterator_new_from_buffer(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum xkb_keymap_format format, enum xkb_keymap_compile_flags compile_flags, const char *path, const char *map, enum xkb_file_type file_type, const char *string, size_t length) { struct xkb_file_iterator * const iter = calloc(1, sizeof(*iter)); if (!iter) { log_err(ctx, XKB_ERROR_ALLOCATION_ERROR, "Cannot allocate file iterator\n"); return NULL; } iter->flags = iterator_flags; iter->ctx = ctx; iter->path = path; iter->map = map; iter->type = file_type; xkb_file_section_init(&iter->section); if (!XkbParseStringInit(ctx, &iter->scanner, string, length, path, NULL)) { xkb_file_iterator_free(iter); return NULL; } return iter; } void xkb_file_iterator_free(struct xkb_file_iterator *iter) { if (!iter) return; xkb_file_section_free(&iter->section); FreeXkbFile(iter->pending_xkb_file); free(iter); } bool xkb_file_iterator_next(struct xkb_file_iterator *iter, const struct xkb_file_section **section) { if (iter->finished) { *section = NULL; return true; } next: { /* C11 compatibility: label cannot be followed by a declaration */ } /* Parse next section in the file */ XkbFile *xkb_file = NULL; if (iter->pending_xkb_file) { /* We are parsing the components of a keymap */ if (iter->pending_section) { /* Parse next component */ xkb_file = iter->pending_section; goto parse_components; } else { /* No more components, try next keymap */ FreeXkbFile(iter->pending_xkb_file); iter->pending_xkb_file = NULL; } } if (!XkbParseStringNext(iter->ctx, &iter->scanner, iter->map, &xkb_file)) { log_err(iter->ctx, XKB_LOG_MESSAGE_NO_ID, "Error while parsing section in file: %s\n", iter->path); goto error; } else if (!xkb_file) { /* No more sections */ iter->finished = true; *section = NULL; return true; } parse_components: /* Reset section */ xkb_file_section_reset(&iter->section); /* Meta data */ if (!xkb_file_section_set_meta_data(iter->ctx, &iter->section, xkb_file)) goto error; /* Return current section */ *section = &iter->section; if (xkb_file->file_type == FILE_TYPE_KEYMAP) { /* * If it’s a keymap, then stop here. * Next iteration will process its components. */ iter->pending_xkb_file = xkb_file; iter->pending_section = (XkbFile *) xkb_file->defs; iter->map = NULL; return true; } else { if (iter->type != FILE_TYPE_INVALID && xkb_file->file_type != iter->type) { if (iter->pending_xkb_file) { /* Within a keymap: filter out component */ iter->pending_section = (XkbFile *) xkb_file->common.next; goto next; } else { /* Component-specific file: type mismatch */ log_err(iter->ctx, XKB_LOG_MESSAGE_NO_ID, "File type mismatch: %s, section: %s\n", iter->path, (xkb_file->name ? xkb_file->name : "(no name)")); goto error; } } if (iter->map) { iter->finished = true; } } /* Collect include statements of current section */ const bool process_includes = !(iter->flags & XKB_FILE_ITERATOR_NO_INCLUDES); if (process_includes && !xkb_file_section_process(iter->ctx, iter->flags, iter->path, &iter->section, xkb_file)) { goto error; } else if (iter->pending_section) { /* Next component */ iter->pending_section = (XkbFile *) xkb_file->common.next; } else { /* No more component, free the file containing the components */ FreeXkbFile(xkb_file); } return true; error: FreeXkbFile(xkb_file); *section = NULL; return false; } /* Lookup a string by its index */ const char * xkb_file_section_get_string(const struct xkb_file_section *section, darray_size_t idx) { return &darray_item(section->buffer, idx); } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/keymap-file-iterator.h000066400000000000000000000127131510033435100253240ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include "xkbcommon/xkbcommon.h" #include "src/darray.h" #include "src/scanner-utils.h" #include "src/utils.h" #include "ast.h" XKB_EXPORT_PRIVATE const char * xkb_file_type_name(enum xkb_file_type type); XKB_EXPORT_PRIVATE const char * xkb_merge_mode_name(enum merge_mode type); XKB_EXPORT_PRIVATE const char * xkb_map_flags_string_iter(unsigned int *index, enum xkb_map_flags flags); XKB_EXPORT_PRIVATE FILE * xkb_resolve_file(struct xkb_context *ctx, enum xkb_file_type file_type, const char *path, const char *map, char *resolved_path, size_t resolved_path_size, char *resolved_map, size_t resolved_map_size); /** An atomic include entry */ struct xkb_file_include { bool valid:1; bool explicit_section:1; enum merge_mode merge; /* * The following are indices from `xkb_file_section::buffer` * * Use `xkb_file_section_get_string()` to retrieve them. */ darray_size_t path; darray_size_t file; darray_size_t section; darray_size_t modifier; /* Flags of the included section, only set if valid = true */ enum xkb_map_flags flags; }; struct xkb_file_include_group { darray_size_t start; darray_size_t end; }; /** A file section: `xkb_{keycodes,compat,geometry,symbols,types} */ struct xkb_file_section { darray_size_t name; enum xkb_file_type file_type; enum xkb_map_flags flags; darray(struct xkb_file_include_group) include_groups; darray(struct xkb_file_include) includes; /** * Char array to store all the strings * * Use `xkb_file_section_get_string()` to retrieve them. */ darray_char buffer; }; XKB_EXPORT_PRIVATE void xkb_file_section_init(struct xkb_file_section *section); XKB_EXPORT_PRIVATE void xkb_file_section_free(struct xkb_file_section *section); enum xkb_file_iterator_flags { XKB_FILE_ITERATOR_NO_FLAG = 0, /** Include errors are fatal */ XKB_FILE_ITERATOR_FAIL_ON_INCLUDE_ERROR = (1 << 0), /** Do not list includes */ XKB_FILE_ITERATOR_NO_INCLUDES = (1 << 1) }; /** * Parse a single keymap file section * * @param[in] ctx The XKB context * @param[in] iterator_flags The flags used to parse the section * @param[in] format The keymap format used to parse the keymap file * @param[in] compile_flags The flags used to parse the keymap file * @param[in] path The path of the keymap file to parse * @param[in] map The name of a specific section in the file * @param[inout] section The resulting section * * @returns `true` on success, else `false` */ XKB_EXPORT_PRIVATE bool xkb_file_section_parse(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum xkb_keymap_format format, enum xkb_keymap_compile_flags compile_flags, unsigned int include_depth, const char *path, const char *map, struct xkb_file_section *section); XKB_EXPORT_PRIVATE const char * xkb_file_section_get_string(const struct xkb_file_section *section, darray_size_t idx); /** Iterator over the sections of a keymap file */ struct xkb_file_iterator { enum xkb_file_iterator_flags flags; bool finished; /** File to analyze */ const char *path; /** Section to analyze; if NULL then iter over all the sections */ const char *map; /** File type to check/filter */ enum xkb_file_type type; /** Scanner of the keymap file */ struct scanner scanner; /** Current section */ struct xkb_file_section section; /** Pending XKB file */ XkbFile *pending_xkb_file; /** Pending component of the XKB file */ XkbFile *pending_section; struct xkb_context *ctx; }; /** * Create a keymap file section iterator from a buffer * * @param ctx The XKB context * @param iterator_flags The flags used to parse the section * @param format The keymap format used to parse the keymap file * @param compile_flags The flags used to parse the keymap file * @param path The path of the keymap file parsed (informative) * @param map The name of a specific section in the file, else NULL * to iterate over all the sections of the file. * @param file_type If the input is a keymap, iterate only over the * corresponding component; else check that the parsed file type matches. * @param string The buffer to parse * @param length The length of the buffer to parse * * @returns A `malloc`ed file iterator on success, else `NULL`. */ XKB_EXPORT_PRIVATE struct xkb_file_iterator * xkb_file_iterator_new_from_buffer(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum xkb_keymap_format format, enum xkb_keymap_compile_flags compile_flags, const char *path, const char *map, enum xkb_file_type file_type, const char *string, size_t length); XKB_EXPORT_PRIVATE void xkb_file_iterator_free(struct xkb_file_iterator *iter); XKB_EXPORT_PRIVATE bool xkb_file_iterator_next(struct xkb_file_iterator *iter, const struct xkb_file_section **section); xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/keymap.c000066400000000000000000000565761510033435100225720ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT * * Author: Dan Nicholson * Author: Daniel Stone * Author: Ran Benita */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "darray.h" #include "keymap.h" #include "text.h" #include "utils.h" #include "xkbcomp-priv.h" static bool has_unbound_vmods(struct xkb_keymap *keymap, xkb_mod_mask_t mask) { xkb_mod_index_t k; struct xkb_mod *mod; xkb_vmods_enumerate(k, mod, &keymap->mods) if ((mask & (UINT32_C(1) << k)) && mod->mapping == 0) return true; return false; } static inline void ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods) { /* * Since we accept numeric values for the vmod mask in the keymap, we may * have extra bits set that encode no real/virtual modifier. Keep them * unchanged for consistency. */ const xkb_mod_mask_t unknown_mods = ~(xkb_mod_mask_t) ((UINT64_C(1) << keymap->mods.num_mods) - UINT64_C(1)); mods->mask = mod_mask_get_effective(keymap, mods->mods) | (mods->mods & unknown_mods); } static void UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act, xkb_mod_mask_t modmap) { switch (act->type) { case ACTION_TYPE_MOD_SET: case ACTION_TYPE_MOD_LATCH: case ACTION_TYPE_MOD_LOCK: if (act->mods.flags & ACTION_MODS_LOOKUP_MODMAP) act->mods.mods.mods = modmap; ComputeEffectiveMask(keymap, &act->mods.mods); break; default: break; } } const struct xkb_sym_interpret default_interpret = { /* Keysym unused for when applying interpretation, but used as a default * entry when dumping the keymap */ .sym = XKB_KEY_VoidSymbol, .repeat = true, .match = MATCH_ANY_OR_NONE, .mods = 0, .virtual_mod = XKB_MOD_INVALID, .num_actions = 0, .a = { .action = { .type = ACTION_TYPE_NONE } }, }; typedef darray(const struct xkb_sym_interpret*) xkb_sym_interprets; /** * Find an interpretation which applies to this particular level, either by * finding an exact match for the symbol and modifier combination, or a * generic XKB_KEY_NoSymbol match. */ static bool FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key, xkb_layout_index_t group, xkb_level_index_t level, xkb_sym_interprets *interprets) { const xkb_keysym_t *syms; int num_syms; num_syms = xkb_keymap_key_get_syms_by_level(keymap, key->keycode, group, level, &syms); if (num_syms <= 0) return false; /* * There may be multiple matchings interprets; we should always return * the most specific. Here we rely on compat.c to set up the * sym_interprets array from the most specific to the least specific, * such that when we find a match we return immediately. */ for (int s = 0; s < num_syms; s++) { bool found = false; for (darray_size_t i = 0; i < keymap->num_sym_interprets; i++) { struct xkb_sym_interpret * const interp = &keymap->sym_interprets[i]; xkb_mod_mask_t mods; found = false; if (interp->sym != syms[s] && interp->sym != XKB_KEY_NoSymbol) continue; if (interp->level_one_only && level != 0) mods = 0; else mods = key->modmap; switch (interp->match) { case MATCH_NONE: found = !(interp->mods & mods); break; case MATCH_ANY_OR_NONE: found = (!mods || (interp->mods & mods)); break; case MATCH_ANY: found = (interp->mods & mods); break; case MATCH_ALL: found = ((interp->mods & mods) == interp->mods); break; case MATCH_EXACTLY: found = (interp->mods == mods); break; } if (found && i > 0 && interp->sym == XKB_KEY_NoSymbol) { /* * For an interpretation matching Any keysym, we may get the * same interpretation for multiple keysyms. This may result in * unwanted duplicate actions. So set this interpretation only * if no previous keysym was matched with this interpret at this * level, else set the default interpretation. */ struct xkb_sym_interpret const **previous_interp; darray_foreach(previous_interp, *interprets) { if (*previous_interp == interp) { /* Keep as a safeguard against refactoring * NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores) */ found = false; log_warn(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Repeated interpretation ignored for keysym " "#%d \"%s\" at level %"PRIu32"/group %"PRIu32" " "on key %s.\n", s + 1, KeysymText(keymap->ctx, syms[s]), level + 1, group + 1, KeyNameText(keymap->ctx, key->name)); goto not_found; } } } if (found) { darray_append(*interprets, interp); interp->required = true; break; } } if (!found) not_found: darray_append(*interprets, &default_interpret); } return true; } static bool ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key) { xkb_mod_mask_t vmodmap = 0; xkb_level_index_t level; // FIXME: do not use darray, add actions directly in FindInterpForKey xkb_sym_interprets interprets = darray_new(); darray(union xkb_action) actions = darray_new(); for (xkb_layout_index_t group = 0; group < key->num_groups; group++) { /* Skip any interpretation for this group if it has explicit actions */ if (key->groups[group].explicit_actions) continue; for (level = 0; level < XkbKeyNumLevels(key, group); level++) { assert(key->groups[group].levels[level].num_actions == 0); const struct xkb_sym_interpret **interp_iter; const struct xkb_sym_interpret *interp; size_t k; darray_resize(interprets, 0); const bool found = FindInterpForKey(keymap, key, group, level, &interprets); if (!found) continue; darray_enumerate(k, interp_iter, interprets) { interp = *interp_iter; /* Infer default key behaviours from the base level. */ if (group == 0 && level == 0) if (!(key->explicit & EXPLICIT_REPEAT) && interp->repeat) key->repeats = true; if ((group == 0 && level == 0) || !interp->level_one_only) if (interp->virtual_mod != XKB_MOD_INVALID) vmodmap |= (UINT32_C(1) << interp->virtual_mod); switch (interp->num_actions) { case 0: break; case 1: darray_append(actions, interp->a.action); break; default: darray_append_items(actions, interp->a.actions, interp->num_actions); } } /* Copy the actions */ if (unlikely(darray_size(actions)) > MAX_ACTIONS_PER_LEVEL) { log_warn(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Could not append interpret actions to key %s: " "maximum is %u, got: %u. Dropping excessive actions\n", KeyNameText(keymap->ctx, key->name), MAX_ACTIONS_PER_LEVEL, darray_size(actions)); key->groups[group].levels[level].num_actions = MAX_ACTIONS_PER_LEVEL; } else { key->groups[group].levels[level].num_actions = (xkb_action_count_t) darray_size(actions); } switch (darray_size(actions)) { case 0: key->groups[group].levels[level].a.action = (union xkb_action) { .type = ACTION_TYPE_NONE }; break; case 1: key->groups[group].levels[level].a.action = darray_item(actions, 0); break; default: key->groups[group].levels[level].a.actions = memdup(darray_items(actions), key->groups[group].levels[level].num_actions, sizeof(*darray_items(actions))); if (!key->groups[group].levels[level].a.actions) { log_err(keymap->ctx, XKB_ERROR_ALLOCATION_ERROR, "Could not allocate interpret actions\n"); darray_free(actions); darray_free(interprets); return false; } } /* Do not free here */ darray_resize(actions, 0); } } darray_free(actions); darray_free(interprets); if (!(key->explicit & EXPLICIT_VMODMAP)) key->vmodmap = vmodmap; return true; } static inline bool is_mod_action(union xkb_action *action) { return action->type == ACTION_TYPE_MOD_SET || action->type == ACTION_TYPE_MOD_LATCH || action->type == ACTION_TYPE_MOD_LOCK; } static inline bool is_group_action(union xkb_action *action) { return action->type == ACTION_TYPE_GROUP_SET || action->type == ACTION_TYPE_GROUP_LATCH || action->type == ACTION_TYPE_GROUP_LOCK; } /* Check for mixing actions of the same category. * We do not support that yet, because it needs a careful refactor of the state * handling. See: `xkb_filter_apply_all`. */ static void CheckMultipleActionsCategories(struct xkb_keymap *keymap, struct xkb_key *key) { for (xkb_layout_index_t g = 0; g < key->num_groups; g++) { for (xkb_level_index_t l = 0; l < XkbKeyNumLevels(key, g); l++) { struct xkb_level *level = &key->groups[g].levels[l]; if (level->num_actions <= 1) continue; for (xkb_action_count_t i = 0; i < level->num_actions; i++) { union xkb_action *action1 = &level->a.actions[i]; bool mod_action = is_mod_action(action1); bool group_action = is_group_action(action1); if (!(mod_action || group_action)) continue; for (xkb_action_count_t j = i + 1; j < level->num_actions; j++) { union xkb_action *action2 = &level->a.actions[j]; if ((mod_action && is_mod_action(action2)) || (group_action && is_group_action(action2))) { log_err(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Cannot use multiple %s actions " "in the same level. Action #%u " "for key %s in group %"PRIu32"/level %"PRIu32" " "ignored.\n", (mod_action ? "modifiers" : "group"), j + 1, KeyNameText(keymap->ctx, key->name), g + 1, l + 1); action2->type = ACTION_TYPE_NONE; } } } } } } static void add_key_aliases(struct xkb_keymap *keymap, darray_size_t min, darray_size_t max, struct xkb_key_alias *aliases) { darray_size_t num_key_aliases = 0; for (darray_size_t alias = min; alias <= max; alias++) { const KeycodeMatch entry = keymap->key_names[alias]; if (entry.is_alias && entry.found) { aliases[num_key_aliases++] = (struct xkb_key_alias) { .alias = alias, .real = entry.alias.real }; } } } /** * This collects a bunch of disparate functions which was done in the server * at various points that really should've been done within xkbcomp. Turns out * your actions and types are a lot more useful when any of your modifiers * other than Shift actually do something ... */ static bool UpdateDerivedKeymapFields(struct xkb_keymap *keymap) { /** * Create the key alias list * * Since we already allocated the key name LUT, we try to overwrite it: * - An alias entry is exactly 2× the size of a LUT entry (on most compilers). * - We ensure that there is a real key for each alias. * - So, if each alias maps to a different keycode, we usually have: * current alloc(keymap.key_names) ≥ needed alloc(keymap.key_aliases). * - Usual keymaps have enough space in the LUT to enable overwriting real * key entries without overlap with the alias entries. * - In the unlikely event that this is not the case, we need to realloc. */ #ifdef _WIN32 /* Bit fields are not packed on Windows as efficiently as other platforms */ static_assert(sizeof(struct xkb_key_alias) == sizeof(KeycodeMatch), ""); #else static_assert(sizeof(struct xkb_key_alias) == 2 * sizeof(KeycodeMatch), ""); #endif darray_size_t num_key_aliases = 0; darray_size_t min_alias = DARRAY_SIZE_MAX; darray_size_t max_alias = 0; for (xkb_atom_t alias = 0; alias < keymap->num_key_names; alias++) { const KeycodeMatch entry = keymap->key_names[alias]; if (entry.is_alias && entry.found) { num_key_aliases++; if (min_alias == DARRAY_SIZE_MAX) min_alias = alias; max_alias = alias; } } if (num_key_aliases) { /* * No fancy algorithm used here: either we can trivially write the whole * range of `xkb_key_aliases` without overlapping with the `KeycodeMatch` * alias entries or we allocate a new array. * In practice no new allocation is is needed and it delivers performs * better than using a buffer to handle overlaps. */ const darray_size_t required_space = sizeof(struct xkb_key_alias) / sizeof(KeycodeMatch) * num_key_aliases; if (min_alias >= required_space) { /* Overwrite before the *first* alias entry */ add_key_aliases(keymap, min_alias, max_alias, keymap->key_aliases); /* Shrink */ struct xkb_key_alias * const r = realloc(keymap->key_aliases, num_key_aliases * sizeof(*keymap->key_aliases)); if (r == NULL) return false; keymap->key_aliases = r; } else if (keymap->num_key_names - max_alias - 1 > required_space) { /* Overwrite after the *last* alias entry, then move to the start */ struct xkb_key_alias * const aliases = (struct xkb_key_alias *) ( keymap->key_names - required_space - !is_aligned(keymap->key_names - required_space, sizeof(struct xkb_key_alias)) ); add_key_aliases(keymap, min_alias, max_alias, aliases); memcpy(keymap->key_aliases, aliases, num_key_aliases * sizeof(*aliases)); /* Shrink */ struct xkb_key_alias * const r = realloc(keymap->key_aliases, num_key_aliases * sizeof(*keymap->key_aliases)); if (r == NULL) return false; keymap->key_aliases = r; } else { /* * No space trivially available: instead of processing the LUT with * a buffer to handle overlaps, we simply allocate a dedicated array */ struct xkb_key_alias * const aliases = calloc(num_key_aliases, sizeof(*aliases)); if (aliases == NULL) return false; add_key_aliases(keymap, min_alias, max_alias, aliases); free(keymap->key_names); keymap->key_aliases = aliases; } } keymap->num_key_aliases = num_key_aliases; /* Find all the interprets for the key and bind them to actions, * which will also update the vmodmap. */ struct xkb_key *key; xkb_keys_foreach(key, keymap) { if (!ApplyInterpsToKey(keymap, key)) return false; CheckMultipleActionsCategories(keymap, key); } /* Update keymap->mods, the virtual -> real mod mapping. */ xkb_mod_index_t idx; struct xkb_mod *mod; xkb_keys_foreach(key, keymap) xkb_vmods_enumerate(idx, mod, &keymap->mods) if (key->vmodmap & (UINT32_C(1) << idx)) mod->mapping |= key->modmap; if (keymap->format >= XKB_KEYMAP_FORMAT_TEXT_V2) { /* * XKB extension: canonical virtual modifiers (incompatible with X11) * * Virtual modifiers that are not mapped, map to their canonical * encoding, i.e. themselves. * * This excludes: * - Modifiers mapped *explicitly*: e.g. `virtual_modifiers M = 0x1;`. * - Modifiers mapped *implicitly* via vmodmap/modifier_map, i.e. the * usual X11 way used in xkeyboard-config. */ xkb_vmods_enumerate(idx, mod, &keymap->mods) { const xkb_mod_mask_t mask = UINT32_C(1) << idx; if (mod->mapping == 0 && !(keymap->mods.explicit_vmods & mask)) { mod->mapping = mask; /* * Make the mapping explicit, so that it is interoperable * without relying on the implementation-specific virtual * modifiers indices. */ keymap->mods.explicit_vmods |= mask; } } } /* Update the canonical modifiers state mask */ assert(keymap->canonical_state_mask == MOD_REAL_MASK_ALL); xkb_mod_mask_t extra_canonical_mods = 0; xkb_vmods_enumerate(idx, mod, &keymap->mods) { extra_canonical_mods |= mod->mapping; } keymap->canonical_state_mask |= extra_canonical_mods; /* Now update the level masks for all the types to reflect the vmods. */ for (darray_size_t i = 0; i < keymap->num_types; i++) { ComputeEffectiveMask(keymap, &keymap->types[i].mods); for (darray_size_t j = 0; j < keymap->types[i].num_entries; j++) { if (has_unbound_vmods(keymap, keymap->types[i].entries[j].mods.mods)) { /* * Map entries which specify unbound virtual modifiers are not * considered (see the XKB protocol, section “Determining the * KeySym Associated with a Key Event”). * * Deactivate entry by zeroing its mod mask and skipping further * processing. * * See also: `entry_is_active`. */ keymap->types[i].entries[j].mods.mask = 0; continue; } ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].mods); ComputeEffectiveMask(keymap, &keymap->types[i].entries[j].preserve); } } /* Update action modifiers. */ xkb_keys_foreach(key, keymap) { for (xkb_layout_index_t i = 0; i < key->num_groups; i++) { for (xkb_level_index_t j = 0; j < XkbKeyNumLevels(key, i); j++) { if (key->groups[i].levels[j].num_actions == 1) { UpdateActionMods(keymap, &key->groups[i].levels[j].a.action, key->modmap); } else { for (xkb_action_count_t k = 0; k < key->groups[i].levels[j].num_actions; k++) { UpdateActionMods(keymap, &key->groups[i].levels[j].a.actions[k], key->modmap); } } } } } /* Update vmod -> led maps. */ struct xkb_led *led; xkb_leds_foreach(led, keymap) ComputeEffectiveMask(keymap, &led->mods); /* Find maximum number of groups out of all keys in the keymap. */ xkb_keys_foreach(key, keymap) keymap->num_groups = MAX(keymap->num_groups, key->num_groups); return true; } typedef bool (*compile_file_fn)(XkbFile *file, struct xkb_keymap *keymap); static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = { [FILE_TYPE_KEYCODES] = CompileKeycodes, [FILE_TYPE_TYPES] = CompileKeyTypes, [FILE_TYPE_COMPAT] = CompileCompatMap, [FILE_TYPE_SYMBOLS] = CompileSymbols, }; bool CompileKeymap(XkbFile *file, struct xkb_keymap *keymap) { XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL }; enum xkb_file_type type; struct xkb_context *ctx = keymap->ctx; /* Collect section files and check for duplicates. */ for (file = (XkbFile *) file->defs; file; file = (XkbFile *) file->common.next) { if (file->file_type < FIRST_KEYMAP_FILE_TYPE || file->file_type > LAST_KEYMAP_FILE_TYPE) { if (file->file_type == FILE_TYPE_GEOMETRY) { log_vrb(ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_UNSUPPORTED_GEOMETRY_SECTION, "Geometry sections are not supported; ignoring\n"); } else { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Cannot define %s in a keymap file\n", xkb_file_type_to_string(file->file_type)); } continue; } if (files[file->file_type]) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "More than one %s section in keymap file; " "All sections after the first ignored\n", xkb_file_type_to_string(file->file_type)); continue; } files[file->file_type] = file; } /* * Compile sections * * NOTE: Any component is optional. */ for (type = FIRST_KEYMAP_FILE_TYPE; type <= LAST_KEYMAP_FILE_TYPE; type++) { if (files[type] == NULL) { log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "Component %s not provided in keymap\n", xkb_file_type_to_string(type)); } else { log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "Compiling %s \"%s\"\n", xkb_file_type_to_string(type), safe_map_name(files[type])); } /* Missing components are initialized with defaults */ const bool ok = compile_file_fns[type](files[type], keymap); if (!ok) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Failed to compile %s\n", xkb_file_type_to_string(type)); return false; } } return UpdateDerivedKeymapFields(keymap); } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/keywords.c000066400000000000000000000401401510033435100231270ustar00rootroot00000000000000/* ANSI-C code produced by gperf version 3.1 */ /* Command-line: gperf src/xkbcomp/keywords.gperf */ /* Computed positions: -k'1-2,5' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) /* The character set is not based on ISO-646. */ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif #line 1 "src/xkbcomp/keywords.gperf" #include "config.h" #include "xkbcomp-priv.h" #include "parser-priv.h" static const struct keyword_tok * keyword_gperf_lookup (register const char *str, register size_t len); #line 11 "src/xkbcomp/keywords.gperf" struct keyword_tok { int name; int tok; }; #include /* maximum key range = 70, duplicates = 0 */ #ifndef GPERF_DOWNCASE #define GPERF_DOWNCASE 1 static unsigned char gperf_downcase[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 }; #endif #ifndef GPERF_CASE_MEMCMP #define GPERF_CASE_MEMCMP 1 static int gperf_case_memcmp (register const char *s1, register const char *s2, register size_t n) { for (; n > 0;) { unsigned char c1 = gperf_downcase[(unsigned char)*s1++]; unsigned char c2 = gperf_downcase[(unsigned char)*s2++]; if (c1 == c2) { n--; continue; } return (int)c1 - (int)c2; } return 0; } #endif #ifdef __GNUC__ __inline #else #ifdef __cplusplus inline #endif #endif static unsigned int keyword_gperf_hash (register const char *str, register size_t len) { static const unsigned char asso_values[] = { 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 0, 73, 5, 36, 0, 10, 1, 15, 15, 73, 0, 10, 20, 35, 20, 50, 73, 10, 10, 5, 0, 15, 73, 0, 15, 73, 73, 73, 73, 73, 73, 73, 0, 73, 5, 36, 0, 10, 1, 15, 15, 73, 0, 10, 20, 35, 20, 50, 73, 10, 10, 5, 0, 15, 73, 0, 15, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73 }; register unsigned int hval = (unsigned int) len; switch (hval) { default: hval += asso_values[(unsigned char)str[4]]; /*FALLTHROUGH*/ case 4: case 3: case 2: hval += asso_values[(unsigned char)str[1]]; /*FALLTHROUGH*/ case 1: hval += asso_values[(unsigned char)str[0]]; break; } return hval; } struct stringpool_t { char stringpool_str3[sizeof("key")]; char stringpool_str4[sizeof("keys")]; char stringpool_str7[sizeof("augment")]; char stringpool_str9[sizeof("text")]; char stringpool_str10[sizeof("xkb_keymap")]; char stringpool_str11[sizeof("keypad_keys")]; char stringpool_str12[sizeof("xkb_keycodes")]; char stringpool_str13[sizeof("xkb_geometry")]; char stringpool_str14[sizeof("xkb_types")]; char stringpool_str15[sizeof("xkb_compat")]; char stringpool_str17[sizeof("replace")]; char stringpool_str19[sizeof("xkb_compat_map")]; char stringpool_str20[sizeof("xkb_layout")]; char stringpool_str21[sizeof("xkb_symbols")]; char stringpool_str22[sizeof("xkb_compatibility")]; char stringpool_str23[sizeof("xkb_semantics")]; char stringpool_str24[sizeof("type")]; char stringpool_str25[sizeof("alias")]; char stringpool_str26[sizeof("xkb_compatibility_map")]; char stringpool_str27[sizeof("alphanumeric_keys")]; char stringpool_str28[sizeof("function_keys")]; char stringpool_str29[sizeof("alternate")]; char stringpool_str30[sizeof("shape")]; char stringpool_str31[sizeof("action")]; char stringpool_str32[sizeof("section")]; char stringpool_str33[sizeof("row")]; char stringpool_str34[sizeof("logo")]; char stringpool_str35[sizeof("alternate_group")]; char stringpool_str36[sizeof("hidden")]; char stringpool_str37[sizeof("virtual")]; char stringpool_str42[sizeof("outline")]; char stringpool_str43[sizeof("default")]; char stringpool_str46[sizeof("modmap")]; char stringpool_str47[sizeof("virtual_modifiers")]; char stringpool_str52[sizeof("overlay")]; char stringpool_str53[sizeof("override")]; char stringpool_str57[sizeof("include")]; char stringpool_str62[sizeof("modifier_map")]; char stringpool_str63[sizeof("modifier_keys")]; char stringpool_str64[sizeof("indicator")]; char stringpool_str66[sizeof("group")]; char stringpool_str67[sizeof("mod_map")]; char stringpool_str69[sizeof("interpret")]; char stringpool_str71[sizeof("solid")]; char stringpool_str72[sizeof("partial")]; }; static const struct stringpool_t stringpool_contents = { "key", "keys", "augment", "text", "xkb_keymap", "keypad_keys", "xkb_keycodes", "xkb_geometry", "xkb_types", "xkb_compat", "replace", "xkb_compat_map", "xkb_layout", "xkb_symbols", "xkb_compatibility", "xkb_semantics", "type", "alias", "xkb_compatibility_map", "alphanumeric_keys", "function_keys", "alternate", "shape", "action", "section", "row", "logo", "alternate_group", "hidden", "virtual", "outline", "default", "modmap", "virtual_modifiers", "overlay", "override", "include", "modifier_map", "modifier_keys", "indicator", "group", "mod_map", "interpret", "solid", "partial" }; #define stringpool ((const char *) &stringpool_contents) const struct keyword_tok * keyword_gperf_lookup (register const char *str, register size_t len) { enum { TOTAL_KEYWORDS = 45, MIN_WORD_LENGTH = 3, MAX_WORD_LENGTH = 21, MIN_HASH_VALUE = 3, MAX_HASH_VALUE = 72 }; static const unsigned char lengthtable[] = { 0, 0, 0, 3, 4, 0, 0, 7, 0, 4, 10, 11, 12, 12, 9, 10, 0, 7, 0, 14, 10, 11, 17, 13, 4, 5, 21, 17, 13, 9, 5, 6, 7, 3, 4, 15, 6, 7, 0, 0, 0, 0, 7, 7, 0, 0, 6, 17, 0, 0, 0, 0, 7, 8, 0, 0, 0, 7, 0, 0, 0, 0, 12, 13, 9, 0, 5, 7, 0, 9, 0, 5, 7 }; static const struct keyword_tok wordlist[] = { {-1}, {-1}, {-1}, #line 38 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str3, KEY}, #line 39 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str4, KEYS}, {-1}, {-1}, #line 29 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str7, AUGMENT}, {-1}, #line 54 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str9, TEXT}, #line 64 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str10, XKB_KEYMAP}, #line 37 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str11, KEYPAD_KEYS}, #line 63 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str12, XKB_KEYCODES}, #line 62 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, XKB_GEOMETRY}, #line 68 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, XKB_TYPES}, #line 61 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15, XKB_COMPATMAP}, {-1}, #line 49 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17, REPLACE}, {-1}, #line 60 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, XKB_COMPATMAP}, #line 65 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20, XKB_LAYOUT}, #line 67 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, XKB_SYMBOLS}, #line 59 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, XKB_COMPATMAP}, #line 66 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str23, XKB_SEMANTICS}, #line 55 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24, TYPE}, #line 25 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25, ALIAS}, #line 58 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, XKB_COMPATMAP}, #line 26 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str27, ALPHANUMERIC_KEYS}, #line 31 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, FUNCTION_KEYS}, #line 28 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, ALTERNATE}, #line 52 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, SHAPE}, #line 24 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, ACTION_TOK}, #line 51 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32, SECTION}, #line 50 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, ROW}, #line 40 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str34, LOGO}, #line 27 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, ALTERNATE_GROUP}, #line 33 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, HIDDEN}, #line 57 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, VIRTUAL}, {-1}, {-1}, {-1}, {-1}, #line 45 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42, OUTLINE}, #line 30 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43, DEFAULT}, {-1}, {-1}, #line 44 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46, MODIFIER_MAP}, #line 56 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, VIRTUAL_MODS}, {-1}, {-1}, {-1}, {-1}, #line 46 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, OVERLAY}, #line 47 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53, OVERRIDE}, {-1}, {-1}, {-1}, #line 34 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57, INCLUDE}, {-1}, {-1}, {-1}, {-1}, #line 42 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, MODIFIER_MAP}, #line 41 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, MODIFIER_KEYS}, #line 35 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, INDICATOR}, {-1}, #line 32 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66, GROUP}, #line 43 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67, MODIFIER_MAP}, {-1}, #line 36 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str69, INTERPRET}, {-1}, #line 53 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, SOLID}, #line 48 "src/xkbcomp/keywords.gperf" {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72, PARTIAL} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register unsigned int key = keyword_gperf_hash (str, len); if (key <= MAX_HASH_VALUE) if (len == lengthtable[key]) { register const char *s = wordlist[key].name + stringpool; if ((((unsigned char)*str ^ (unsigned char)*s) & ~32) == 0 && !gperf_case_memcmp (str, s, len)) return &wordlist[key]; } } return 0; } #line 69 "src/xkbcomp/keywords.gperf" int keyword_to_token(const char *string, size_t len) { const struct keyword_tok *kt = keyword_gperf_lookup(string, len); if (!kt) return -1; return kt->tok; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/keywords.gperf000066400000000000000000000041271510033435100240150ustar00rootroot00000000000000%{ #include "config.h" #include "xkbcomp-priv.h" #include "parser-priv.h" static const struct keyword_tok * keyword_gperf_lookup (register const char *str, register size_t len); %} struct keyword_tok { int name; int tok; }; %language=ANSI-C %define hash-function-name keyword_gperf_hash %define lookup-function-name keyword_gperf_lookup %readonly-tables %enum %includes %struct-type %pic %ignore-case %compare-lengths %% action, ACTION_TOK alias, ALIAS alphanumeric_keys, ALPHANUMERIC_KEYS alternate_group, ALTERNATE_GROUP alternate, ALTERNATE augment, AUGMENT default, DEFAULT function_keys, FUNCTION_KEYS group, GROUP hidden, HIDDEN include, INCLUDE indicator, INDICATOR interpret, INTERPRET keypad_keys, KEYPAD_KEYS key, KEY keys, KEYS logo, LOGO modifier_keys, MODIFIER_KEYS modifier_map, MODIFIER_MAP mod_map, MODIFIER_MAP modmap, MODIFIER_MAP outline, OUTLINE overlay, OVERLAY override, OVERRIDE partial, PARTIAL replace, REPLACE row, ROW section, SECTION shape, SHAPE solid, SOLID text, TEXT type, TYPE virtual_modifiers, VIRTUAL_MODS virtual, VIRTUAL xkb_compatibility_map, XKB_COMPATMAP xkb_compatibility, XKB_COMPATMAP xkb_compat_map, XKB_COMPATMAP xkb_compat, XKB_COMPATMAP xkb_geometry, XKB_GEOMETRY xkb_keycodes, XKB_KEYCODES xkb_keymap, XKB_KEYMAP xkb_layout, XKB_LAYOUT xkb_semantics, XKB_SEMANTICS xkb_symbols, XKB_SYMBOLS xkb_types, XKB_TYPES %% int keyword_to_token(const char *string, size_t len) { const struct keyword_tok *kt = keyword_gperf_lookup(string, len); if (!kt) return -1; return kt->tok; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/parser-priv.h000066400000000000000000000010321510033435100235340ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #pragma once #include "config.h" #include struct parser_param; struct scanner; #include "scanner-utils.h" #include "parser.h" int _xkbcommon_lex(YYSTYPE *yylval, struct scanner *scanner); XkbFile * parse(struct xkb_context *ctx, struct scanner *scanner, const char *map); bool parse_next(struct xkb_context *ctx, struct scanner *scanner, XkbFile **xkb_file); int keyword_to_token(const char *string, size_t len); xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/parser.y000066400000000000000000001257751510033435100226240ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ /* * The parser should work with reasonably recent versions of bison. * * byacc support was dropped, because it does not support the following features: * - `%define parse.error detailed` */ /* The following goes in the header */ %code requires { #include "config.h" #include "scanner-utils.h" #include "xkbcomp/ast.h" } %{ #include "config.h" #include #include "keysym.h" #include "xkbcomp/xkbcomp-priv.h" #include "xkbcomp/parser-priv.h" #include "xkbcomp/ast-build.h" struct parser_param { struct xkb_context *ctx; struct scanner *scanner; XkbFile *rtrn; bool more_maps; }; #define parser_err(param, error_id, fmt, ...) \ scanner_err((param)->scanner, error_id, fmt, ##__VA_ARGS__) #define parser_warn(param, warning_id, fmt, ...) \ scanner_warn((param)->scanner, warning_id, fmt, ##__VA_ARGS__) #define parser_vrb(param, verbosity, warning_id, fmt, ...) \ scanner_vrb((param)->scanner, verbosity, warning_id, fmt, ##__VA_ARGS__) static void _xkbcommon_error(struct parser_param *param, const char *msg) { parser_err(param, XKB_ERROR_INVALID_XKB_SYNTAX, "%s", msg); } static bool resolve_keysym(struct parser_param *param, struct sval name, xkb_keysym_t *sym_rtrn) { xkb_keysym_t sym; if (isvaleq(name, SVAL_LIT("any")) || isvaleq(name, SVAL_LIT("nosymbol"))) { *sym_rtrn = XKB_KEY_NoSymbol; return true; } if (isvaleq(name, SVAL_LIT("none")) || isvaleq(name, SVAL_LIT("voidsymbol"))) { *sym_rtrn = XKB_KEY_VoidSymbol; return true; } /* xkb_keysym_from_name needs a C string. */ char buf[XKB_KEYSYM_NAME_MAX_SIZE]; if (name.len >= sizeof(buf)) { return false; } memcpy(buf, name.start, name.len); buf[name.len] = '\0'; sym = xkb_keysym_from_name(buf, XKB_KEYSYM_NO_FLAGS); if (sym != XKB_KEY_NoSymbol) { *sym_rtrn = sym; check_deprecated_keysyms(parser_warn, param, param->ctx, sym, buf, buf, "%s", ""); return true; } return false; } #define param_scanner param->scanner %} %define api.pure %lex-param { struct scanner *param_scanner } %parse-param { struct parser_param *param } %define parse.error detailed %token END_OF_FILE 0 "end of file" ERROR_TOK 255 "invalid token" XKB_KEYMAP 1 "xkb_keymap" XKB_KEYCODES 2 "xkb_keycodes" XKB_TYPES 3 "xkb_types" XKB_SYMBOLS 4 "xkb_symbols" XKB_COMPATMAP 5 "xkb_compatibility" XKB_GEOMETRY 6 "xkb_geometry" XKB_SEMANTICS 7 "xkb_semantics" XKB_LAYOUT 8 "xkb_layout" INCLUDE 10 "include" OVERRIDE 11 "override" AUGMENT 12 "augment" REPLACE 13 "replace" ALTERNATE 14 "alternate" VIRTUAL_MODS 20 "virtual_modifiers" TYPE 21 "type" INTERPRET 22 "interpret" ACTION_TOK 23 "action" KEY 24 "key" ALIAS 25 "alias" GROUP 26 "group" MODIFIER_MAP 27 "modifier_map" INDICATOR 28 "indicator" SHAPE 29 "shape" KEYS 30 "keys" ROW 31 "row" SECTION 32 "section" OVERLAY 33 "overlay" TEXT 34 "text" OUTLINE 35 "outline" SOLID 36 "solid" LOGO 37 "logo" VIRTUAL 38 "virtual" EQUALS 40 "=" PLUS 41 "+" MINUS 42 "-" DIVIDE 43 "/" TIMES 44 "*" OBRACE 45 "{" CBRACE 46 "}" OPAREN 47 "(" CPAREN 48 ")" OBRACKET 49 "[" CBRACKET 50 "]" DOT 51 "." COMMA 52 "," SEMI 53 ";" EXCLAM 54 "!" INVERT 55 "~" STRING 60 "string literal" DECIMAL_DIGIT 61 "decimal digit" INTEGER 62 "integer literal" FLOAT 63 "float literal" IDENT 64 "identifier" KEYNAME 65 "key name" PARTIAL 70 "partial" DEFAULT 71 "default" HIDDEN 72 "hidden" ALPHANUMERIC_KEYS 73 "alphanumeric_keys" MODIFIER_KEYS 74 "modifier_keys" KEYPAD_KEYS 75 "keypad_keys" FUNCTION_KEYS 76 "function_keys" ALTERNATE_GROUP 77 "alternate_group" %right EQUALS %left PLUS MINUS %left TIMES DIVIDE %left EXCLAM INVERT %left OPAREN %start XkbFile %union { int64_t num; enum xkb_file_type file_type; char *str; struct sval sval; xkb_atom_t atom; enum merge_mode merge; enum xkb_map_flags mapFlags; xkb_keysym_t keysym; ParseCommon *any; struct { ParseCommon *head; ParseCommon *last; } anyList; uint32_t noSymbolOrActionList; ExprDef *expr; struct { ExprDef *head; ExprDef *last; } exprList; VarDef *var; struct { VarDef *head; VarDef *last; } varList; VModDef *vmod; struct { VModDef *head; VModDef *last; } vmodList; InterpDef *interp; KeyTypeDef *keyType; SymbolsDef *syms; ModMapDef *modMask; GroupCompatDef *groupCompat; LedMapDef *ledMap; LedNameDef *ledName; KeycodeDef *keyCode; KeyAliasDef *keyAlias; void *geom; XkbFile *file; struct { XkbFile *head; XkbFile *last; } fileList; } %type DECIMAL_DIGIT INTEGER FLOAT %type STRING %type IDENT %type KEYNAME %type KeyCode Number Integer Float SignedNumber DoodadType %type MergeMode OptMergeMode %type XkbCompositeType FileType %type Flag Flags OptFlags %type MapName OptMapName %type FieldSpec Ident Element String %type KeySym KeySymLit %type NoSymbolOrActionList %type Decl %type DeclList %type Expr Term Lhs Terminal Coord CoordList %type MultiKeySymOrActionList NonEmptyActions Actions Action %type KeySyms NonEmptyKeySyms KeySymList KeyOrKeySym %type ExprList KeyOrKeySymList %type ActionList MultiActionList MultiKeySymList %type VarDecl SymbolsVarDecl %type VarDeclList SymbolsBody OptSymbolsBody %type VModDef %type VModDefList VModDecl %type InterpretDecl InterpretMatch %type KeyTypeDecl %type SymbolsDecl %type ModMapDecl %type GroupCompatDecl %type LedMapDecl %type LedNameDecl %type KeyNameDecl %type KeyAliasDecl %type ShapeDecl SectionDecl SectionBody SectionBodyItem RowBody RowBodyItem %type Keys Key OverlayDecl OverlayKeyList OverlayKey OutlineList OutlineInList %type DoodadDecl %type XkbFile XkbMapConfig %type XkbMapConfigList %type XkbCompositeMap %destructor { FreeStmt((ParseCommon *) $$); } %destructor { FreeStmt((ParseCommon *) $$.head); } /* The destructor also runs on the start symbol when the parser *succeeds*. * The `if` here catches this case. */ %destructor { if (!param->rtrn) FreeXkbFile($$); } %destructor { FreeXkbFile($$.head); } %destructor { free($$); } %% /* * An actual file may contain more than one map. However, if we do things * in the normal yacc way, i.e. aggregate all of the maps into a list and * let the caller find the map it wants, we end up scanning and parsing a * lot of unneeded maps (in the end we always just need one). * Instead of doing that, we make yyparse return one map at a time, and * then call it repeatedly until we find the map we need. Once we find it, * we don't need to parse everything that follows in the file. * This does mean that if we e.g. always use the first map, the file may * contain complete garbage after that. But it's worth it. */ XkbFile : XkbCompositeMap { $$ = param->rtrn = $1; param->more_maps = !!param->rtrn; (void) yynerrs; } | XkbMapConfig { $$ = param->rtrn = $1; param->more_maps = !!param->rtrn; YYACCEPT; } | END_OF_FILE { $$ = param->rtrn = NULL; param->more_maps = false; } ; XkbCompositeMap : OptFlags XkbCompositeType OptMapName OBRACE XkbMapConfigList CBRACE SEMI { $$ = XkbFileCreate($2, $3, (ParseCommon *) $5.head, $1); } ; XkbCompositeType: XKB_KEYMAP { $$ = FILE_TYPE_KEYMAP; } | XKB_SEMANTICS { $$ = FILE_TYPE_KEYMAP; } | XKB_LAYOUT { $$ = FILE_TYPE_KEYMAP; } ; /* * NOTE: Any component is optional */ XkbMapConfigList : XkbMapConfigList XkbMapConfig { if ($2) { if ($1.head) { $$.head = $1.head; $$.last->common.next = &$2->common; $$.last = $2; } else { $$.head = $$.last = $2; } } } | { $$.head = $$.last = NULL; } ; XkbMapConfig : OptFlags FileType OptMapName OBRACE DeclList CBRACE SEMI { $$ = XkbFileCreate($2, $3, $5.head, $1); } ; FileType : XKB_KEYCODES { $$ = FILE_TYPE_KEYCODES; } | XKB_TYPES { $$ = FILE_TYPE_TYPES; } | XKB_COMPATMAP { $$ = FILE_TYPE_COMPAT; } | XKB_SYMBOLS { $$ = FILE_TYPE_SYMBOLS; } | XKB_GEOMETRY { $$ = FILE_TYPE_GEOMETRY; } ; OptFlags : Flags { $$ = $1; } | { $$ = 0; } ; Flags : Flags Flag { $$ = ($1 | $2); } | Flag { $$ = $1; } ; Flag : PARTIAL { $$ = MAP_IS_PARTIAL; } | DEFAULT { $$ = MAP_IS_DEFAULT; } | HIDDEN { $$ = MAP_IS_HIDDEN; } | ALPHANUMERIC_KEYS { $$ = MAP_HAS_ALPHANUMERIC; } | MODIFIER_KEYS { $$ = MAP_HAS_MODIFIER; } | KEYPAD_KEYS { $$ = MAP_HAS_KEYPAD; } | FUNCTION_KEYS { $$ = MAP_HAS_FN; } | ALTERNATE_GROUP { $$ = MAP_IS_ALTGR; } ; DeclList : DeclList Decl { if ($2) { if ($1.head) { $$.head = $1.head; $1.last->next = $2; $$.last = $2; } else { $$.head = $$.last = $2; } } } /* * VModDecl is "inlined" directly into DeclList, i.e. * each VModDef in the VModDecl is a separate Decl in * the File. */ | DeclList OptMergeMode VModDecl { for (VModDef *vmod = $3.head; vmod; vmod = (VModDef *) vmod->common.next) vmod->merge = $2; if ($1.head) { $$.head = $1.head; $1.last->next = &$3.head->common; $$.last = &$3.last->common; } else { $$.head = &$3.head->common; $$.last = &$3.last->common; } } | { $$.head = $$.last = NULL; } ; Decl : OptMergeMode VarDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } /* OptMergeMode VModDecl - see above. */ | OptMergeMode InterpretDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode KeyNameDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode KeyAliasDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode KeyTypeDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode SymbolsDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode ModMapDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode GroupCompatDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode LedMapDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode LedNameDecl { $2->merge = $1; $$ = (ParseCommon *) $2; } | OptMergeMode ShapeDecl { $$ = NULL; } | OptMergeMode SectionDecl { $$ = NULL; } | OptMergeMode DoodadDecl { $$ = NULL; } | MergeMode STRING { $$ = (ParseCommon *) IncludeCreate(param->ctx, $2, $1); free($2); } ; VarDecl : Lhs EQUALS Expr SEMI { $$ = VarCreate($1, $3); } | Ident SEMI { $$ = BoolVarCreate($1, true); } | EXCLAM Ident SEMI { $$ = BoolVarCreate($2, false); } ; KeyNameDecl : KEYNAME EQUALS KeyCode SEMI { $$ = KeycodeCreate($1, $3); } ; KeyAliasDecl : ALIAS KEYNAME EQUALS KEYNAME SEMI { $$ = KeyAliasCreate($2, $4); } ; VModDecl : VIRTUAL_MODS VModDefList SEMI { $$ = $2; } ; VModDefList : VModDefList COMMA VModDef { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; } | VModDef { $$.head = $$.last = $1; } ; VModDef : Ident { $$ = VModCreate($1, NULL); } | Ident EQUALS Expr { $$ = VModCreate($1, $3); } ; InterpretDecl : INTERPRET InterpretMatch OBRACE VarDeclList CBRACE SEMI { $2->def = $4.head; $$ = $2; } ; InterpretMatch : KeySym PLUS Expr { $$ = InterpCreate($1, $3); } | KeySym { $$ = InterpCreate($1, NULL); } ; VarDeclList : VarDeclList VarDecl { if ($2) { if ($1.head) { $$.head = $1.head; $$.last->common.next = &$2->common; $$.last = $2; } else { $$.head = $$.last = $2; } } } | { $$.head = $$.last = NULL; } ; KeyTypeDecl : TYPE String OBRACE VarDeclList CBRACE SEMI { $$ = KeyTypeCreate($2, $4.head); } ; SymbolsDecl : KEY KEYNAME OBRACE OptSymbolsBody CBRACE SEMI { $$ = SymbolsCreate($2, $4.head); } ; OptSymbolsBody : SymbolsBody { $$ = $1; } | { $$.head = $$.last = NULL; } ; SymbolsBody : SymbolsBody COMMA SymbolsVarDecl { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; } | SymbolsVarDecl { $$.head = $$.last = $1; } ; SymbolsVarDecl : Lhs EQUALS Expr { $$ = VarCreate($1, $3); } | Lhs EQUALS MultiKeySymOrActionList { $$ = VarCreate($1, $3); } | Ident { $$ = BoolVarCreate($1, true); } | EXCLAM Ident { $$ = BoolVarCreate($2, false); } | MultiKeySymOrActionList { $$ = VarCreate(NULL, $1); } ; /* * A list of keysym/action lists * * There is some ambiguity because we use `{}` to denote both an empty list of * keysyms and an empty list of actions. But as soon as we get a keysym or an * action, we know whether it is a `MultiKeySymList` or a `MultiActionList`. * So we just count the `{}` at the *beginning* using `NoSymbolOrActionList`, * then replace it by the relevant count of `NoSymbol` or `NoAction()` once the * ambiguity is solved. If not, this is a list of empties of *some* type: we * drop those empties and delegate the type resolution using `ExprEmptyList()`. */ MultiKeySymOrActionList : OBRACKET MultiKeySymList CBRACKET { $$ = $2.head; } | OBRACKET NoSymbolOrActionList COMMA MultiKeySymList CBRACKET { /* Prepend n times NoSymbol */ struct {ExprDef *head; ExprDef *last;} list = { .head = $4.head, .last = $4.last }; for (uint32_t k = 0; k < $2; k++) { ExprDef* const syms = ExprCreateKeySymList(XKB_KEY_NoSymbol); if (!syms) { /* TODO: Use Bison’s more appropriate YYNOMEM */ YYABORT; } syms->common.next = &list.head->common; list.head = syms; } $$ = list.head; } | OBRACKET MultiActionList CBRACKET { $$ = $2.head; } | OBRACKET NoSymbolOrActionList COMMA MultiActionList CBRACKET { /* Prepend n times NoAction() */ struct {ExprDef *head; ExprDef *last;} list = { .head = $4.head, .last = $4.last }; for (uint32_t k = 0; k < $2; k++) { ExprDef* const acts = ExprCreateActionList(NULL); if (!acts) { /* TODO: Use Bison’s more appropriate YYNOMEM */ YYABORT; } acts->common.next = &list.head->common; list.head = acts; } $$ = list.head; } /* * A list of *empty* keysym/action lists `{}`. * There is not enough context here to decide if it is * a `MultiKeySymList` or a `MultiActionList`. */ | OBRACKET NoSymbolOrActionList CBRACKET { $$ = ExprEmptyList(); } ; /* A list of `{}`, which remains ambiguous until reaching a keysym or action list */ NoSymbolOrActionList : NoSymbolOrActionList COMMA OBRACE CBRACE { $$ = $1 + 1; } | OBRACE CBRACE { $$ = 1; } | { $$ = 0; } ; GroupCompatDecl : GROUP Integer EQUALS Expr SEMI { $$ = GroupCompatCreate($2, $4); } ; ModMapDecl : MODIFIER_MAP Ident OBRACE KeyOrKeySymList CBRACE SEMI { $$ = ModMapCreate($2, $4.head); } ; KeyOrKeySymList : KeyOrKeySymList COMMA KeyOrKeySym { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; } | KeyOrKeySym { $$.head = $$.last = $1; } ; KeyOrKeySym : KEYNAME { $$ = ExprCreateKeyName($1); } | KeySym { $$ = ExprCreateKeySym($1); } ; LedMapDecl: INDICATOR String OBRACE VarDeclList CBRACE SEMI { $$ = LedMapCreate($2, $4.head); } ; LedNameDecl: INDICATOR Integer EQUALS Expr SEMI { $$ = LedNameCreate($2, $4, false); } | VIRTUAL INDICATOR Integer EQUALS Expr SEMI { $$ = LedNameCreate($3, $5, true); } ; ShapeDecl : SHAPE String OBRACE OutlineList CBRACE SEMI { $$ = NULL; } | SHAPE String OBRACE CoordList CBRACE SEMI { (void) $4; $$ = NULL; } ; SectionDecl : SECTION String OBRACE SectionBody CBRACE SEMI { $$ = NULL; } ; SectionBody : SectionBody SectionBodyItem { $$ = NULL;} | SectionBodyItem { $$ = NULL; } ; SectionBodyItem : ROW OBRACE RowBody CBRACE SEMI { $$ = NULL; } | VarDecl { FreeStmt((ParseCommon *) $1); $$ = NULL; } | DoodadDecl { $$ = NULL; } | LedMapDecl { FreeStmt((ParseCommon *) $1); $$ = NULL; } | OverlayDecl { $$ = NULL; } ; RowBody : RowBody RowBodyItem { $$ = NULL;} | RowBodyItem { $$ = NULL; } ; RowBodyItem : KEYS OBRACE Keys CBRACE SEMI { $$ = NULL; } | VarDecl { FreeStmt((ParseCommon *) $1); $$ = NULL; } ; Keys : Keys COMMA Key { $$ = NULL; } | Key { $$ = NULL; } ; Key : KEYNAME { $$ = NULL; } | OBRACE ExprList CBRACE { FreeStmt((ParseCommon *) $2.head); $$ = NULL; } ; OverlayDecl : OVERLAY String OBRACE OverlayKeyList CBRACE SEMI { $$ = NULL; } ; OverlayKeyList : OverlayKeyList COMMA OverlayKey { $$ = NULL; } | OverlayKey { $$ = NULL; } ; OverlayKey : KEYNAME EQUALS KEYNAME { $$ = NULL; } ; OutlineList : OutlineList COMMA OutlineInList { $$ = NULL;} | OutlineInList { $$ = NULL; } ; OutlineInList : OBRACE CoordList CBRACE { (void) $2; $$ = NULL; } | Ident EQUALS OBRACE CoordList CBRACE { (void) $4; $$ = NULL; } | Ident EQUALS Expr { FreeStmt((ParseCommon *) $3); $$ = NULL; } ; CoordList : CoordList COMMA Coord { (void) $1; (void) $3; $$ = NULL; } | Coord { (void) $1; $$ = NULL; } ; Coord : OBRACKET SignedNumber COMMA SignedNumber CBRACKET { $$ = NULL; } ; DoodadDecl : DoodadType String OBRACE VarDeclList CBRACE SEMI { FreeStmt((ParseCommon *) $4.head); $$ = NULL; } ; DoodadType : TEXT { $$ = 0; } | OUTLINE { $$ = 0; } | SOLID { $$ = 0; } | LOGO { $$ = 0; } ; FieldSpec : Ident { $$ = $1; } | Element { $$ = $1; } ; Element : ACTION_TOK { $$ = xkb_atom_intern_literal(param->ctx, "action"); } | INTERPRET { $$ = xkb_atom_intern_literal(param->ctx, "interpret"); } | TYPE { $$ = xkb_atom_intern_literal(param->ctx, "type"); } | KEY { $$ = xkb_atom_intern_literal(param->ctx, "key"); } | GROUP { $$ = xkb_atom_intern_literal(param->ctx, "group"); } | MODIFIER_MAP {$$ = xkb_atom_intern_literal(param->ctx, "modifier_map");} | INDICATOR { $$ = xkb_atom_intern_literal(param->ctx, "indicator"); } | SHAPE { $$ = xkb_atom_intern_literal(param->ctx, "shape"); } | ROW { $$ = xkb_atom_intern_literal(param->ctx, "row"); } | SECTION { $$ = xkb_atom_intern_literal(param->ctx, "section"); } | TEXT { $$ = xkb_atom_intern_literal(param->ctx, "text"); } ; OptMergeMode : MergeMode { $$ = $1; } | { $$ = MERGE_DEFAULT; } ; MergeMode : INCLUDE { $$ = MERGE_DEFAULT; } | AUGMENT { $$ = MERGE_AUGMENT; } | OVERRIDE { $$ = MERGE_OVERRIDE; } | REPLACE { $$ = MERGE_REPLACE; } | ALTERNATE { /* * This used to be MERGE_ALT_FORM. This functionality was * unused and has been removed. */ parser_warn(param, XKB_LOG_MESSAGE_NO_ID, "ignored unsupported legacy merge mode \"alternate\""); $$ = MERGE_DEFAULT; } ; ExprList : ExprList COMMA Expr { if ($3) { if ($1.head) { $$.head = $1.head; $$.last->common.next = &$3->common; $$.last = $3; } else { $$.head = $$.last = $3; } } } | Expr { $$.head = $$.last = $1; } | { $$.head = $$.last = NULL; } ; Expr : Expr DIVIDE Expr { $$ = ExprCreateBinary(STMT_EXPR_DIVIDE, $1, $3); } | Expr PLUS Expr { $$ = ExprCreateBinary(STMT_EXPR_ADD, $1, $3); } | Expr MINUS Expr { $$ = ExprCreateBinary(STMT_EXPR_SUBTRACT, $1, $3); } | Expr TIMES Expr { $$ = ExprCreateBinary(STMT_EXPR_MULTIPLY, $1, $3); } | Lhs EQUALS Expr { $$ = ExprCreateBinary(STMT_EXPR_ASSIGN, $1, $3); } | Term { $$ = $1; } ; Term : MINUS Term { $$ = ExprCreateUnary(STMT_EXPR_NEGATE, $2); } | PLUS Term { $$ = ExprCreateUnary(STMT_EXPR_UNARY_PLUS, $2); } | EXCLAM Term { $$ = ExprCreateUnary(STMT_EXPR_NOT, $2); } | INVERT Term { $$ = ExprCreateUnary(STMT_EXPR_INVERT, $2); } | Lhs { $$ = $1; } | FieldSpec OPAREN ExprList CPAREN %prec OPAREN { $$ = ExprCreateAction($1, $3.head); } | Actions { $$ = $1; } | Terminal { $$ = $1; } | OPAREN Expr CPAREN { $$ = $2; } ; MultiActionList : MultiActionList COMMA Action { ExprDef *expr = ExprCreateActionList($3); $$ = $1; $$.last->common.next = &expr->common; $$.last = expr; } | MultiActionList COMMA Actions { $$ = $1; $$.last->common.next = &$3->common; $$.last = $3; } | Action { $$.head = $$.last = ExprCreateActionList($1); } | NonEmptyActions { $$.head = $$.last = $1; } ; ActionList : ActionList COMMA Action { $$ = $1; $$.last->common.next = &$3->common; $$.last = $3; } | Action { $$.head = $$.last = $1; } ; NonEmptyActions : OBRACE ActionList CBRACE { $$ = ExprCreateActionList($2.head); } ; Actions : NonEmptyActions { $$ = $1; } | OBRACE CBRACE { $$ = ExprCreateActionList(NULL); } ; Action : FieldSpec OPAREN ExprList CPAREN { $$ = ExprCreateAction($1, $3.head); } ; Lhs : FieldSpec { $$ = ExprCreateIdent($1); } | FieldSpec DOT FieldSpec { $$ = ExprCreateFieldRef($1, $3); } | FieldSpec OBRACKET Expr CBRACKET { $$ = ExprCreateArrayRef(XKB_ATOM_NONE, $1, $3); } | FieldSpec DOT FieldSpec OBRACKET Expr CBRACKET { $$ = ExprCreateArrayRef($1, $3, $5); } ; Terminal : String { $$ = ExprCreateString($1); } | Integer { $$ = ExprCreateInteger($1); } | Float { $$ = ExprCreateFloat(/* Discard $1 */); } | KEYNAME { $$ = ExprCreateKeyName($1); } ; MultiKeySymList : MultiKeySymList COMMA KeySymLit { ExprDef *expr = ExprCreateKeySymList($3); $$ = $1; $$.last->common.next = &expr->common; $$.last = expr; } | MultiKeySymList COMMA KeySyms { $$ = $1; $$.last->common.next = &$3->common; $$.last = $3; } | KeySymLit { $$.head = $$.last = ExprCreateKeySymList($1); } | NonEmptyKeySyms { $$.head = $$.last = $1; } ; KeySymList : KeySymList COMMA KeySymLit { $$ = ExprAppendKeySymList($1, $3); } | KeySymList COMMA STRING { $$ = ExprKeySymListAppendString(param->scanner, $1, $3); free($3); if (!$$) YYERROR; } | KeySymLit { $$ = ExprCreateKeySymList($1); if (!$$) YYERROR; } | STRING { $$ = ExprCreateKeySymList(XKB_KEY_NoSymbol); if (!$$) YYERROR; $$ = ExprKeySymListAppendString(param->scanner, $$, $1); free($1); if (!$$) YYERROR; } ; NonEmptyKeySyms : OBRACE KeySymList CBRACE { $$ = $2; } | STRING { $$ = ExprCreateKeySymList(XKB_KEY_NoSymbol); if (!$$) YYERROR; $$ = ExprKeySymListAppendString(param->scanner, $$, $1); free($1); if (!$$) YYERROR; } ; KeySyms : NonEmptyKeySyms { $$ = $1; } | OBRACE CBRACE { $$ = ExprCreateKeySymList(XKB_KEY_NoSymbol); } ; KeySym : KeySymLit { $$ = $1; } | STRING { $$ = KeysymParseString(param->scanner, $1); free($1); if ($$ == XKB_KEY_NoSymbol) YYERROR; } ; KeySymLit : IDENT { if (!resolve_keysym(param, $1, &$$)) { parser_warn( param, XKB_WARNING_UNRECOGNIZED_KEYSYM, "unrecognized keysym \"%.*s\"", (unsigned int) $1.len, $1.start ); $$ = XKB_KEY_NoSymbol; } } /* Handle keysym that is also a keyword */ | SECTION { $$ = XKB_KEY_section; } | DECIMAL_DIGIT { /* * Special case for digits 0..9: * map to XKB_KEY_0 .. XKB_KEY_9, consistent with * other keysym names: → XKB_KEY_. */ $$ = XKB_KEY_0 + (xkb_keysym_t) $1; } | INTEGER { if ($1 < XKB_KEYSYM_MIN) { /* Negative value */ static_assert(XKB_KEYSYM_MIN == 0, "Keysyms are positive"); parser_warn( param, XKB_ERROR_INVALID_NUMERIC_KEYSYM, "unrecognized keysym \"-%#06"PRIx64"\"" " (%"PRId64")", -$1, $1 ); $$ = XKB_KEY_NoSymbol; } /* * Integers 0..9 are handled with DECIMAL_DIGIT if * they were formatted as single characters '0'..'9'. * Otherwise they are handled here as raw keysyms * values. E.g. `01` and `0x1` are interpreted as * the keysym 0x0001, while `1` is interpreted as * XKB_KEY_1. */ else { /* Any other numeric value */ if ($1 <= XKB_KEYSYM_MAX) { /* * Valid keysym * No normalization is performed and value * is used as is. */ $$ = (xkb_keysym_t) $1; check_deprecated_keysyms( parser_warn, param, param->ctx, $$, NULL, $$, "%#06"PRIx32, ""); } else { /* Invalid keysym */ parser_warn( param, XKB_ERROR_INVALID_NUMERIC_KEYSYM, "unrecognized keysym \"%#06"PRIx64"\" " "(%"PRId64")", $1, $1 ); $$ = XKB_KEY_NoSymbol; } parser_vrb( /* * Require an extra high verbosity, because * keysyms are formatted as number unless * enabling pretty-pretting for the * serialization. */ param, XKB_LOG_VERBOSITY_COMPREHENSIVE, XKB_WARNING_NUMERIC_KEYSYM, "numeric keysym \"%#06"PRIx64"\" (%"PRId64")", $1, $1 ); } } ; SignedNumber : MINUS Number { $$ = -$2; } | Number { $$ = $1; } ; Number : FLOAT { $$ = $1; } | DECIMAL_DIGIT { $$ = $1; } | INTEGER { $$ = $1; } ; Float : FLOAT { $$ = 0; } ; Integer : INTEGER { $$ = $1; } | DECIMAL_DIGIT { $$ = $1; } ; KeyCode : INTEGER { $$ = $1; } | DECIMAL_DIGIT { $$ = $1; } ; Ident : IDENT { $$ = xkb_atom_intern(param->ctx, $1.start, $1.len); } | DEFAULT { $$ = xkb_atom_intern_literal(param->ctx, "default"); } ; String : STRING { $$ = xkb_atom_intern(param->ctx, $1, strlen($1)); free($1); } ; OptMapName : MapName { $$ = $1; } | { $$ = NULL; } ; MapName : STRING { $$ = $1; } ; %% /* Parse a specific section */ XkbFile * parse(struct xkb_context *ctx, struct scanner *scanner, const char *map) { int ret; XkbFile *first = NULL; struct parser_param param = { .scanner = scanner, .ctx = ctx, .rtrn = NULL, .more_maps = false, }; /* * If we got a specific map, we look for it exclusively and return * immediately upon finding it. Otherwise, we need to get the * default map. If we find a map marked as default, we return it * immediately. If there are no maps marked as default, we return * the first map in the file. */ while ((ret = yyparse(¶m)) == 0 && param.more_maps) { if (map) { if (streq_not_null(map, param.rtrn->name)) return param.rtrn; else FreeXkbFile(param.rtrn); } else { if (param.rtrn->flags & MAP_IS_DEFAULT) { FreeXkbFile(first); return param.rtrn; } else if (!first) { first = param.rtrn; } else { FreeXkbFile(param.rtrn); } } param.rtrn = NULL; } if (ret != 0) { /* Some error happend; clear the Xkbfiles parsed so far */ FreeXkbFile(first); FreeXkbFile(param.rtrn); return NULL; } if (first) log_vrb(ctx, XKB_LOG_VERBOSITY_DETAILED, XKB_WARNING_MISSING_DEFAULT_SECTION, "No map in include statement, but \"%s\" contains several; " "Using first defined map, \"%s\"\n", scanner->file_name, safe_map_name(first)); return first; } /* Parse the next section */ bool parse_next(struct xkb_context *ctx, struct scanner *scanner, XkbFile **xkb_file) { int ret; struct parser_param param = { .scanner = scanner, .ctx = ctx, .rtrn = NULL, .more_maps = false, }; if ((ret = yyparse(¶m)) == 0 && param.more_maps) { *xkb_file = param.rtrn; return true; } else { FreeXkbFile(param.rtrn); *xkb_file = NULL; return (ret == 0); } } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/rules.c000066400000000000000000002143601510033435100224210ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1996 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcomp-priv.h" #include "context.h" #include "keymap.h" #include "messages-codes.h" #include "context.h" #include "rules.h" #include "rmlvo.h" #include "include.h" #include "scanner-utils.h" #include "darray.h" #include "utils.h" #include "utils-numbers.h" #include "utils-paths.h" #define MAX_INCLUDE_DEPTH 5 /* Scanner / Lexer */ /* Values returned with some tokens, like yylval. */ union lvalue { struct sval string; }; enum rules_token { TOK_END_OF_FILE = 0, TOK_END_OF_LINE, TOK_IDENTIFIER, TOK_GROUP_NAME, TOK_BANG, TOK_EQUALS, TOK_WILD_CARD_STAR, TOK_WILD_CARD_NONE, TOK_WILD_CARD_SOME, TOK_WILD_CARD_ANY, TOK_INCLUDE, TOK_ERROR }; static inline bool is_ident(char ch) { return is_graph(ch) && ch != '\\'; } static enum rules_token lex(struct scanner *s, union lvalue *val) { skip_more_whitespace_and_comments: /* Skip spaces. */ while (scanner_chr(s, ' ') || scanner_chr(s, '\t') || scanner_chr(s, '\r')); /* Skip comments. */ if (scanner_lit(s, "//")) { scanner_skip_to_eol(s); } /* New line. */ if (scanner_eol(s)) { while (scanner_eol(s)) scanner_next(s); return TOK_END_OF_LINE; } /* Escaped line continuation. */ if (scanner_chr(s, '\\')) { /* Optional \r. */ scanner_chr(s, '\r'); if (!scanner_eol(s)) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "illegal new line escape; must appear at end of line"); return TOK_ERROR; } scanner_next(s); goto skip_more_whitespace_and_comments; } /* See if we're done. */ if (scanner_eof(s)) return TOK_END_OF_FILE; /* New token. */ s->token_pos = s->pos; /* Operators and punctuation. */ if (scanner_chr(s, '!')) return TOK_BANG; if (scanner_chr(s, '=')) return TOK_EQUALS; /* Wild cards */ if (scanner_chr(s, '*')) return TOK_WILD_CARD_STAR; if (scanner_lit(s, "")) return TOK_WILD_CARD_NONE; if (scanner_lit(s, "")) return TOK_WILD_CARD_SOME; if (scanner_lit(s, "")) return TOK_WILD_CARD_ANY; /* Group name. */ if (scanner_chr(s, '$')) { val->string.start = s->s + s->pos; val->string.len = 0; while (is_ident(scanner_peek(s))) { scanner_next(s); val->string.len++; } if (val->string.len == 0) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "unexpected character after \'$\'; expected name"); return TOK_ERROR; } return TOK_GROUP_NAME; } /* Include statement. */ if (scanner_lit(s, "include")) return TOK_INCLUDE; /* Identifier. */ /* Ensure that we can parse KcCGST values with merge modes */ assert(is_ident(MERGE_OVERRIDE_PREFIX)); assert(is_ident(MERGE_AUGMENT_PREFIX)); assert(is_ident(MERGE_REPLACE_PREFIX)); if (is_ident(scanner_peek(s))) { val->string.start = s->s + s->pos; val->string.len = 0; while (is_ident(scanner_peek(s))) { scanner_next(s); val->string.len++; } return TOK_IDENTIFIER; } scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "unrecognized token"); return TOK_ERROR; } /***====================================================================***/ enum rules_mlvo { MLVO_MODEL, MLVO_LAYOUT, MLVO_VARIANT, MLVO_OPTION, _MLVO_NUM_ENTRIES }; typedef uint8_t mlvo_index_t; typedef uint8_t mlvo_mask_t; static const struct sval rules_mlvo_svals[_MLVO_NUM_ENTRIES] = { [MLVO_MODEL] = SVAL_INIT("model"), [MLVO_LAYOUT] = SVAL_INIT("layout"), [MLVO_VARIANT] = SVAL_INIT("variant"), [MLVO_OPTION] = SVAL_INIT("option"), }; enum rules_kccgst { KCCGST_KEYCODES, KCCGST_TYPES, KCCGST_COMPAT, KCCGST_SYMBOLS, KCCGST_GEOMETRY, _KCCGST_NUM_ENTRIES }; typedef uint8_t kccgst_index_t; typedef uint8_t kccgst_mask_t; static const struct sval rules_kccgst_svals[_KCCGST_NUM_ENTRIES] = { [KCCGST_KEYCODES] = SVAL_INIT("keycodes"), [KCCGST_TYPES] = SVAL_INIT("types"), [KCCGST_COMPAT] = SVAL_INIT("compat"), [KCCGST_SYMBOLS] = SVAL_INIT("symbols"), [KCCGST_GEOMETRY] = SVAL_INIT("geometry"), }; static_assert(XKB_MAX_GROUPS < (1u << 30), "Layout index does not fix in matched_sval::matched_layouts"); #define OPTIONS_MATCH_ALL_GROUPS XKB_MAX_GROUPS /* We use this to keep score whether an mlvo was matched or not; if not, * we warn the user that his preference was ignored. */ struct matched_sval { struct sval sval; bool matched:1; /* Used for layout-specific options */ xkb_layout_index_t layout:31; }; typedef darray(struct matched_sval) darray_matched_sval; /* * A broken-down version of xkb_rule_names (without the rules, * obviously). */ struct rule_names { struct matched_sval model; darray_matched_sval layouts; darray_matched_sval variants; darray_matched_sval options; }; struct group { struct sval name; darray_sval elements; }; struct mapping { enum rules_mlvo mlvo_at_pos[_MLVO_NUM_ENTRIES]; mlvo_index_t num_mlvo; mlvo_mask_t defined_mlvo_mask; bool has_layout_idx_range; /* This member has 2 uses: * • Keep track of layout and variant indices while parsing MLVO headers. * • Store layout/variant range afterwards. * Thus provide 2 structs to reflect these semantics in the code. */ union { struct { xkb_layout_index_t layout_idx, variant_idx; }; struct { xkb_layout_index_t layout_idx_min, layout_idx_max; }; }; /* This member has 2 uses: * • Check if the mapping is active by interpreting the value as a boolean. * • Keep track of the remaining layout indices to match. * Thus provide 2 names to reflect these semantics in the code. */ union { xkb_layout_mask_t active; xkb_layout_mask_t layouts_candidates_mask; }; enum rules_kccgst kccgst_at_pos[_KCCGST_NUM_ENTRIES]; kccgst_index_t num_kccgst; kccgst_mask_t defined_kccgst_mask; }; enum mlvo_match_type { /** Match the given plain value */ MLVO_MATCH_NORMAL = 0, /** Match depending on the value of `wildcard_match_type` */ MLVO_MATCH_WILDCARD_LEGACY, /** Match empty value */ MLVO_MATCH_WILDCARD_NONE, /** Match non-empty value */ MLVO_MATCH_WILDCARD_SOME, /** Match any value, optionally empty */ MLVO_MATCH_WILDCARD_ANY, /** Match any entry in a group */ MLVO_MATCH_GROUP, }; enum wildcard_match_type { /** ‘*’ matches only non-empty strings */ WILDCARD_MATCH_NONEMPTY = 0, /** ‘*’ matches all strings */ WILDCARD_MATCH_ALL, }; struct rule { struct sval mlvo_value_at_pos[_MLVO_NUM_ENTRIES]; enum mlvo_match_type match_type_at_pos[_MLVO_NUM_ENTRIES]; mlvo_index_t num_mlvo_values; struct sval kccgst_value_at_pos[_KCCGST_NUM_ENTRIES]; kccgst_index_t num_kccgst_values; bool skip; }; #define SLICE_KCCGST_BIT_FIELD_SIZE 4 static_assert(!((1u << (SLICE_KCCGST_BIT_FIELD_SIZE - 1)) & (_KCCGST_NUM_ENTRIES - 1)), "Cannot encode KcCGST enum safely (need space for the sign)"); struct kccgst_buffer_slice { uint32_t length:(32 - SLICE_KCCGST_BIT_FIELD_SIZE); enum rules_kccgst kccgst:SLICE_KCCGST_BIT_FIELD_SIZE; xkb_layout_index_t layout; }; /* Buffer for pending KcCGST values */ struct kccgst_buffer { darray_char buffer; /* Slice corresponding to each value in the buffer */ darray(struct kccgst_buffer_slice) slices; }; /* * This is the main object used to match a given RMLVO against a rules * file and aggregate the results in a KcCGST. It goes through a simple * matching state machine, with tokens as transitions (see * matcher_match()). */ struct matcher { struct xkb_context *ctx; /* Input.*/ struct rule_names rmlvo; union lvalue val; darray(struct group) groups; /* Current mapping. */ struct mapping mapping; /* Current rule. */ struct rule rule; /* * Buffers for pending KcCGST values. Required in case of using layout * index ranges, to ensure that the values are merged in the expected order. * See the note: “Layout index ranges and merging KcCGST values”. */ struct kccgst_buffer pending_kccgst; /* Output. */ darray_char kccgst[_KCCGST_NUM_ENTRIES]; }; static struct sval strip_spaces(struct sval v) { while (v.len > 0 && is_space(v.start[0])) { v.len--; v.start++; } while (v.len > 0 && is_space(v.start[v.len - 1])) v.len--; return v; } static darray_matched_sval split_comma_separated_mlvo(struct xkb_context *ctx, enum rules_mlvo mlvo, const char *s) { darray_matched_sval arr = darray_new(); /* * Make sure the array returned by this function always includes at * least one value, e.g. "" -> { "" } and "," -> { "", "" }. */ if (!s) { struct matched_sval val = { .sval = { NULL, 0 } }; darray_append(arr, val); return arr; } while (true) { struct matched_sval val = { .sval = { s, 0 }, .matched = false, /* NOTE: Cannot store XKB_LAYOUT_INVALID */ .layout = OPTIONS_MATCH_ALL_GROUPS }; while (*s != '\0' && *s != ',' && *s != OPTIONS_GROUP_SPECIFIER_PREFIX) { s++; val.sval.len++; } val.sval = strip_spaces(val.sval); if (*s == OPTIONS_GROUP_SPECIFIER_PREFIX) { /* Handle numeric layout index */ s++; const char* const layout_start = s; xkb_layout_index_t layout = XKB_LAYOUT_INVALID; int count = parse_dec_to_uint32_t(s, SIZE_MAX, &layout); if (count > 0) { /* Note: 1-indexed layout */ s += count; if (layout == 0 || layout > XKB_MAX_GROUPS) { log_err(ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Invalid layout index %"PRIu32" " "for the RMVLO component: \"%.*s\"\n", layout, (unsigned int) val.sval.len, val.sval.start); } else if (mlvo != MLVO_OPTION) { log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "Layout index %"PRIu32" is not supported for " "the RMLVO component: \"%.*s\"\n", layout, (unsigned int) val.sval.len, val.sval.start); } else { val.layout = layout - 1; } } /* Consume until reaching next item or end of string */ const char* const layout_index_end = s; while (*s != '\0' && *s != ',') { s++; } if (count <= 0 || layout_index_end != s) { log_err(ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Invalid layout index \"%.*s\" for the RMLVO " "component \"%.*s\"; discarding specifier.\n", (unsigned int) (s - layout_start), layout_start, (unsigned int) val.sval.len, val.sval.start); val.layout = OPTIONS_MATCH_ALL_GROUPS; } } darray_append(arr, val); if (*s == '\0') break; if (*s == ',') s++; } return arr; } static struct matcher * matcher_new_from_rmlvo(const struct xkb_rmlvo_builder *rmlvo, const char **rules) { struct matcher *m = calloc(1, sizeof(*m)); if (!m) return NULL; m->ctx = rmlvo->ctx; /* Sanitize */ struct xkb_rule_names names = { .rules = rmlvo->rules, .model = rmlvo->model, /* Initial values only used to detect missing entries */ .layout = (darray_empty(rmlvo->layouts)) ? NULL : "x", .variant = (darray_empty(rmlvo->layouts)) ? NULL : "x", .options = (darray_empty(rmlvo->options)) ? NULL : "x", }; const enum RMLVO changed = xkb_context_sanitize_rule_names(rmlvo->ctx, &names); /* Initialize matcher with sanitized names, if relevant */ if (changed & RMLVO_RULES) { *rules = names.rules; } else { *rules = rmlvo->rules; } if (changed & RMLVO_MODEL) { m->rmlvo.model.sval.start = names.model; } else { m->rmlvo.model.sval.start = rmlvo->model; } m->rmlvo.model.sval.len = strlen_safe(rmlvo->model); m->rmlvo.model.layout = OPTIONS_MATCH_ALL_GROUPS; assert((changed & RMLVO_LAYOUT) || !(changed & RMLVO_VARIANT)); if (changed & RMLVO_LAYOUT) { /* Layout and variant are tied together */ m->rmlvo.layouts = split_comma_separated_mlvo(rmlvo->ctx, MLVO_LAYOUT, names.layout); m->rmlvo.variants = split_comma_separated_mlvo(rmlvo->ctx, MLVO_VARIANT, names.variant); if (darray_size(m->rmlvo.layouts) > darray_size(m->rmlvo.variants)) { /* Do not warn if no variants was provided */ if (!isempty(names.variant)) log_warn(m->ctx, XKB_LOG_MESSAGE_NO_ID, "More layouts than variants: \"%s\" vs. \"%s\".\n", names.layout ? names.layout : "(none)", names.variant ? names.variant : "(none)"); darray_resize0(m->rmlvo.variants, darray_size(m->rmlvo.layouts)); } else if (darray_size(m->rmlvo.layouts) < darray_size(m->rmlvo.variants)) { log_err(m->ctx, XKB_LOG_MESSAGE_NO_ID, "Less layouts than variants: \"%s\" vs. \"%s\".\n", names.layout ? names.layout : "(none)", names.variant ? names.variant : "(none)"); darray_resize(m->rmlvo.variants, darray_size(m->rmlvo.layouts)); darray_shrink(m->rmlvo.variants); } } else { struct xkb_rmlvo_builder_layout *layout; darray_foreach(layout, rmlvo->layouts) { struct matched_sval val = { .sval = { .start = layout->layout, .len = strlen_safe(layout->layout) }, .layout = OPTIONS_MATCH_ALL_GROUPS, .matched = false }; darray_append(m->rmlvo.layouts, val); val.sval.start = layout->variant; val.sval.len = strlen_safe(layout->variant); darray_append(m->rmlvo.variants, val); } } if (changed & RMLVO_OPTIONS) { m->rmlvo.options = split_comma_separated_mlvo(rmlvo->ctx, MLVO_OPTION, names.options); } else { struct xkb_rmlvo_builder_option *option; darray_foreach(option, rmlvo->options) { struct matched_sval val = { .sval = { .start = option->option, .len = strlen_safe(option->option), }, .layout = (option->layout) == XKB_LAYOUT_INVALID ? OPTIONS_MATCH_ALL_GROUPS : option->layout, .matched = false }; darray_append(m->rmlvo.options, val); } } return m; } static struct matcher * matcher_new_from_names(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo) { struct matcher *m = calloc(1, sizeof(*m)); if (!m) return NULL; m->ctx = ctx; m->rmlvo.model.sval.start = rmlvo->model; m->rmlvo.model.sval.len = strlen_safe(rmlvo->model); m->rmlvo.model.layout = OPTIONS_MATCH_ALL_GROUPS; m->rmlvo.layouts = split_comma_separated_mlvo(ctx, MLVO_LAYOUT, rmlvo->layout); m->rmlvo.variants = split_comma_separated_mlvo(ctx, MLVO_VARIANT, rmlvo->variant); m->rmlvo.options = split_comma_separated_mlvo(ctx, MLVO_OPTION, rmlvo->options); if (darray_size(m->rmlvo.layouts) > darray_size(m->rmlvo.variants)) { /* Do not warn if no variants was provided */ if (!isempty(rmlvo->variant)) log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "More layouts than variants: \"%s\" vs. \"%s\".\n", rmlvo->layout ? rmlvo->layout : "(none)", rmlvo->variant ? rmlvo->variant : "(none)"); darray_resize0(m->rmlvo.variants, darray_size(m->rmlvo.layouts)); } else if (darray_size(m->rmlvo.layouts) < darray_size(m->rmlvo.variants)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Less layouts than variants: \"%s\" vs. \"%s\".\n", rmlvo->layout ? rmlvo->layout : "(none)", rmlvo->variant ? rmlvo->variant : "(none)"); darray_resize(m->rmlvo.variants, darray_size(m->rmlvo.layouts)); darray_shrink(m->rmlvo.variants); } return m; } static void matcher_free(struct matcher *m) { if (!m) return; darray_free(m->rmlvo.layouts); darray_free(m->rmlvo.variants); darray_free(m->rmlvo.options); struct group *group; darray_foreach(group, m->groups) darray_free(group->elements); darray_free(m->pending_kccgst.buffer); darray_free(m->pending_kccgst.slices); for (kccgst_index_t i = 0; i < (kccgst_index_t) _KCCGST_NUM_ENTRIES; i++) darray_free(m->kccgst[i]); darray_free(m->groups); free(m); } static void matcher_group_start_new(struct matcher *m, struct sval name) { struct group group = { .name = name, .elements = darray_new() }; darray_append(m->groups, group); } static void matcher_group_add_element(struct matcher *m, struct scanner *s, struct sval element) { darray_append(darray_item(m->groups, darray_size(m->groups) - 1).elements, element); } static bool read_rules_file(struct xkb_context *ctx, struct matcher *matcher, unsigned int include_depth, FILE *file, const char *path); static void matcher_include(struct matcher *m, struct scanner *parent_scanner, unsigned int include_depth, struct sval inc) { if (include_depth >= MAX_INCLUDE_DEPTH) { scanner_err(parent_scanner, XKB_LOG_MESSAGE_NO_ID, "maximum include depth (%u) exceeded; " "maybe there is an include loop?", MAX_INCLUDE_DEPTH); return; } const char *stmt_file = inc.start; size_t stmt_file_len = inc.len; /* Process %-expansion, if any */ char buf[PATH_MAX] = {0}; const ssize_t expanded = expand_path(m->ctx, parent_scanner->file_name, stmt_file, stmt_file_len, FILE_TYPE_RULES, buf, sizeof(buf)); if (expanded < 0) { /* Error */ return; } else if (expanded > 0) { /* %-expanded */ stmt_file = buf; stmt_file_len = (size_t) expanded; assert(stmt_file[stmt_file_len] == '\0'); } /* Lookup the first candidate */ FILE* file; unsigned int offset = 0; const bool absolute_path = is_absolute_path(stmt_file); if (absolute_path) { /* Absolute path: no need for lookup in XKB paths */ if (!expanded) { /* No %expansion: ensure it’s NULL-terminated */ if (stmt_file_len < sizeof(buf)) { memcpy(buf, stmt_file, stmt_file_len); buf[stmt_file_len] = '\0'; stmt_file = buf; } else { log_err(m->ctx, XKB_ERROR_INVALID_PATH, "Path is too long: %zu > %zu, got raw path: %.*s\n", stmt_file_len, sizeof(buf), (unsigned int) stmt_file_len, stmt_file); return; } } else { /* %-expansion is always NULL-terminated */ assert(stmt_file[stmt_file_len] == '\0'); } file = fopen(stmt_file, "rb"); } else { /* Relative path: lookup the first XKB path */ if (unlikely(expanded)) { /* * Relative path after expansion * * Unlikely to happen, because %-expansion is meant to use absolute * paths. Considering that: * - we do not resolve paths before expansion, leading to unexpected * result here; * - we need the buffer afterwards, but it currently contains the * expanded path; * - this is an edge case; * we simply make the lookup fail. */ file = NULL; } else { file = FindFileInXkbPath(m->ctx, parent_scanner->file_name, stmt_file, stmt_file_len, FILE_TYPE_RULES, buf, sizeof(buf), &offset); } } while (file) { assert(strlen_safe(buf) < sizeof(buf)); bool ret = read_rules_file(m->ctx, m, include_depth + 1, file, buf); fclose(file); if (ret) return; /* Failed to parse rules or get all the components */ log_err(m->ctx, XKB_LOG_MESSAGE_NO_ID, "No components returned from included XKB rules \"%s\"\n", buf); if (absolute_path) { /* There is no point to search further if the path is absolute */ break; } /* Try next XKB path */ offset++; file = FindFileInXkbPath(m->ctx, parent_scanner->file_name, stmt_file, stmt_file_len, FILE_TYPE_RULES, buf, sizeof(buf), &offset); } log_err(m->ctx, XKB_LOG_MESSAGE_NO_ID, "Failed to open included XKB rules \"%.*s\"\n", (unsigned int) stmt_file_len, stmt_file); } static void matcher_mapping_start_new(struct matcher *m) { for (mlvo_index_t i = 0; i < (mlvo_index_t) _MLVO_NUM_ENTRIES; i++) m->mapping.mlvo_at_pos[i] = _MLVO_NUM_ENTRIES; for (kccgst_index_t i = 0; i < (kccgst_index_t) _KCCGST_NUM_ENTRIES; i++) m->mapping.kccgst_at_pos[i] = _KCCGST_NUM_ENTRIES; m->mapping.has_layout_idx_range = false; m->mapping.layout_idx = m->mapping.variant_idx = XKB_LAYOUT_INVALID; m->mapping.num_mlvo = m->mapping.num_kccgst = 0; m->mapping.defined_mlvo_mask = 0; m->mapping.defined_kccgst_mask = 0; m->mapping.active = true; } static int parse_layout_int_index(const char *s, size_t max_len, xkb_layout_index_t *out) { /* We expect a NULL-terminated string of at least length 3 */ assert(max_len >= 3); uint32_t val = 0; const int count = parse_dec_to_uint32_t(&s[1], max_len - 2, &val); if (count <= 0 || s[1 + count] != ']' || val == 0 || val > XKB_MAX_GROUPS) return -1; /* To zero-based index. */ *out = val - 1; return count + 2; /* == length "[index]" */ } /* Parse Kccgst layout index: * "[%i]" or "[n]", where "n" is a decimal number */ static int extract_layout_index(const char *s, size_t max_len, xkb_layout_index_t *out) { /* This function is pretty stupid, but works for now. */ *out = XKB_LAYOUT_INVALID; if (max_len < 3 || s[0] != '[') return -1; if (max_len > 3 && s[1] == '%' && s[2] == 'i' && s[3] == ']') { /* Special index: %i */ return 4; /* == length "[%i]" */ } /* Numeric index */ return parse_layout_int_index(s, max_len, out); } /* Special layout indices */ enum layout_index_ranges { LAYOUT_INDEX_SINGLE = XKB_LAYOUT_INVALID - 4, LAYOUT_INDEX_FIRST = XKB_LAYOUT_INVALID - 3, LAYOUT_INDEX_LATER = XKB_LAYOUT_INVALID - 2, LAYOUT_INDEX_ANY = XKB_LAYOUT_INVALID - 1 }; static_assert((xkb_layout_index_t) XKB_MAX_GROUPS < (xkb_layout_index_t) LAYOUT_INDEX_SINGLE, "Cannot define special indices"); static_assert((xkb_layout_index_t) LAYOUT_INDEX_SINGLE < (xkb_layout_index_t) LAYOUT_INDEX_FIRST && (xkb_layout_index_t) LAYOUT_INDEX_FIRST < (xkb_layout_index_t) LAYOUT_INDEX_LATER && (xkb_layout_index_t) LAYOUT_INDEX_LATER < (xkb_layout_index_t) LAYOUT_INDEX_ANY && (xkb_layout_index_t) LAYOUT_INDEX_ANY < (xkb_layout_index_t) XKB_LAYOUT_INVALID, "Special indices must respect certain order"); /* Parse index of layout/variant in MLVO mapping */ static int extract_mapping_layout_index(const char *s, size_t max_len, xkb_layout_index_t *out) { static const struct { const char* name; int length; enum layout_index_ranges range; } names[] = { { "single]", 7, LAYOUT_INDEX_SINGLE }, { "first]" , 6, LAYOUT_INDEX_FIRST }, { "later]" , 6, LAYOUT_INDEX_LATER }, { "any]" , 4, LAYOUT_INDEX_ANY }, }; /* Check for minimal `[` + index + `]` */ if (max_len < 3 || s[0] != '[') { *out = XKB_LAYOUT_INVALID; return -1; } /* Try named indices ranges */ for (unsigned int k = 0; k < ARRAY_SIZE(names); k++) { if (strncmp(&s[1], names[k].name, names[k].length) == 0) { *out = (xkb_layout_index_t) names[k].range; return names[k].length + 1; /* == length "[index]" */ } } /* Try numeric index */ *out = XKB_LAYOUT_INVALID; return parse_layout_int_index(s, max_len, out); } static inline bool is_mlvo_mask_defined(struct matcher *m, enum rules_mlvo mlvo) { return m->mapping.defined_mlvo_mask & (1u << mlvo); } static void matcher_mapping_set_mlvo(struct matcher *m, struct scanner *s, struct sval ident) { enum rules_mlvo mlvo; struct sval mlvo_sval; for (mlvo = 0; mlvo < _MLVO_NUM_ENTRIES; mlvo++) { mlvo_sval = rules_mlvo_svals[mlvo]; if (svaleq_prefix(mlvo_sval, ident)) break; } /* Not found. */ if (mlvo >= _MLVO_NUM_ENTRIES) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: \"%.*s\" is not a valid value here; " "ignoring rule set", (unsigned int) ident.len, ident.start); m->mapping.active = false; return; } if (is_mlvo_mask_defined(m, mlvo)) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: \"%.*s\" appears twice on the same line; " "ignoring rule set", (unsigned int) mlvo_sval.len, mlvo_sval.start); m->mapping.active = false; return; } /* If there are leftovers still, it must be an index. */ if (mlvo_sval.len < ident.len) { xkb_layout_index_t idx; int consumed = extract_mapping_layout_index(ident.start + mlvo_sval.len, ident.len - mlvo_sval.len, &idx); if ((int) (ident.len - mlvo_sval.len) != consumed) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: \"%.*s\" may only be followed by a " "valid group index; ignoring rule set", (unsigned int) mlvo_sval.len, mlvo_sval.start); m->mapping.active = false; return; } if (mlvo == MLVO_LAYOUT) { m->mapping.layout_idx = idx; } else if (mlvo == MLVO_VARIANT) { m->mapping.variant_idx = idx; } else { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: \"%.*s\" cannot be followed by a group " "index; ignoring rule set", (unsigned int) mlvo_sval.len, mlvo_sval.start); m->mapping.active = false; return; } } else if (mlvo == MLVO_LAYOUT) { m->mapping.layout_idx = (xkb_layout_index_t) LAYOUT_INDEX_SINGLE; } else if (mlvo == MLVO_VARIANT) { m->mapping.variant_idx = (xkb_layout_index_t) LAYOUT_INDEX_SINGLE; } /* Check that if both layout and variant are defined, then they must have * the same index */ if (((mlvo == MLVO_LAYOUT && is_mlvo_mask_defined(m, MLVO_VARIANT)) || (mlvo == MLVO_VARIANT && is_mlvo_mask_defined(m, MLVO_LAYOUT))) && m->mapping.layout_idx != m->mapping.variant_idx) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: \"layout\" index must be the same as the " "\"variant\" index"); m->mapping.active = false; return; } m->mapping.mlvo_at_pos[m->mapping.num_mlvo] = mlvo; m->mapping.defined_mlvo_mask |= (mlvo_mask_t) 1u << mlvo; m->mapping.num_mlvo++; } static void matcher_mapping_set_layout_bounds(struct matcher *m) { /* Handle case where one of the index is XKB_LAYOUT_INVALID */ xkb_layout_index_t idx = MIN(m->mapping.layout_idx, m->mapping.variant_idx); switch (idx) { case XKB_LAYOUT_INVALID: /* No layout nor variant */ assert(!is_mlvo_mask_defined(m, MLVO_LAYOUT) && !is_mlvo_mask_defined(m, MLVO_VARIANT)); m->mapping.has_layout_idx_range = false; m->mapping.layout_idx_min = XKB_LAYOUT_INVALID; m->mapping.layout_idx_max = XKB_LAYOUT_INVALID; m->mapping.layouts_candidates_mask = 0x1; break; case LAYOUT_INDEX_LATER: m->mapping.has_layout_idx_range = true; m->mapping.layout_idx_min = 1; m->mapping.layout_idx_max = MIN(XKB_MAX_GROUPS, darray_size(m->rmlvo.layouts)); m->mapping.layouts_candidates_mask = (xkb_layout_mask_t) /* All but the first layout */ ((UINT64_C(1) << m->mapping.layout_idx_max) - UINT64_C(1)) & ~UINT64_C(1); break; case LAYOUT_INDEX_ANY: m->mapping.has_layout_idx_range = true; m->mapping.layout_idx_min = 0; m->mapping.layout_idx_max = MIN(XKB_MAX_GROUPS, darray_size(m->rmlvo.layouts)); m->mapping.layouts_candidates_mask = (xkb_layout_mask_t) /* All layouts */ (UINT64_C(1) << m->mapping.layout_idx_max) - UINT64_C(1); break; case LAYOUT_INDEX_SINGLE: case LAYOUT_INDEX_FIRST: /* No index or first index */ idx = 0; /* fallthrough */ default: /* Mere layout index */ m->mapping.has_layout_idx_range = false; m->mapping.layout_idx_min = idx; m->mapping.layout_idx_max = idx + 1; m->mapping.layouts_candidates_mask = UINT32_C(1) << idx; } } static void matcher_mapping_set_kccgst(struct matcher *m, struct scanner *s, struct sval ident) { enum rules_kccgst kccgst; struct sval kccgst_sval; for (kccgst = 0; kccgst < _KCCGST_NUM_ENTRIES; kccgst++) { kccgst_sval = rules_kccgst_svals[kccgst]; if (svaleq(rules_kccgst_svals[kccgst], ident)) break; } /* Not found. */ if (kccgst >= _KCCGST_NUM_ENTRIES) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: \"%.*s\" is not a valid value here; " "ignoring rule set", (unsigned int) ident.len, ident.start); m->mapping.active = false; return; } if (m->mapping.defined_kccgst_mask & (1u << kccgst)) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: \"%.*s\" appears twice on the same line; " "ignoring rule set", (unsigned int) kccgst_sval.len, kccgst_sval.start); m->mapping.active = false; return; } m->mapping.kccgst_at_pos[m->mapping.num_kccgst] = kccgst; m->mapping.defined_kccgst_mask |= (kccgst_mask_t) 1u << kccgst; m->mapping.num_kccgst++; } static bool matcher_mapping_verify(struct matcher *m, struct scanner *s) { if (m->mapping.num_mlvo == 0) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: must have at least one value on the left " "hand side; ignoring rule set"); goto skip; } if (m->mapping.num_kccgst == 0) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid mapping: must have at least one value on the right " "hand side; ignoring rule set"); goto skip; } /* * This following is very stupid, but this is how it works. * See the "Notes" section in the overview above. */ if (is_mlvo_mask_defined(m, MLVO_LAYOUT)) { assert(m->mapping.layout_idx != XKB_LAYOUT_INVALID); switch (m->mapping.layout_idx) { case LAYOUT_INDEX_SINGLE: /* Layout rule without index matches when * exactly 1 layout is specified */ if (darray_size(m->rmlvo.layouts) > 1) goto skip; break; case LAYOUT_INDEX_ANY: case LAYOUT_INDEX_LATER: case LAYOUT_INDEX_FIRST: /* No restrictions */ break; default: /* Layout rule with index matches when at least 2 layouts are * specified. Index must be in valid range. */ if (darray_size(m->rmlvo.layouts) < 2 || m->mapping.layout_idx >= darray_size(m->rmlvo.layouts)) goto skip; } } if (is_mlvo_mask_defined(m, MLVO_VARIANT)) { assert(m->mapping.variant_idx != XKB_LAYOUT_INVALID); switch (m->mapping.variant_idx) { case LAYOUT_INDEX_SINGLE: /* Variant rule without index matches * when exactly 1 variant is specified */ if (darray_size(m->rmlvo.variants) > 1) goto skip; break; case LAYOUT_INDEX_ANY: case LAYOUT_INDEX_LATER: case LAYOUT_INDEX_FIRST: /* No restriction */ break; default: /* Variant rule with index matches when at least 2 variants are * specified. Index must be in valid range. */ if (darray_size(m->rmlvo.variants) < 2 || m->mapping.variant_idx >= darray_size(m->rmlvo.variants)) goto skip; } } return true; skip: m->mapping.active = false; return false; } static void matcher_rule_start_new(struct matcher *m) { memset(&m->rule, 0, sizeof(m->rule)); m->rule.skip = !m->mapping.active; } static void matcher_rule_set_mlvo_common(struct matcher *m, struct scanner *s, struct sval ident, enum mlvo_match_type match_type) { if (m->rule.num_mlvo_values >= m->mapping.num_mlvo) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid rule: has more values than the mapping line; " "ignoring rule"); m->rule.skip = true; return; } m->rule.match_type_at_pos[m->rule.num_mlvo_values] = match_type; m->rule.mlvo_value_at_pos[m->rule.num_mlvo_values] = ident; m->rule.num_mlvo_values++; } static void matcher_rule_set_mlvo_wildcard(struct matcher *m, struct scanner *s, enum mlvo_match_type match_type) { struct sval dummy = { NULL, 0 }; matcher_rule_set_mlvo_common(m, s, dummy, match_type); } static void matcher_rule_set_mlvo_group(struct matcher *m, struct scanner *s, struct sval ident) { matcher_rule_set_mlvo_common(m, s, ident, MLVO_MATCH_GROUP); } static void matcher_rule_set_mlvo(struct matcher *m, struct scanner *s, struct sval ident) { matcher_rule_set_mlvo_common(m, s, ident, MLVO_MATCH_NORMAL); } static void matcher_rule_set_kccgst(struct matcher *m, struct scanner *s, struct sval ident) { if (m->rule.num_kccgst_values >= m->mapping.num_kccgst) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid rule: has more values than the mapping line; " "ignoring rule"); m->rule.skip = true; return; } m->rule.kccgst_value_at_pos[m->rule.num_kccgst_values] = ident; m->rule.num_kccgst_values++; } static bool match_group(struct matcher *m, struct sval group_name, struct sval to) { struct group *group = NULL; struct sval *element; bool found = false; darray_foreach(group, m->groups) { if (svaleq(group->name, group_name)) { found = true; break; } } if (!found) { /* * rules/evdev intentionally uses some undeclared group names * in rules (e.g. commented group definitions which may be * uncommented if needed). So we continue silently. */ return false; } darray_foreach(element, group->elements) if (svaleq(to, *element)) return true; return false; } static bool match_value(struct matcher *m, struct sval val, struct sval to, enum mlvo_match_type match_type, enum wildcard_match_type wildcard_type) { switch (match_type) { case MLVO_MATCH_WILDCARD_LEGACY: /* Match empty values only if explicitly required */ return wildcard_type == WILDCARD_MATCH_ALL || !!to.len; case MLVO_MATCH_WILDCARD_NONE: return !to.len; case MLVO_MATCH_WILDCARD_SOME: return !!to.len; case MLVO_MATCH_WILDCARD_ANY: /* Contrary to the legacy ‘*’, this wild card *always* matches */ return true; case MLVO_MATCH_GROUP: return match_group(m, val, to); default: assert(match_type == MLVO_MATCH_NORMAL); return svaleq(val, to); } } static bool match_value_and_mark(struct matcher *m, struct sval val, struct matched_sval *to, enum mlvo_match_type match_type, enum wildcard_match_type wildcard_type) { bool matched = match_value(m, val, to->sval, match_type, wildcard_type); if (matched) to->matched = true; return matched; } /* * This function performs %-expansion on @value (see overview above), * and appends the result to @expanded. */ static bool expand_rmlvo_in_kccgst_value(struct matcher *m, struct scanner *s, struct sval value, xkb_layout_index_t layout_idx, darray_char *expanded, size_t *i) { const char *str = value.start; /* * Some ugly hand-lexing here, but going through the scanner is more * trouble than it's worth, and the format is ugly on its own merit. */ enum rules_mlvo mlv; xkb_layout_index_t idx; char pfx, sfx; struct matched_sval *expanded_value; /* %i not as layout/variant index "%l[%i]" but as qualifier ":%i" */ if (str[*i] == 'i' && (*i + 1 == value.len || is_merge_mode_prefix(str[*i + 1]))) { if (layout_idx == XKB_LAYOUT_INVALID) { scanner_err( s, XKB_ERROR_RULES_INVALID_LAYOUT_INDEX_PERCENT_EXPANSION, "Invalid %%i in %%-expansion: there is no corresponding " "layout nor variant in the MLVO fields of the rules header." ); goto error; } (*i)++; char index_str[MAX_LAYOUT_INDEX_STR_LENGTH + 1]; int count = snprintf(index_str, sizeof(index_str), "%"PRIu32, layout_idx + 1); darray_appends_nullterminate(*expanded, index_str, count); return true; } pfx = sfx = 0; /* Check for prefix. */ if (str[*i] == '(' || is_merge_mode_prefix(str[*i]) || str[*i] == '_' || str[*i] == '-') { pfx = str[*i]; if (str[*i] == '(') sfx = ')'; if (++(*i) >= value.len) goto error; } /* Mandatory model/layout/variant specifier. */ switch (str[(*i)++]) { case 'm': mlv = MLVO_MODEL; break; case 'l': mlv = MLVO_LAYOUT; break; case 'v': mlv = MLVO_VARIANT; break; default: goto error; } /* Check for index. */ idx = XKB_LAYOUT_INVALID; bool expanded_index = false; if (*i < value.len && str[*i] == '[') { if (mlv != MLVO_LAYOUT && mlv != MLVO_VARIANT) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid index in %%-expansion; " "may only index layout or variant"); goto error; } int consumed = extract_layout_index(str + (*i), value.len - (*i), &idx); if (consumed == -1) goto error; if (idx == XKB_LAYOUT_INVALID) { /* %i encountered */ assert(layout_idx != XKB_LAYOUT_INVALID); idx = layout_idx; expanded_index = true; } *i += consumed; } /* Check for suffix, if there supposed to be one. */ if (sfx != 0) { if (*i >= value.len) goto error; if (str[(*i)++] != sfx) goto error; } /* Get the expanded value. */ expanded_value = NULL; if (mlv == MLVO_LAYOUT) { if (idx == XKB_LAYOUT_INVALID) { /* No index provided: match only if single layout */ if (darray_size(m->rmlvo.layouts) == 1) expanded_value = &darray_item(m->rmlvo.layouts, 0); /* Some index provided: expand only if it is %i or * if there are multiple layouts */ } else if (idx < darray_size(m->rmlvo.layouts) && (expanded_index || darray_size(m->rmlvo.layouts) > 1)) { expanded_value = &darray_item(m->rmlvo.layouts, idx); } } else if (mlv == MLVO_VARIANT) { if (idx == XKB_LAYOUT_INVALID) { /* No index provided: match only if single variant */ if (darray_size(m->rmlvo.variants) == 1) expanded_value = &darray_item(m->rmlvo.variants, 0); /* Some index provided: expand only if it is %i or * if there are multiple variants */ } else if (idx < darray_size(m->rmlvo.variants) && (expanded_index || darray_size(m->rmlvo.variants) > 1)) { expanded_value = &darray_item(m->rmlvo.variants, idx); } } else if (mlv == MLVO_MODEL) { expanded_value = &m->rmlvo.model; } /* If we didn't get one, skip silently. */ if (!expanded_value || expanded_value->sval.len == 0) { return true; } if (pfx != 0) darray_appends_nullterminate(*expanded, &pfx, 1); darray_appends_nullterminate(*expanded, expanded_value->sval.start, (darray_size_t) expanded_value->sval.len); if (sfx != 0) darray_appends_nullterminate(*expanded, &sfx, 1); expanded_value->matched = true; return true; error: scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid %%-expansion in value; not used"); return false; } /* * This function performs :all replacement on @value (see overview above), * and appends the result to @expanded. */ static void expand_qualifier_in_kccgst_value( struct matcher *m, struct scanner *s, struct sval value, darray_char *expanded, bool has_layout_idx_range, bool has_separator, darray_size_t prefix_idx, size_t *i) { const char *str = value.start; /* “all” followed by nothing or by a layout separator */ if ((*i + 3 <= value.len || is_merge_mode_prefix(str[*i + 3])) && str[*i] == 'a' && str[*i+1] == 'l' && str[*i+2] == 'l') { if (has_layout_idx_range) scanner_vrb(s, XKB_LOG_VERBOSITY_DETAILED, XKB_LOG_MESSAGE_NO_ID, "Using :all qualifier with indices range " "is not recommended."); /* Add at least one layout */ darray_appends_nullterminate(*expanded, "1", 1); /* Check for more layouts (slow path) */ if (darray_size(m->rmlvo.layouts) > 1) { char layout_index[MAX_LAYOUT_INDEX_STR_LENGTH + 1]; const darray_size_t prefix_length = darray_size(*expanded) - prefix_idx - 1; for (xkb_layout_index_t l = 1; l < MIN(XKB_MAX_GROUPS, darray_size(m->rmlvo.layouts)); l++) { if (!has_separator) darray_append(*expanded, MERGE_DEFAULT_PREFIX); /* Append prefix */ darray_appends_nullterminate(*expanded, &darray_item(*expanded, prefix_idx), prefix_length); /* Append index */ int count = snprintf(layout_index, sizeof(layout_index), "%"PRIu32, l + 1); darray_appends_nullterminate(*expanded, layout_index, count); } } *i += 3; } } static inline void #ifdef _MSC_VER concat_kccgst(darray_char *into, darray_size_t size, _In_reads_(size) const char* from) #else concat_kccgst(darray_char *into, darray_size_t size, const char from[static size]) #endif { /* * Appending bar to foo -> foo (not an error if this happens) * Appending +bar to foo -> foo+bar * Appending bar to +foo -> bar+foo * Appending +bar to +foo -> +foo+bar */ const bool from_plus = is_merge_mode_prefix(from[0]); if (from_plus || darray_empty(*into)) { darray_appends_nullterminate(*into, from, size); } else { const char ch = (char) (darray_empty(*into) ? '\0' : darray_item(*into, 0)); const bool into_plus = is_merge_mode_prefix(ch); if (into_plus) darray_prepends_nullterminate(*into, from, size); } } /* * This function performs %-expansion and :all-expansion on @value * (see overview above), and appends the result to @to. */ static bool append_expanded_kccgst_value(struct matcher *m, struct scanner *s, bool merge, darray_char *to, struct sval value, xkb_layout_index_t layout_idx) { const char *str = value.start; darray_char expanded = darray_new(); darray_size_t last_item_idx = 0; bool has_separator = false; for (size_t i = 0; i < value.len; ) { /* Check if that's a start of an expansion or qualifier */ switch (str[i]) { /* Qualifier */ case ':': darray_appends_nullterminate(expanded, &str[i++], 1); expand_qualifier_in_kccgst_value(m, s, value, &expanded, m->mapping.has_layout_idx_range, has_separator, last_item_idx, &i); break; /* Expansion */ case '%': i++; if (i >= value.len || !expand_rmlvo_in_kccgst_value(m, s, value, layout_idx, &expanded, &i)) goto error; break; /* New item */ case MERGE_OVERRIDE_PREFIX: case MERGE_AUGMENT_PREFIX: case MERGE_REPLACE_PREFIX: darray_appends_nullterminate(expanded, &str[i++], 1); last_item_idx = darray_size(expanded) - 1; has_separator = true; break; /* Just a normal character. */ default: darray_appends_nullterminate(expanded, &str[i++], 1); } } /* See note: “Layout index ranges and merging KcCGST values” */ if (merge) { if (!darray_empty(expanded)) concat_kccgst(to, darray_size(expanded), darray_items(expanded)); } else { darray_concat(*to, expanded); } darray_free(expanded); return true; error: darray_free(expanded); return false; } static bool matcher_append_pending_kccgst(struct matcher *m) { if (!m->mapping.has_layout_idx_range) return true; /* * Handle pending KcCGST values * See note: “Layout index ranges and merging KcCGST values” */ for (kccgst_index_t i = 0; i < m->mapping.num_kccgst; i++) { const enum rules_kccgst kccgst = m->mapping.kccgst_at_pos[i]; /* For each relevant layout, append the relevant KcCGST values to * the output. */ for (xkb_layout_index_t layout = m->mapping.layout_idx_min; layout < m->mapping.layout_idx_max; layout++) { /* There may be multiple values to add if the rule set involved * options. Process them sequentially. */ register const struct kccgst_buffer* const buf = &m->pending_kccgst; size_t offset = 0; for (darray_size_t k = 0; k < darray_size(buf->slices); k++) { register const struct kccgst_buffer_slice * const slice = &darray_item(buf->slices, k); if (slice->kccgst == kccgst && slice->layout == layout && slice->length) concat_kccgst(&m->kccgst[kccgst], slice->length, darray_items(buf->buffer) + offset); offset += slice->length; } } } /* Ensure we won’t come here before the next relevant rule set */ m->mapping.has_layout_idx_range = false; return true; } static void matcher_rule_verify(struct matcher *m, struct scanner *s) { if (m->rule.num_mlvo_values != m->mapping.num_mlvo || m->rule.num_kccgst_values != m->mapping.num_kccgst) { scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "invalid rule: must have same number of values " "as mapping line; ignoring rule"); m->rule.skip = true; } } static void matcher_rule_apply_if_matches(struct matcher *m, struct scanner *s) { /* Initial candidates (used if m->mapping.has_layout_idx_range == true) */ xkb_layout_mask_t candidate_layouts = m->mapping.layouts_candidates_mask; xkb_layout_index_t idx; /* Loop over MLVO pattern components */ for (mlvo_index_t i = 0; i < m->mapping.num_mlvo; i++) { enum rules_mlvo mlvo = m->mapping.mlvo_at_pos[i]; struct sval value = m->rule.mlvo_value_at_pos[i]; enum mlvo_match_type match_type = m->rule.match_type_at_pos[i]; struct matched_sval *to; bool matched = false; /* NOTE: Wild card * matches empty values only for model and options, as * implemented in libxkbfile and xserver. The reason for such different * treatment is not documented. */ if (mlvo == MLVO_MODEL) { to = &m->rmlvo.model; matched = match_value_and_mark(m, value, to, match_type, WILDCARD_MATCH_ALL); } else if (m->mapping.has_layout_idx_range) { /* Special index: loop over the index range */ for (idx = m->mapping.layout_idx_min; idx < m->mapping.layout_idx_max && candidate_layouts; idx++) { /* Process only if index not skipped */ const xkb_layout_mask_t mask = UINT32_C(1) << idx; if (candidate_layouts & mask) { switch (mlvo) { case MLVO_LAYOUT: to = &darray_item(m->rmlvo.layouts, idx); if (match_value_and_mark(m, value, to, match_type, WILDCARD_MATCH_NONEMPTY)) { /* Mark matched, keep index */ matched = true; } else { /* Not matched, remove index */ candidate_layouts &= ~mask; } break; case MLVO_VARIANT: to = &darray_item(m->rmlvo.variants, idx); if (match_value_and_mark(m, value, to, match_type, WILDCARD_MATCH_NONEMPTY)) { /* Mark matched, keep index */ matched = true; } else { /* Not matched, remove index */ candidate_layouts &= ~mask; } break; default: assert(mlvo == MLVO_OPTION); bool found_option = false; darray_foreach(to, m->rmlvo.options) { /* * Skip if layout-specific option and the target * layout does not match. */ if (to->layout != OPTIONS_MATCH_ALL_GROUPS && to->layout != idx) continue; if (match_value_and_mark(m, value, to, match_type, WILDCARD_MATCH_ALL)) { /* Mark matched, keep index */ matched = true; found_option = true; break; } } if (!found_option) { /* Not matched, remove index */ candidate_layouts &= ~mask; } } } } } else { /* Numeric index or no index */ switch (mlvo) { case MLVO_LAYOUT: to = &darray_item(m->rmlvo.layouts, m->mapping.layout_idx_min); matched = match_value_and_mark(m, value, to, match_type, WILDCARD_MATCH_NONEMPTY); break; case MLVO_VARIANT: to = &darray_item(m->rmlvo.variants, m->mapping.layout_idx_min); matched = match_value_and_mark(m, value, to, match_type, WILDCARD_MATCH_NONEMPTY); break; default: assert(mlvo == MLVO_OPTION); darray_foreach(to, m->rmlvo.options) { /* * Skip if it is a layout-specific option and either: * - the rule has no layout nor variant field * (layout_idx_min == XKB_LAYOUT_INVALID), or * - the target layout index does not match. */ if (to->layout != OPTIONS_MATCH_ALL_GROUPS && to->layout != m->mapping.layout_idx_min) continue; matched = match_value_and_mark(m, value, to, match_type, WILDCARD_MATCH_ALL); if (matched) break; } } } if (!matched) return; } if (m->mapping.has_layout_idx_range) { /* Special index: loop over the index range */ for (idx = m->mapping.layout_idx_min; idx < m->mapping.layout_idx_max; idx++) { if (candidate_layouts & (UINT32_C(1) << idx)) { for (kccgst_index_t i = 0; i < m->mapping.num_kccgst; i++) { const enum rules_kccgst kccgst = m->mapping.kccgst_at_pos[i]; const struct sval value = m->rule.kccgst_value_at_pos[i]; /* * [NOTE] Layout index ranges and merging KcCGST values * * Layout indices match following first the order of the * rules in the file, then their natural order. So do not * merge with the output for now but buffer the resulting * KcCGST value and wait reaching the end of the rule set. * * Because the rule set may also involve options, it may * match multiple times for the *same* layout index. So * buffer the result of *each* match. * * When the end of the rule set is reached, merge buffered * KcCGST sequentially, following first the layouts order, * then the order of the rules in the file. * * Example: * * ! model = symbols * * = pc * ! layout[any] option = symbols * C 1 = +c1:%i * C 2 = +c2:%i * B 3 = skip * B 4 = +b:%i * * The result of {layout: "A,B,C", options: "4,3,2,1"} is: * symbols = pc+b:2+c1:3+c2:3. * * - `skip` was dropped because it has no explicit merge * mode; * - although every rule was matched in order, the resulting * order of the symbols follows the order of the layouts, * so `+b` appears before `+c1` and `+c2`. * - the relative order of the options for layout C follows * the order within the rule set, not the order of RMLVO. */ register struct kccgst_buffer * const buf = &m->pending_kccgst; const darray_size_t prev_buffer_length = darray_size(buf->buffer); append_expanded_kccgst_value(m, s, false, &buf->buffer, value, idx); const uint32_t length = (uint32_t) (darray_size(buf->buffer) - prev_buffer_length); const struct kccgst_buffer_slice slice = { .length = length, .kccgst = kccgst, .layout = idx }; darray_append(buf->slices, slice); } } } } else { /* Numeric index or no index */ for (kccgst_index_t i = 0; i < m->mapping.num_kccgst; i++) { enum rules_kccgst kccgst = m->mapping.kccgst_at_pos[i]; struct sval value = m->rule.kccgst_value_at_pos[i]; append_expanded_kccgst_value(m, s, true, &m->kccgst[kccgst], value, m->mapping.layout_idx_min); } } /* * If a rule matches in a rule set, the rest of the set should be * skipped. However, rule sets matching against options may contain * several legitimate rules, so they are processed entirely. */ if (!(is_mlvo_mask_defined(m, MLVO_OPTION))) { m->mapping.layouts_candidates_mask &= ~candidate_layouts; } } static enum rules_token gettok(struct matcher *m, struct scanner *s) { return lex(s, &m->val); } static bool matcher_match(struct matcher *m, struct scanner *s, unsigned int include_depth, const char *string, size_t len, const char *file_name) { enum rules_token tok; if (!m) return false; initial: switch (tok = gettok(m, s)) { case TOK_BANG: goto bang; case TOK_END_OF_LINE: goto initial; case TOK_END_OF_FILE: goto finish; default: goto unexpected; } bang: switch (tok = gettok(m, s)) { case TOK_GROUP_NAME: matcher_group_start_new(m, m->val.string); goto group_name; case TOK_INCLUDE: goto include_statement; case TOK_IDENTIFIER: matcher_mapping_start_new(m); matcher_mapping_set_mlvo(m, s, m->val.string); goto mapping_mlvo; default: goto unexpected; } group_name: switch (tok = gettok(m, s)) { case TOK_EQUALS: goto group_element; default: goto unexpected; } group_element: switch (tok = gettok(m, s)) { case TOK_IDENTIFIER: matcher_group_add_element(m, s, m->val.string); goto group_element; case TOK_END_OF_LINE: goto initial; default: goto unexpected; } include_statement: switch (tok = gettok(m, s)) { case TOK_IDENTIFIER: matcher_include(m, s, include_depth, m->val.string); goto include_statement_end; default: goto unexpected; } include_statement_end: switch (tok = gettok(m, s)) { case TOK_END_OF_LINE: goto initial; default: goto unexpected; } mapping_mlvo: switch (tok = gettok(m, s)) { case TOK_IDENTIFIER: if (m->mapping.active) matcher_mapping_set_mlvo(m, s, m->val.string); goto mapping_mlvo; case TOK_EQUALS: goto mapping_kccgst; default: goto unexpected; } mapping_kccgst: switch (tok = gettok(m, s)) { case TOK_IDENTIFIER: if (m->mapping.active) matcher_mapping_set_kccgst(m, s, m->val.string); goto mapping_kccgst; case TOK_END_OF_LINE: if (m->mapping.active && matcher_mapping_verify(m, s)) { matcher_mapping_set_layout_bounds(m); if (m->mapping.has_layout_idx_range) { /* Lazily reset buffers for layout index ranges. * We’ll reuse the allocations. */ darray_size(m->pending_kccgst.buffer) = 0; darray_size(m->pending_kccgst.slices) = 0; } } goto rule_mlvo_first; default: goto unexpected; } rule_mlvo_first: switch (tok = gettok(m, s)) { case TOK_BANG: matcher_append_pending_kccgst(m); goto bang; case TOK_END_OF_LINE: goto rule_mlvo_first; case TOK_END_OF_FILE: matcher_append_pending_kccgst(m); goto finish; default: matcher_rule_start_new(m); goto rule_mlvo_no_tok; } rule_mlvo: tok = gettok(m, s); rule_mlvo_no_tok: switch (tok) { case TOK_IDENTIFIER: if (!m->rule.skip) { if (m->val.string.len == 1 && m->val.string.start[0] == '+') matcher_rule_set_mlvo_wildcard(m, s, MLVO_MATCH_WILDCARD_SOME); else matcher_rule_set_mlvo(m, s, m->val.string); } goto rule_mlvo; case TOK_WILD_CARD_STAR: if (!m->rule.skip) matcher_rule_set_mlvo_wildcard(m, s, MLVO_MATCH_WILDCARD_LEGACY); goto rule_mlvo; case TOK_WILD_CARD_NONE: if (!m->rule.skip) matcher_rule_set_mlvo_wildcard(m, s, MLVO_MATCH_WILDCARD_NONE); goto rule_mlvo; case TOK_WILD_CARD_SOME: if (!m->rule.skip) matcher_rule_set_mlvo_wildcard(m, s, MLVO_MATCH_WILDCARD_SOME); goto rule_mlvo; case TOK_WILD_CARD_ANY: if (!m->rule.skip) matcher_rule_set_mlvo_wildcard(m, s, MLVO_MATCH_WILDCARD_ANY); goto rule_mlvo; case TOK_GROUP_NAME: if (!m->rule.skip) matcher_rule_set_mlvo_group(m, s, m->val.string); goto rule_mlvo; case TOK_EQUALS: goto rule_kccgst; default: goto unexpected; } rule_kccgst: switch (tok = gettok(m, s)) { case TOK_IDENTIFIER: if (!m->rule.skip) matcher_rule_set_kccgst(m, s, m->val.string); goto rule_kccgst; case TOK_END_OF_LINE: if (!m->rule.skip) matcher_rule_verify(m, s); if (!m->rule.skip) matcher_rule_apply_if_matches(m, s); goto rule_mlvo_first; default: goto unexpected; } unexpected: switch (tok) { case TOK_ERROR: goto error; default: goto state_error; } finish: return true; state_error: scanner_err(s, XKB_ERROR_INVALID_RULES_SYNTAX, "unexpected token"); error: return false; } static bool read_rules_file(struct xkb_context *ctx, struct matcher *matcher, unsigned int include_depth, FILE *file, const char *path) { bool ret; char *string; size_t size; struct scanner scanner; if (!map_file(file, &string, &size)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Couldn't read rules file \"%s\": %s\n", path, strerror(errno)); return false; } scanner_init(&scanner, matcher->ctx, string, size, path, NULL); /* Basic detection of wrong character encoding. The first character relevant to the grammar must be ASCII: whitespace, !, / (for comment) */ if (!scanner_check_supported_char_encoding(&scanner)) { scanner_err(&scanner, XKB_ERROR_INVALID_FILE_ENCODING, "This could be a file encoding issue. " "Supported encodings must be backward compatible with ASCII."); scanner_err(&scanner, XKB_ERROR_INVALID_FILE_ENCODING, "E.g. ISO/CEI 8859 and UTF-8 are supported " "but UTF-16, UTF-32 and CP1026 are not."); unmap_file(string, size); return false; } ret = matcher_match(matcher, &scanner, include_depth, string, size, path); unmap_file(string, size); return ret; } static bool xkb_resolve_rules(struct xkb_context *ctx, const char* rules, struct matcher *matcher, struct xkb_component_names *out, xkb_layout_index_t *explicit_layouts) { bool ret = false; FILE *file; struct matched_sval *mval; unsigned int offset = 0; char path[PATH_MAX]; file = FindFileInXkbPath(ctx, "(unknown)", rules, strlen(rules), FILE_TYPE_RULES, path, sizeof(path), &offset); if (!file) { log_err(ctx, XKB_ERROR_CANNOT_RESOLVE_RMLVO, "Cannot load XKB rules \"%s\"\n", rules); goto err_out; } ret = read_rules_file(ctx, matcher, 0, file, path); if (!ret || darray_empty(matcher->kccgst[KCCGST_KEYCODES]) || darray_empty(matcher->kccgst[KCCGST_TYPES]) || darray_empty(matcher->kccgst[KCCGST_COMPAT]) || /* darray_empty(matcher->kccgst[KCCGST_GEOMETRY]) || */ darray_empty(matcher->kccgst[KCCGST_SYMBOLS])) { log_err(ctx, XKB_ERROR_CANNOT_RESOLVE_RMLVO, "No components returned from XKB rules \"%s\"\n", path); ret = false; goto err_out; } darray_steal(matcher->kccgst[KCCGST_KEYCODES], &out->keycodes, NULL); darray_steal(matcher->kccgst[KCCGST_TYPES], &out->types, NULL); darray_steal(matcher->kccgst[KCCGST_COMPAT], &out->compatibility, NULL); darray_steal(matcher->kccgst[KCCGST_SYMBOLS], &out->symbols, NULL); darray_steal(matcher->kccgst[KCCGST_GEOMETRY], &out->geometry, NULL); mval = &matcher->rmlvo.model; if (!mval->matched && mval->sval.len > 0) log_err(matcher->ctx, XKB_ERROR_CANNOT_RESOLVE_RMLVO, "Unrecognized RMLVO model \"%.*s\" was ignored\n", (unsigned int) mval->sval.len, mval->sval.start); darray_foreach(mval, matcher->rmlvo.layouts) if (!mval->matched && mval->sval.len > 0) log_err(matcher->ctx, XKB_ERROR_CANNOT_RESOLVE_RMLVO, "Unrecognized RMLVO layout \"%.*s\" was ignored\n", (unsigned int) mval->sval.len, mval->sval.start); darray_foreach(mval, matcher->rmlvo.variants) if (!mval->matched && mval->sval.len > 0) log_err(matcher->ctx, XKB_ERROR_CANNOT_RESOLVE_RMLVO, "Unrecognized RMLVO variant \"%.*s\" was ignored\n", (unsigned int) mval->sval.len, mval->sval.start); darray_foreach(mval, matcher->rmlvo.options) if (!mval->matched && mval->sval.len > 0) log_err(matcher->ctx, XKB_ERROR_CANNOT_RESOLVE_RMLVO, "Unrecognized RMLVO option \"%.*s\" was ignored\n", (unsigned int) mval->sval.len, mval->sval.start); /* Set the number of explicit layouts */ if (out->symbols != NULL && explicit_layouts != NULL) { *explicit_layouts = 1; /* at least one group */ const char *symbols = out->symbols; /* Take the highest modifier */ while ((symbols = strchr(symbols, ':')) != NULL && symbols[1] != '\0') { xkb_layout_index_t group = 0; const int count = parse_dec_to_uint32_t(++symbols, SIZE_MAX, &group); /* Update only when valid group index, but continue parsing * even on invalid ones, as we do not handle them here. */ if (count > 0 && (symbols[count] == '\0' || is_merge_mode_prefix(symbols[count])) && group > 0 && group <= XKB_MAX_GROUPS) { *explicit_layouts = MAX(*explicit_layouts, group); symbols += count; } } } err_out: if (file) fclose(file); return ret; } bool xkb_components_from_rmlvo_builder(const struct xkb_rmlvo_builder *rmlvo, struct xkb_component_names *out, xkb_layout_index_t *explicit_layouts) { const char *rules = rmlvo->rules; struct matcher *matcher = matcher_new_from_rmlvo(rmlvo, &rules); if (!matcher) return false; const bool ret = xkb_resolve_rules(rmlvo->ctx, rules, matcher, out, explicit_layouts); matcher_free(matcher); return ret; } bool xkb_components_from_rules_names(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo, struct xkb_component_names *out, xkb_layout_index_t *explicit_layouts) { struct matcher *matcher = matcher_new_from_names(ctx, rmlvo); if (!matcher) return false; const bool ret = xkb_resolve_rules(ctx, rmlvo->rules, matcher, out, explicit_layouts); matcher_free(matcher); return ret; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/rules.h000066400000000000000000000020741510033435100224230ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include "xkbcomp-priv.h" #include "rmlvo.h" XKB_EXPORT_PRIVATE bool xkb_components_from_rmlvo_builder(const struct xkb_rmlvo_builder *rmlvo, struct xkb_component_names *out, xkb_layout_index_t *explicit_layouts); XKB_EXPORT_PRIVATE bool xkb_components_from_rules_names(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo, struct xkb_component_names *out, xkb_layout_index_t *explicit_layouts); /* Maximum length of a layout index string: * * length = ceiling (bitsize(xkb_layout_index_t) * logBase 10 2) * < ceiling (bitsize(xkb_layout_index_t) * 5 / 16) * < 1 + floor (bitsize(xkb_layout_index_t) * 5 / 16) */ #define MAX_LAYOUT_INDEX_STR_LENGTH \ (1 + ((sizeof(xkb_layout_index_t) * CHAR_BIT * 5) >> 4)) #define OPTIONS_GROUP_SPECIFIER_PREFIX '!' xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/scanner.c000066400000000000000000000234441510033435100227210ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "scanner-utils.h" #include "xkbcomp-priv.h" #include "parser-priv.h" const char DECIMAL_SEPARATOR = '.'; static bool number(struct scanner *s, int64_t *out, int *out_tok) { if (scanner_lit(s, "0x")) { switch (scanner_hex_int64(s, out)) { case -1: *out_tok = ERROR_TOK; return true; case 0: return false; default: *out_tok = INTEGER; return true; } } else { bool is_digit = false; switch (scanner_dec_int64(s, out)) { case -1: *out_tok = ERROR_TOK; return true; case 0: return false; case 1: is_digit = true; break; default: ; } if (scanner_chr(s, DECIMAL_SEPARATOR)) { /* * Since the parser does not use floats, we do not care of the * actual floating-point number value: we just need to ensure that * the syntax is correct. So just truncate it! * * Note that `strtold` would not work reliably in our context, * because it depends on the locale for e.g. the decimal separator * (e.g. a period or a comma) and requires a null-terminated string, * which we cannot guarantee. */ int64_t dec; if (scanner_dec_int64(s, &dec) < 0) { *out_tok = ERROR_TOK; return true; } *out_tok = FLOAT; } else if (is_digit) { *out_tok = DECIMAL_DIGIT; } else { *out_tok = INTEGER; } return true; } } int _xkbcommon_lex(YYSTYPE *yylval, struct scanner *s) { skip_more_whitespace_and_comments: /* Skip spaces. */ while (is_space(scanner_peek(s))) scanner_next(s); /* * Skip U+200E LEFT-TO-RIGHT MARK and U+200F RIGHT-TO-LEFT MARK, assuming * UTF-8 encoding. These Unicode code points are useful for forcing the text * directionality when displaying/editing an XKB file. */ if (scanner_lit(s, u8"\u200E") || scanner_lit(s, u8"\u200F")) goto skip_more_whitespace_and_comments; /* Skip comments. */ if (scanner_lit(s, "//") || scanner_chr(s, '#')) { scanner_skip_to_eol(s); goto skip_more_whitespace_and_comments; } /* See if we're done. */ if (scanner_eof(s)) return END_OF_FILE; /* New token. */ s->token_pos = s->pos; s->buf_pos = 0; /* String literal. */ if (scanner_chr(s, '\"')) { while (!scanner_eof(s) && !scanner_eol(s) && scanner_peek(s) != '\"') { if (scanner_chr(s, '\\')) { uint8_t o; const size_t start_pos = s->pos; if (scanner_chr(s, '\\')) scanner_buf_append(s, '\\'); else if (scanner_chr(s, '"')) scanner_buf_append(s, '"'); else if (scanner_chr(s, 'n')) scanner_buf_append(s, '\n'); else if (scanner_chr(s, 't')) scanner_buf_append(s, '\t'); else if (scanner_chr(s, 'r')) scanner_buf_append(s, '\r'); else if (scanner_chr(s, 'b')) scanner_buf_append(s, '\b'); else if (scanner_chr(s, 'f')) scanner_buf_append(s, '\f'); else if (scanner_chr(s, 'v')) scanner_buf_append(s, '\v'); else if (scanner_chr(s, 'e')) scanner_buf_append(s, '\x1b'); else if (scanner_chr(s, 'u')) { /* Unicode escape sequence */ uint32_t cp = 0; if (scanner_unicode_code_point(s, &cp) && is_valid_char(cp)) { /* Encode code point using UTF-8 */ scanner_buf_appends_code_point(s, cp); } else { scanner_warn( s, XKB_WARNING_INVALID_UNICODE_ESCAPE_SEQUENCE, "invalid Unicode escape sequence \"%.*s\" " "in string literal", (int) (s->pos - start_pos + 1), &s->s[start_pos - 1] ); /* Ignore. */ } } else if (scanner_oct(s, &o) && is_valid_char((uint32_t) o)) scanner_buf_append(s, (char) o); else if (s->pos > start_pos) { scanner_warn(s, XKB_WARNING_INVALID_ESCAPE_SEQUENCE, "invalid octal escape sequence \"%.*s\" " "in string literal", (int) (s->pos - start_pos + 1), &s->s[start_pos - 1]); /* Ignore. */ } else { scanner_warn(s, XKB_WARNING_UNKNOWN_CHAR_ESCAPE_SEQUENCE, "unknown escape sequence \"\\%c\" in string literal", scanner_peek(s)); /* Ignore. */ } } else { scanner_buf_append(s, scanner_next(s)); } } if (!scanner_buf_append(s, '\0') || !scanner_chr(s, '\"')) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "unterminated string literal"); return ERROR_TOK; } yylval->str = strdup(s->buf); if (!yylval->str) return ERROR_TOK; return STRING; } /* Key name literal. */ if (scanner_chr(s, '<')) { while (is_graph(scanner_peek(s)) && scanner_peek(s) != '>') scanner_next(s); if (!scanner_chr(s, '>')) { scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "unterminated key name literal"); return ERROR_TOK; } /* Empty key name literals are allowed. */ const char *start = s->s + s->token_pos + 1; const size_t len = s->pos - s->token_pos - 2; yylval->atom = xkb_atom_intern(s->ctx, start, len); return KEYNAME; } /* Operators and punctuation. */ if (scanner_chr(s, ';')) return SEMI; if (scanner_chr(s, '{')) return OBRACE; if (scanner_chr(s, '}')) return CBRACE; if (scanner_chr(s, '=')) return EQUALS; if (scanner_chr(s, '[')) return OBRACKET; if (scanner_chr(s, ']')) return CBRACKET; if (scanner_chr(s, '(')) return OPAREN; if (scanner_chr(s, ')')) return CPAREN; if (scanner_chr(s, '.')) return DOT; if (scanner_chr(s, ',')) return COMMA; if (scanner_chr(s, '+')) return PLUS; if (scanner_chr(s, '-')) return MINUS; if (scanner_chr(s, '*')) return TIMES; if (scanner_chr(s, '/')) return DIVIDE; if (scanner_chr(s, '!')) return EXCLAM; if (scanner_chr(s, '~')) return INVERT; int tok = ERROR_TOK; /* Identifier. */ if (is_alpha(scanner_peek(s)) || scanner_peek(s) == '_') { while (is_alnum(scanner_peek(s)) || scanner_peek(s) == '_') scanner_next(s); const char *start = s->s + s->token_pos; const size_t len = s->pos - s->token_pos; /* Keyword. */ tok = keyword_to_token(start, len); if (tok >= 0) return tok; yylval->sval = SVAL(start, len); return IDENT; } /* Number literal (hexadecimal / decimal / float). */ if (number(s, &yylval->num, &tok)) { if (tok == ERROR_TOK) { scanner_err(s, XKB_ERROR_MALFORMED_NUMBER_LITERAL, "malformed number literal"); return ERROR_TOK; } return tok; } scanner_err(s, XKB_LOG_MESSAGE_NO_ID, "unrecognized token"); return ERROR_TOK; } bool XkbParseStringInit(struct xkb_context *ctx, struct scanner *scanner, const char *string, size_t len, const char *file_name, const char *map) { scanner_init(scanner, ctx, string, len, file_name, NULL); /* Basic detection of wrong character encoding. The first character relevant to the grammar must be ASCII: whitespace, section, comment */ if (!scanner_check_supported_char_encoding(scanner)) { scanner_err(scanner, XKB_ERROR_INVALID_FILE_ENCODING, "This could be a file encoding issue. " "Supported encodings must be backward compatible with ASCII."); scanner_err(scanner, XKB_ERROR_INVALID_FILE_ENCODING, "E.g. ISO/CEI 8859 and UTF-8 are supported " "but UTF-16, UTF-32 and CP1026 are not."); return false; } return true; } XkbFile * XkbParseString(struct xkb_context *ctx, const char *string, size_t len, const char *file_name, const char *map) { struct scanner scanner; if (!XkbParseStringInit(ctx, &scanner, string, len, file_name, map)) return NULL; return parse(ctx, &scanner, map); } bool XkbParseStringNext(struct xkb_context *ctx, struct scanner *scanner, const char *map, XkbFile **out) { if (map) { *out = parse(ctx, scanner, map); return !!(*out); } else { return parse_next(ctx, scanner, out); } } XkbFile * XkbParseFile(struct xkb_context *ctx, FILE *file, const char *file_name, const char *map) { bool ok; XkbFile *xkb_file; char *string; size_t size; ok = map_file(file, &string, &size); if (!ok) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Couldn't read XKB file %s: %s\n", file_name, strerror(errno)); return NULL; } xkb_file = XkbParseString(ctx, string, size, file_name, map); unmap_file(string, size); return xkb_file; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/symbols.c000066400000000000000000002054351510033435100227620ustar00rootroot00000000000000/* * For HPND: * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * * For MIT: * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * * SPDX-License-Identifier: HPND AND MIT * * Author: Daniel Stone * Author: Ran Benita */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-keysyms.h" #include "action.h" #include "expr.h" #include "darray.h" #include "include.h" #include "keymap.h" #include "keysym.h" #include "messages-codes.h" #include "text.h" #include "util-mem.h" #include "vmod.h" #include "xkbcomp-priv.h" #include "xkbcomp/ast.h" enum key_repeat { KEY_REPEAT_UNDEFINED = 0, KEY_REPEAT_YES = 1, KEY_REPEAT_NO = 2, }; enum group_field { GROUP_FIELD_SYMS = (1 << 0), GROUP_FIELD_ACTS = (1 << 1), GROUP_FIELD_TYPE = (1 << 2), }; enum key_field { KEY_FIELD_REPEAT = (1 << 0), KEY_FIELD_DEFAULT_TYPE = (1 << 1), KEY_FIELD_GROUPINFO = (1 << 2), KEY_FIELD_VMODMAP = (1 << 3), }; typedef struct { enum group_field defined; darray(struct xkb_level) levels; xkb_atom_t type; } GroupInfo; typedef struct { enum key_field defined; enum merge_mode merge; xkb_atom_t name; darray(GroupInfo) groups; enum key_repeat repeat; xkb_mod_mask_t vmodmap; xkb_atom_t default_type; enum xkb_range_exceed_type out_of_range_group_action; xkb_layout_index_t out_of_range_group_number; } KeyInfo; static void StealLevelInfo(struct xkb_level *into, struct xkb_level *from) { clear_level(into); if (from->num_syms > 1) { /* Steal */ into->s.syms = steal(&from->s.syms); } else { into->s.sym = from->s.sym; } into->num_syms = from->num_syms; from->num_syms = 0; if (from->num_actions > 1) { into->a.actions = steal(&from->a.actions); } else { into->a.action = from->a.action; } into->num_actions = from->num_actions; from->num_actions = 0; } static void InitGroupInfo(GroupInfo *groupi) { memset(groupi, 0, sizeof(*groupi)); } static void ClearGroupInfo(GroupInfo *groupi) { struct xkb_level *leveli; darray_foreach(leveli, groupi->levels) clear_level(leveli); darray_free(groupi->levels); } static void CopyGroupInfo(GroupInfo *to, const GroupInfo *from) { to->defined = from->defined; to->type = from->type; darray_init(to->levels); darray_copy(to->levels, from->levels); for (xkb_level_index_t j = 0; j < darray_size(to->levels); j++) { if (darray_item(from->levels, j).num_syms > 1) { darray_item(to->levels, j).s.syms = memdup(darray_item(from->levels, j).s.syms, darray_item(from->levels, j).num_syms, sizeof(xkb_keysym_t)); } if (darray_item(from->levels, j).num_actions > 1) { darray_item(to->levels, j).a.actions = memdup(darray_item(from->levels, j).a.actions, darray_item(from->levels, j).num_actions, sizeof(union xkb_action)); } } } static void InitKeyInfo(struct xkb_context *ctx, KeyInfo *keyi) { memset(keyi, 0, sizeof(*keyi)); keyi->name = xkb_atom_intern_literal(ctx, "*"); keyi->out_of_range_group_action = RANGE_WRAP; } static void ClearKeyInfo(KeyInfo *keyi) { GroupInfo *groupi; darray_foreach(groupi, keyi->groups) ClearGroupInfo(groupi); darray_free(keyi->groups); } /***====================================================================***/ typedef struct { enum merge_mode merge; bool haveSymbol; /* NOTE: Can also be XKB_MOD_NONE, meaning * “don’t add a modifier to the modmap”. */ xkb_mod_index_t modifier; union { xkb_atom_t keyName; xkb_keysym_t keySym; } u; } ModMapEntry; typedef struct { char *name; /* e.g. pc+us+inet(evdev) */ int errorCount; unsigned int include_depth; xkb_layout_index_t explicit_group; darray(KeyInfo) keys; KeyInfo default_key; ActionsInfo default_actions; darray(xkb_atom_t) group_names; darray(ModMapEntry) modmaps; struct xkb_mod_set mods; xkb_layout_index_t max_groups; struct xkb_context *ctx; /* Needed for AddKeySymbols. */ const struct xkb_keymap *keymap; } SymbolsInfo; static void InitSymbolsInfo(SymbolsInfo *info, const struct xkb_keymap *keymap, unsigned int include_depth, const struct xkb_mod_set *mods) { memset(info, 0, sizeof(*info)); info->ctx = keymap->ctx; info->include_depth = include_depth; info->keymap = keymap; info->max_groups = format_max_groups(keymap->format); InitKeyInfo(keymap->ctx, &info->default_key); InitActionsInfo(&info->default_actions); InitVMods(&info->mods, mods, include_depth > 0); info->explicit_group = XKB_LAYOUT_INVALID; } static void ClearSymbolsInfo(SymbolsInfo *info) { KeyInfo *keyi; free(info->name); darray_foreach(keyi, info->keys) ClearKeyInfo(keyi); darray_free(info->keys); darray_free(info->group_names); darray_free(info->modmaps); ClearKeyInfo(&info->default_key); } static const char * KeyInfoText(SymbolsInfo *info, KeyInfo *keyi) { return KeyNameText(info->ctx, keyi->name); } static bool MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber, bool report, xkb_layout_index_t group, xkb_atom_t key_name) { /* First find the type of the merged group. */ if (into->type != from->type) { if (from->type == XKB_ATOM_NONE) { /* it's empty for consistency with other comparisons */ } else if (into->type == XKB_ATOM_NONE) { into->type = from->type; } else { xkb_atom_t use = (clobber ? from->type : into->type); xkb_atom_t ignore = (clobber ? into->type : from->type); if (report) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_TYPE_MERGING_GROUPS, "Multiple definitions for group %"PRIu32" type of key %s; " "Using %s, ignoring %s\n", group + 1, KeyNameText(info->ctx, key_name), xkb_atom_text(info->ctx, use), xkb_atom_text(info->ctx, ignore)); } into->type = use; } } into->defined |= (from->defined & GROUP_FIELD_TYPE); /* Now look at the levels. */ if (darray_empty(from->levels)) { InitGroupInfo(from); return true; } if (darray_empty(into->levels)) { from->type = into->type; *into = *from; InitGroupInfo(from); return true; } /* Merge the actions and syms. */ const darray_size_t levels_in_both = MIN(darray_size(into->levels), darray_size(from->levels)); darray_size_t fromKeysymsCount = 0; darray_size_t fromActionsCount = 0; for (darray_size_t i = 0; i < levels_in_both; i++) { struct xkb_level* const intoLevel = &darray_item(into->levels, i); struct xkb_level* const fromLevel = &darray_item(from->levels, i); const bool fromHasNoKeysym = fromLevel->num_syms == 0; const bool fromHasNoAction = fromLevel->num_actions == 0; if (fromHasNoKeysym && fromHasNoAction) { /* Empty `from`: do nothing */ continue; } const bool intoHasNoKeysym = intoLevel->num_syms == 0; const bool intoHasNoAction = intoLevel->num_actions == 0; if (intoHasNoKeysym && intoHasNoAction) { /* Empty `into`: use `from` keysyms and actions */ StealLevelInfo(intoLevel, fromLevel); fromKeysymsCount++; fromActionsCount++; continue; } /* Possible level conflict */ assert(intoLevel->num_syms > 0 || intoLevel->num_actions > 0); assert(fromLevel->num_syms > 0 || fromLevel->num_actions > 0); /* Handle keysyms */ if (!XkbLevelsSameSyms(fromLevel, intoLevel)) { /* Incompatible keysyms */ if (report && !(intoHasNoKeysym || fromHasNoKeysym)) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_SYMBOL, "Multiple symbols for level %u/group " "%"PRIu32" on key %s; Using %s, ignoring %s\n", i + 1, group + 1, KeyNameText(info->ctx, key_name), (clobber ? "from" : "to"), (clobber ? "to" : "from")); } if (fromHasNoKeysym) { /* No keysym to copy */ } else if (clobber) { /* Override: copy any defined keysym from `from` */ if (unlikely(fromLevel->num_syms > 1)) { /* Multiple keysyms: always replace, all syms are defined */ if (unlikely(intoLevel->num_syms > 1)) free(intoLevel->s.syms); /* Steal */ intoLevel->s.syms = fromLevel->s.syms; intoLevel->num_syms = fromLevel->num_syms; fromLevel->num_syms = 0; fromKeysymsCount++; } else if (fromLevel->s.sym != XKB_KEY_NoSymbol) { /* Single defined keysym */ if (unlikely(intoLevel->num_syms > 1)) free(intoLevel->s.syms); intoLevel->s.sym = fromLevel->s.sym; intoLevel->num_syms = 1; fromKeysymsCount++; } } else { /* Augment: copy only the keysyms from `from` that are * undefined in `into` */ if (unlikely(intoLevel->num_syms > 1)) { /* Multiple keysyms: always ignore, all syms are defined */ } else if (intoLevel->s.sym == XKB_KEY_NoSymbol) { /* Single undefined keysym */ if (unlikely(fromLevel->num_syms > 1)) { /* Steal */ intoLevel->s.syms = fromLevel->s.syms; intoLevel->num_syms = fromLevel->num_syms; fromLevel->num_syms = 0; } else { intoLevel->s.sym = fromLevel->s.sym; intoLevel->num_syms = 1; } fromKeysymsCount++; } } } /* Handle actions */ if (!XkbLevelsSameActions(intoLevel, fromLevel)) { /* Incompatible actions */ if (report && !(intoHasNoAction || fromHasNoAction)) { if (unlikely(intoLevel->num_actions > 1)) { log_warn( info->ctx, XKB_WARNING_CONFLICTING_KEY_ACTION, "Multiple actions for level %u/group %"PRIu32" " "on key %s; %s\n", i + 1, group + 1, KeyNameText(info->ctx, key_name), clobber ? "Using from, ignoring to" : "Using to, ignoring from"); } else { union xkb_action *use, *ignore; use = clobber ? &fromLevel->a.action : &intoLevel->a.action; ignore = clobber ? &intoLevel->a.action : &fromLevel->a.action; log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_ACTION, "Multiple actions for level %u/group " "%"PRIu32" on key %s; Using %s, ignoring %s\n", i + 1, group + 1, KeyNameText(info->ctx, key_name), ActionTypeText(use->type), ActionTypeText(ignore->type)); } } if (fromHasNoAction) { /* No action to copy */ } else if (clobber) { /* Override: copy any defined action from `from` */ if (unlikely(fromLevel->num_actions > 1)) { /* Multiple actions: always replace, all syms are defined */ if (unlikely(intoLevel->num_actions > 1)) free(intoLevel->a.actions); /* Steal */ intoLevel->a.actions = fromLevel->a.actions; intoLevel->num_actions = fromLevel->num_actions; fromLevel->num_actions = 0; fromActionsCount++; } else if (fromLevel->a.action.type != ACTION_TYPE_NONE) { /* Single defined action */ if (unlikely(intoLevel->num_actions > 1)) free(intoLevel->a.actions); intoLevel->a.action = fromLevel->a.action; intoLevel->num_actions = 1; fromActionsCount++; } } else { /* Augment: copy only the actions from `from` that are * undefined in `into` */ if (unlikely(intoLevel->num_actions > 1)) { /* Multiple keysyms: always ignore, all syms are defined */ } else if (intoLevel->a.action.type == ACTION_TYPE_NONE) { /* Single undefined keysym */ if (unlikely(fromLevel->num_actions > 1)) { /* Steal */ intoLevel->a.actions = fromLevel->a.actions; intoLevel->num_actions = fromLevel->num_actions; fromLevel->num_actions = 0; } else { intoLevel->a.action = fromLevel->a.action; intoLevel->num_actions = 1; } fromActionsCount++; } } } } /* If @from has extra levels, get them as well. */ struct xkb_level *level; darray_foreach_from(level, from->levels, levels_in_both) { darray_append(into->levels, *level); /* We may have stolen keysyms or actions arrays: * do not free them when clearing `from` */ level->num_syms = 0; level->num_actions = 0; fromKeysymsCount++; fromActionsCount++; } if (fromKeysymsCount) { /* Reset defined keysyms field if we used no keysym from `into` */ if (fromKeysymsCount == darray_size(into->levels)) into->defined &= ~GROUP_FIELD_SYMS; into->defined |= (from->defined & GROUP_FIELD_SYMS); } if (fromActionsCount) { /* Reset defined actions field if we used no action from `into` */ if (fromActionsCount == darray_size(into->levels)) into->defined &= ~GROUP_FIELD_ACTS; into->defined |= (from->defined & GROUP_FIELD_ACTS); } return true; } static bool UseNewKeyField(enum key_field field, enum key_field old, enum key_field new, bool clobber, bool report, enum key_field *collide) { if (!(old & field)) return (new & field); if (new & field) { if (report) *collide |= field; return clobber; } return false; } static bool MergeKeys(SymbolsInfo *info, KeyInfo *into, KeyInfo *from, bool same_file) { xkb_layout_index_t i; xkb_layout_index_t groups_in_both; enum key_field collide = 0; const int verbosity = xkb_context_get_log_verbosity(info->ctx); const bool clobber = (from->merge != MERGE_AUGMENT); const bool report = (same_file && verbosity > 0) || verbosity > 9; if (from->merge == MERGE_REPLACE) { ClearKeyInfo(into); *into = *from; InitKeyInfo(info->ctx, from); return true; } groups_in_both = MIN(darray_size(into->groups), darray_size(from->groups)); for (i = 0; i < groups_in_both; i++) MergeGroups(info, &darray_item(into->groups, i), &darray_item(from->groups, i), clobber, report, i, into->name); /* If @from has extra groups, just move them to @into. */ for (i = groups_in_both; i < darray_size(from->groups); i++) { darray_append(into->groups, darray_item(from->groups, i)); InitGroupInfo(&darray_item(from->groups, i)); } if (UseNewKeyField(KEY_FIELD_VMODMAP, into->defined, from->defined, clobber, report, &collide)) { into->vmodmap = from->vmodmap; into->defined |= KEY_FIELD_VMODMAP; } if (UseNewKeyField(KEY_FIELD_REPEAT, into->defined, from->defined, clobber, report, &collide)) { into->repeat = from->repeat; into->defined |= KEY_FIELD_REPEAT; } if (UseNewKeyField(KEY_FIELD_DEFAULT_TYPE, into->defined, from->defined, clobber, report, &collide)) { into->default_type = from->default_type; into->defined |= KEY_FIELD_DEFAULT_TYPE; } if (UseNewKeyField(KEY_FIELD_GROUPINFO, into->defined, from->defined, clobber, report, &collide)) { into->out_of_range_group_action = from->out_of_range_group_action; into->out_of_range_group_number = from->out_of_range_group_number; into->defined |= KEY_FIELD_GROUPINFO; } if (collide) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_FIELDS, "Symbol map for key %s redefined; " "Using %s definition for conflicting fields\n", KeyNameText(info->ctx, into->name), (clobber ? "first" : "last")); } ClearKeyInfo(from); InitKeyInfo(info->ctx, from); return true; } static struct xkb_key * XkbKeyByName(struct xkb_keymap *keymap, xkb_atom_t name, bool use_aliases) { if (name < keymap->num_key_names) { const KeycodeMatch match = keymap->key_names[name]; if (match.found) { if (!match.is_alias) { assert(name == keymap->keys[match.key.index].name); return &keymap->keys[match.key.index]; } else if (use_aliases) { assert(match.alias.real == keymap->keys[keymap->key_names[match.alias.real].key.index].name); return &keymap->keys[keymap->key_names[match.alias.real].key.index]; } } } return NULL; } static xkb_atom_t XkbResolveKeyAlias(const struct xkb_keymap *keymap, xkb_atom_t name) { if (name < keymap->num_key_names) { const KeycodeMatch match = keymap->key_names[name]; if (match.found && match.is_alias) { return match.alias.real; } } return name; } /* TODO: Make it so this function doesn't need the entire keymap. */ static bool AddKeySymbols(SymbolsInfo *info, KeyInfo *keyi, bool same_file) { /* * Don't keep aliases in the keys array; this guarantees that * searching for keys to merge with by straight comparison (see the * following loop) is enough, and we won't get multiple KeyInfo's * for the same key because of aliases. */ keyi->name = XkbResolveKeyAlias(info->keymap, keyi->name); KeyInfo *iter; darray_foreach(iter, info->keys) if (iter->name == keyi->name) return MergeKeys(info, iter, keyi, same_file); darray_append(info->keys, *keyi); InitKeyInfo(info->ctx, keyi); return true; } static bool AddModMapEntry(SymbolsInfo *info, ModMapEntry *new) { ModMapEntry *old; bool clobber = (new->merge != MERGE_AUGMENT); darray_foreach(old, info->modmaps) { xkb_mod_index_t use, ignore; if ((new->haveSymbol != old->haveSymbol) || (new->haveSymbol && new->u.keySym != old->u.keySym) || (!new->haveSymbol && new->u.keyName != old->u.keyName)) continue; if (new->modifier == old->modifier) return true; use = (clobber ? new->modifier : old->modifier); ignore = (clobber ? old->modifier : new->modifier); if (new->haveSymbol) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_MODMAP, "Symbol \"%s\" added to modifier map for multiple modifiers; " "Using %s, ignoring %s\n", KeysymText(info->ctx, new->u.keySym), ModIndexText(info->ctx, &info->mods, use), ModIndexText(info->ctx, &info->mods, ignore)); } else { log_warn(info->ctx, XKB_WARNING_CONFLICTING_MODMAP, "Key \"%s\" added to modifier map for multiple modifiers; " "Using %s, ignoring %s\n", KeyNameText(info->ctx, new->u.keyName), ModIndexText(info->ctx, &info->mods, use), ModIndexText(info->ctx, &info->mods, ignore)); } old->modifier = use; return true; } darray_append(info->modmaps, *new); return true; } /***====================================================================***/ static void MergeIncludedSymbols(SymbolsInfo *into, SymbolsInfo *from, enum merge_mode merge) { xkb_atom_t *group_name; xkb_layout_index_t group_names_in_both; if (from->errorCount > 0) { into->errorCount += from->errorCount; return; } MergeModSets(into->ctx, &into->mods, &from->mods, merge); if (into->name == NULL) { into->name = steal(&from->name); } group_names_in_both = MIN(darray_size(into->group_names), darray_size(from->group_names)); for (xkb_layout_index_t i = 0; i < group_names_in_both; i++) { if (!darray_item(from->group_names, i)) continue; if (merge == MERGE_AUGMENT && darray_item(into->group_names, i)) continue; darray_item(into->group_names, i) = darray_item(from->group_names, i); } /* If @from has more, get them as well. */ darray_foreach_from(group_name, from->group_names, group_names_in_both) darray_append(into->group_names, *group_name); if (darray_empty(into->keys)) { into->keys = from->keys; darray_init(from->keys); } else { KeyInfo *keyi; darray_foreach(keyi, from->keys) { keyi->merge = merge; if (!AddKeySymbols(into, keyi, false)) into->errorCount++; } } if (darray_empty(into->modmaps)) { into->modmaps = from->modmaps; darray_init(from->modmaps); } else { ModMapEntry *mm; darray_foreach(mm, from->modmaps) { mm->merge = merge; if (!AddModMapEntry(into, mm)) into->errorCount++; } } } static void HandleSymbolsFile(SymbolsInfo *info, XkbFile *file); static bool HandleIncludeSymbols(SymbolsInfo *info, IncludeStmt *include) { SymbolsInfo included; if (ExceedsIncludeMaxDepth(info->ctx, info->include_depth)) { info->errorCount += 10; return false; } InitSymbolsInfo(&included, info->keymap, info->include_depth + 1, &info->mods); included.name = steal(&include->stmt); for (IncludeStmt *stmt = include; stmt; stmt = stmt->next_incl) { SymbolsInfo next_incl; XkbFile *file; char path[PATH_MAX]; file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_SYMBOLS, path, sizeof(path)); if (!file) { info->errorCount += 10; ClearSymbolsInfo(&included); return false; } InitSymbolsInfo(&next_incl, info->keymap, info->include_depth + 1, &included.mods); if (stmt->modifier) { next_incl.explicit_group = atoi(stmt->modifier) - 1; if (next_incl.explicit_group >= info->max_groups) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Cannot set explicit group to %"PRIu32" - " "must be between 1..%u; Ignoring group number\n", next_incl.explicit_group + 1, info->max_groups); next_incl.explicit_group = info->explicit_group; } } else if (info->keymap->num_groups != 0 && next_incl.include_depth == 1) { /* If keymap is the result of RMLVO resolution and we are at the * first include depth, transform e.g. `pc` into `pc:1` in order to * force only one group per key using the explicit group. * * NOTE: X11’s xkbcomp does not apply this rule. */ next_incl.explicit_group = 0; } else { /* The keymap was not generated from rules or this is not the first * level of include: take the parent’s explicit group. */ next_incl.explicit_group = info->explicit_group; } HandleSymbolsFile(&next_incl, file); MergeIncludedSymbols(&included, &next_incl, stmt->merge); ClearSymbolsInfo(&next_incl); FreeXkbFile(file); } MergeIncludedSymbols(info, &included, include->merge); ClearSymbolsInfo(&included); return (info->errorCount == 0); } static bool GetGroupIndex(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, enum group_field field, xkb_layout_index_t *ndx_rtrn) { assert (field == GROUP_FIELD_SYMS || field == GROUP_FIELD_ACTS); const char *name = (field == GROUP_FIELD_SYMS ? "symbols" : "actions"); if (arrayNdx == NULL) { xkb_layout_index_t i = 0; GroupInfo *groupi; darray_enumerate(i, groupi, keyi->groups) { if (!(groupi->defined & field)) { *ndx_rtrn = i; return true; } } if (i >= info->max_groups) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Too many groups of %s for key %s (max %u); " "Ignoring %s defined for extra groups\n", name, KeyInfoText(info, keyi), info->max_groups, name); return false; } darray_resize0(keyi->groups, darray_size(keyi->groups) + 1); *ndx_rtrn = darray_size(keyi->groups) - 1; return true; } if (!ExprResolveGroup(info->ctx, info->max_groups, arrayNdx, ndx_rtrn)) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Illegal group index for %s of key %s\n" "Definition with non-integer array index ignored\n", name, KeyInfoText(info, keyi)); return false; } (*ndx_rtrn)--; if (*ndx_rtrn >= darray_size(keyi->groups)) darray_resize0(keyi->groups, *ndx_rtrn + 1); return true; } static bool AddSymbolsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, ExprDef *value) { xkb_layout_index_t ndx = 0; if (!GetGroupIndex(info, keyi, arrayNdx, GROUP_FIELD_SYMS, &ndx)) return false; GroupInfo *groupi = &darray_item(keyi->groups, ndx); if (value->common.type == STMT_EXPR_EMPTY_LIST) { groupi->defined |= GROUP_FIELD_SYMS; return true; } if (value->common.type != STMT_EXPR_KEYSYM_LIST) { log_err(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Expected a list of symbols, found %s; " "Ignoring symbols for group %"PRIu32" of %s\n", stmt_type_to_string(value->common.type), ndx + 1, KeyInfoText(info, keyi)); return false; } if (groupi->defined & GROUP_FIELD_SYMS) { log_err(info->ctx, XKB_ERROR_CONFLICTING_KEY_SYMBOLS_ENTRY, "Symbols for key %s, group %"PRIu32" already defined; " "Ignoring duplicate definition\n", KeyInfoText(info, keyi), ndx + 1); return false; } xkb_level_index_t nLevels = 0; xkb_level_index_t nonEmptyLevels = 0; /* Contrary to actions, keysyms are already parsed at this point so we drop * trailing symbols by not adding them in the first place. */ for (ExprKeysymList *keysymList = (ExprKeysymList *) value; keysymList; keysymList = (ExprKeysymList *) keysymList->common.next) { nLevels++; /* Drop trailing NoSymbol */ if (darray_size(keysymList->syms) > 0) nonEmptyLevels = nLevels; } if (nonEmptyLevels < nLevels) nLevels = nonEmptyLevels; if (darray_size(groupi->levels) < nLevels) darray_resize0(groupi->levels, nLevels); groupi->defined |= GROUP_FIELD_SYMS; xkb_level_index_t level = 0; for (ExprKeysymList *keysymList = (ExprKeysymList *) value; keysymList && level < nLevels; keysymList = (ExprKeysymList *) keysymList->common.next, level++) { struct xkb_level *leveli = &darray_item(groupi->levels, level); assert(leveli->num_syms == 0); if (unlikely(darray_size(keysymList->syms) > MAX_KEYSYMS_PER_LEVEL)) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Key %s has too many keysyms for group %"PRIu32", " "level %"PRIu32"; expected max %u, got: %u\n", KeyInfoText(info, keyi), ndx + 1, level + 1, MAX_KEYSYMS_PER_LEVEL, darray_size(keysymList->syms)); return false; } leveli->num_syms = (xkb_keysym_count_t) darray_size(keysymList->syms); switch (leveli->num_syms) { case 0: leveli->s.sym = XKB_KEY_NoSymbol; break; case 1: leveli->s.sym = darray_item(keysymList->syms, 0); assert(leveli->s.sym != XKB_KEY_NoSymbol); break; default: darray_shrink(keysymList->syms); darray_steal(keysymList->syms, &leveli->s.syms, NULL); #ifndef NDEBUG /* Canonical list: all NoSymbol were dropped */ for (xkb_keysym_count_t k = 0; k < leveli->num_syms; k++) assert(leveli->s.syms[k] != XKB_KEY_NoSymbol); #endif } } return true; } static bool AddActionsToKey(SymbolsInfo *info, KeyInfo *keyi, ExprDef *arrayNdx, ExprDef *value) { xkb_layout_index_t ndx = 0; if (!GetGroupIndex(info, keyi, arrayNdx, GROUP_FIELD_ACTS, &ndx)) return false; GroupInfo *groupi = &darray_item(keyi->groups, ndx); if (value->common.type == STMT_EXPR_EMPTY_LIST) { groupi->defined |= GROUP_FIELD_ACTS; return true; } if (value->common.type != STMT_EXPR_ACTION_LIST) { log_wsgo(info->ctx, XKB_ERROR_INVALID_EXPRESSION_TYPE, "Bad expression type (%d) for action list value; " "Ignoring actions for group %"PRIu32" of %s\n", value->common.type, ndx, KeyInfoText(info, keyi)); return false; } if (groupi->defined & GROUP_FIELD_ACTS) { log_wsgo(info->ctx, XKB_WARNING_CONFLICTING_KEY_ACTION, "Actions for key %s, group %"PRIu32" already defined\n", KeyInfoText(info, keyi), ndx); return false; } xkb_level_index_t nLevels = 0; /* Contrary to keysyms with trailing `NoSymbol`, we cannot detect trailing * `NoAction()` now, because we need to parse the actions first. Jusr count * explicit actions for now. */ for (ParseCommon *p = &value->common; p; p = p->next) nLevels++; if (darray_size(groupi->levels) < nLevels) darray_resize0(groupi->levels, nLevels); groupi->defined |= GROUP_FIELD_ACTS; xkb_level_index_t level = 0; xkb_level_index_t nonEmptyLevels = 0; for (ExprActionList *actionList = (ExprActionList *) value; actionList; actionList = (ExprActionList *) actionList->common.next, level++) { struct xkb_level *leveli = &darray_item(groupi->levels, level); assert(leveli->num_actions == 0); unsigned int num_actions = 0; for (ExprDef *act = actionList->actions; act; act = (ExprDef *) act->common.next) num_actions++; if (unlikely(num_actions > MAX_ACTIONS_PER_LEVEL)) { log_err(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Key %s has too many actions for group %"PRIu32", " "level %"PRIu32"; expected max %u, got: %u\n", KeyInfoText(info, keyi), ndx + 1, level + 1, MAX_ACTIONS_PER_LEVEL, num_actions); return false; } /* Parse actions and add only defined actions */ darray(union xkb_action) actions = darray_new(); for (ExprDef *act = actionList->actions; act; act = (ExprDef *) act->common.next) { union xkb_action toAct = { 0 }; if (!HandleActionDef(info->ctx, info->keymap->format, &info->default_actions, &info->mods, act, &toAct)) { log_err(info->ctx, XKB_ERROR_INVALID_VALUE, "Illegal action definition for %s; " "Action for group %"PRIu32"/level %"PRIu32" ignored\n", KeyInfoText(info, keyi), ndx + 1, level + 1); /* Ensure action type is reset */ toAct.type = ACTION_TYPE_NONE; } if (toAct.type == ACTION_TYPE_NONE) { /* Drop action */ } else if (likely(num_actions == 1)) { /* Only one action: do not allocate */ leveli->num_actions = 1; leveli->a.action = toAct; goto next_level; } else { darray_append(actions, toAct); } } if (darray_empty(actions)) { leveli->num_actions = 0; } else if (likely(darray_size(actions) > 1)) { leveli->num_actions = (xkb_action_count_t) darray_size(actions); darray_shrink(actions); darray_steal(actions, &leveli->a.actions, NULL); #ifndef NDEBUG /* Canonical list: all NoAction() were dropped */ for (xkb_action_count_t k = 0; k < leveli->num_actions; k++) assert(leveli->a.actions[k].type != ACTION_TYPE_NONE); #endif } else { /* Unlikely: some actions were dropped and only one remains */ assert(num_actions > darray_size(actions)); leveli->num_actions = 1; leveli->a.action = darray_item(actions, 0); assert(leveli->a.action.type != ACTION_TYPE_NONE); darray_free(actions); } next_level: /* * Check trailing `NoAction()`, but count as empty level only if there * is no corresponding keysym. */ if (leveli->num_actions > 0 || leveli->num_syms > 0) nonEmptyLevels = level + 1; } if (nonEmptyLevels < nLevels) { /* Drop trailing `NoAction()`. * No need to clear dropped levels: there are no keysyms nor actions */ darray_size(groupi->levels) = nonEmptyLevels; if (nonEmptyLevels > 0) darray_shrink(groupi->levels); else darray_free(groupi->levels); } return true; } static const LookupEntry repeatEntries[] = { { "true", KEY_REPEAT_YES }, { "yes", KEY_REPEAT_YES }, { "on", KEY_REPEAT_YES }, { "false", KEY_REPEAT_NO }, { "no", KEY_REPEAT_NO }, { "off", KEY_REPEAT_NO }, { "default", KEY_REPEAT_UNDEFINED }, { NULL, 0 } }; static bool SetSymbolsField(SymbolsInfo *info, KeyInfo *keyi, const char *field, ExprDef *arrayNdx, ExprDef *value) { if (istreq(field, "type")) { xkb_layout_index_t ndx = 0; xkb_atom_t val = XKB_ATOM_NONE; if (!ExprResolveString(info->ctx, value, &val)) { log_err(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE, "The type field of a key symbol map must be a string; " "Ignoring illegal type definition\n"); return false; } if (!arrayNdx) { keyi->default_type = val; keyi->defined |= KEY_FIELD_DEFAULT_TYPE; } else if (!ExprResolveGroup(info->ctx, info->max_groups, arrayNdx, &ndx)) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Illegal group index for type of key %s; " "Definition with non-integer array index ignored\n", KeyInfoText(info, keyi)); return false; } else { ndx--; if (ndx >= darray_size(keyi->groups)) { /* Avoid clang-tidy false positive */ assert(darray_size(keyi->groups) < ndx + 1); darray_resize0(keyi->groups, ndx + 1); } darray_item(keyi->groups, ndx).type = val; darray_item(keyi->groups, ndx).defined |= GROUP_FIELD_TYPE; } } else if (istreq(field, "symbols")) { return AddSymbolsToKey(info, keyi, arrayNdx, value); } else if (istreq(field, "actions")) { return AddActionsToKey(info, keyi, arrayNdx, value); } else if (istreq(field, "vmods") || istreq(field, "virtualmods") || istreq(field, "virtualmodifiers")) { xkb_mod_mask_t mask = 0; if (!ExprResolveModMask(info->ctx, value, MOD_VIRT, &info->mods, &mask)) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, "Expected a virtual modifier mask, found %s; " "Ignoring virtual modifiers definition for key %s\n", stmt_type_to_string(value->common.type), KeyInfoText(info, keyi)); return false; } keyi->vmodmap = mask; keyi->defined |= KEY_FIELD_VMODMAP; } else if (istreq(field, "locking") || istreq(field, "lock") || istreq(field, "locks")) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Key behaviors not supported; " "Ignoring locking specification for key %s\n", KeyInfoText(info, keyi)); } else if (istreq(field, "radiogroup") || istreq(field, "permanentradiogroup") || istreq(field, "allownone")) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Radio groups not supported; " "Ignoring radio group specification for key %s\n", KeyInfoText(info, keyi)); } else if (istreq_prefix("overlay", field) || istreq_prefix("permanentoverlay", field)) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Overlays not supported; " "Ignoring overlay specification for key %s\n", KeyInfoText(info, keyi)); } else if (istreq(field, "repeating") || istreq(field, "repeats") || istreq(field, "repeat")) { uint32_t val = 0; if (!ExprResolveEnum(info->ctx, value, &val, repeatEntries)) { log_err(info->ctx, XKB_ERROR_INVALID_VALUE, "Illegal repeat setting for %s; " "Non-boolean repeat setting ignored\n", KeyInfoText(info, keyi)); return false; } keyi->repeat = (enum key_repeat) val; keyi->defined |= KEY_FIELD_REPEAT; } else if (istreq(field, "groupswrap") || istreq(field, "wrapgroups")) { bool set = false; if (!ExprResolveBoolean(info->ctx, value, &set)) { log_err(info->ctx, XKB_ERROR_INVALID_VALUE, "Illegal groupsWrap setting for %s; " "Non-boolean value ignored\n", KeyInfoText(info, keyi)); return false; } keyi->out_of_range_group_action = (set ? RANGE_WRAP : RANGE_SATURATE); keyi->defined |= KEY_FIELD_GROUPINFO; } else if (istreq(field, "groupsclamp") || istreq(field, "clampgroups")) { bool set = false; if (!ExprResolveBoolean(info->ctx, value, &set)) { log_err(info->ctx, XKB_ERROR_INVALID_VALUE, "Illegal groupsClamp setting for %s; " "Non-boolean value ignored\n", KeyInfoText(info, keyi)); return false; } keyi->out_of_range_group_action = (set ? RANGE_SATURATE : RANGE_WRAP); keyi->defined |= KEY_FIELD_GROUPINFO; } else if (istreq(field, "groupsredirect") || istreq(field, "redirectgroups")) { xkb_layout_index_t grp = 0; if (!ExprResolveGroup(info->ctx, info->max_groups, value, &grp)) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Illegal group index for redirect of key %s; " "Definition with non-integer group ignored\n", KeyInfoText(info, keyi)); return false; } keyi->out_of_range_group_action = RANGE_REDIRECT; keyi->out_of_range_group_number = grp - 1; keyi->defined |= KEY_FIELD_GROUPINFO; } else { log_err(info->ctx, XKB_ERROR_UNKNOWN_FIELD, "Unknown field \"%s\" in a symbol interpretation; " "Definition ignored\n", field); return false; } return true; } static bool SetGroupName(SymbolsInfo *info, ExprDef *arrayNdx, ExprDef *value, enum merge_mode merge) { if (!arrayNdx) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_MISSING_SYMBOLS_GROUP_NAME_INDEX, "You must specify an index when specifying a group name; " "Group name definition without array subscript ignored\n"); return false; } xkb_layout_index_t group = 0; if (!ExprResolveGroup(info->ctx, info->max_groups, arrayNdx, &group)) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Illegal index in group name definition; " "Definition with non-integer array index ignored\n"); return false; } xkb_atom_t name = XKB_ATOM_NONE; if (!ExprResolveString(info->ctx, value, &name)) { log_err(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Group name must be a string; " "Illegal name for group %"PRIu32" ignored\n", group); return false; } xkb_layout_index_t group_to_use; if (info->explicit_group == XKB_LAYOUT_INVALID) { group_to_use = group - 1; } else if (group - 1 == 0) { group_to_use = info->explicit_group; } else { log_warn(info->ctx, XKB_WARNING_NON_BASE_GROUP_NAME, "An explicit group was specified for the '%s' map, " "but it provides a name for a group other than Group1 " "(%"PRIu32"); Ignoring group name '%s'\n", info->name, group, xkb_atom_text(info->ctx, name)); return false; } if (group_to_use >= darray_size(info->group_names)) { /* Avoid clang-tidy false positive */ assert(darray_size(info->group_names) < group_to_use + 1); darray_resize0(info->group_names, group_to_use + 1); } else { const xkb_atom_t old_name = darray_item(info->group_names, group_to_use); if (old_name != XKB_ATOM_NONE && old_name != name) { const bool replace = (merge != MERGE_AUGMENT); const xkb_atom_t use = (replace ? name : old_name); const xkb_atom_t ignore = (replace ? old_name : name); log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple definitions of group %"PRIu32" name " "in map '%s'; Using '%s', ignoring '%s'\n", group_to_use, info->name, xkb_atom_text(info->ctx, use), xkb_atom_text(info->ctx, ignore)); name = use; } } darray_item(info->group_names, group_to_use) = name; return true; } static bool HandleGlobalVar(SymbolsInfo *info, VarDef *stmt) { const char *elem, *field; ExprDef *arrayNdx; bool ret; if (!ExprResolveLhs(info->ctx, stmt->name, &elem, &field, &arrayNdx)) return false; if (elem && istreq(elem, "key")) { KeyInfo temp = {0}; InitKeyInfo(info->ctx, &temp); /* Do not replace the whole key, only the current field */ temp.merge = (temp.merge == MERGE_REPLACE) ? MERGE_OVERRIDE : stmt->merge; ret = SetSymbolsField(info, &temp, field, arrayNdx, stmt->value); MergeKeys(info, &info->default_key, &temp, true); } else if (!elem && (istreq(field, "name") || istreq(field, "groupname"))) { ret = SetGroupName(info, arrayNdx, stmt->value, stmt->merge); } else if (!elem && (istreq(field, "groupswrap") || istreq(field, "wrapgroups"))) { log_err(info->ctx, XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Global \"groupswrap\" not supported; Ignored\n"); ret = true; } else if (!elem && (istreq(field, "groupsclamp") || istreq(field, "clampgroups"))) { log_err(info->ctx, XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Global \"groupsclamp\" not supported; Ignored\n"); ret = true; } else if (!elem && (istreq(field, "groupsredirect") || istreq(field, "redirectgroups"))) { log_err(info->ctx, XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Global \"groupsredirect\" not supported; Ignored\n"); ret = true; } else if (!elem && istreq(field, "allownone")) { log_err(info->ctx, XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Radio groups not supported; " "Ignoring \"allownone\" specification\n"); ret = true; } else if (elem) { ret = SetDefaultActionField(info->ctx, info->keymap->format, &info->default_actions, &info->mods, elem, field, arrayNdx, stmt->value, stmt->merge); } else { log_err(info->ctx, XKB_ERROR_UNKNOWN_DEFAULT_FIELD, "Default defined for unknown field \"%s\"; Ignored\n", field); return false; } return ret; } static bool HandleSymbolsBody(SymbolsInfo *info, VarDef *def, KeyInfo *keyi) { if (!def) return true; /* Empty body */ bool all_valid_entries = true; for (; def; def = (VarDef *) def->common.next) { const char *field; ExprDef *arrayNdx; bool ok = true; if (!def->name) { if (unlikely(!def->value) || def->value->common.type != STMT_EXPR_ACTION_LIST) field = "symbols"; /* Default to symbols field */ else field = "actions"; arrayNdx = NULL; } else { const char *elem; ok = ExprResolveLhs(info->ctx, def->name, &elem, &field, &arrayNdx); if (ok && elem) { log_err(info->ctx, XKB_ERROR_GLOBAL_DEFAULTS_WRONG_SCOPE, "Cannot set global defaults for \"%s\" element within " "a key statement: move statements to the global file " "scope. Assignment to \"%s.%s\" ignored.\n", elem, elem, field); ok = false; } } if (unlikely(!def->value)) { log_err(info->ctx, XKB_ERROR_ALLOCATION_ERROR, "Could not allocate the value of field \"%s\". " "Statement ignored.\n", field); ok = false; } if (!ok || !SetSymbolsField(info, keyi, field, arrayNdx, def->value)) all_valid_entries = false; } return all_valid_entries; } static bool SetExplicitGroup(SymbolsInfo *info, KeyInfo *keyi) { xkb_layout_index_t i; GroupInfo *groupi; bool warn = false; if (info->explicit_group == XKB_LAYOUT_INVALID) return true; darray_enumerate_from(i, groupi, keyi->groups, 1) { if (groupi->defined) { warn = true; ClearGroupInfo(groupi); InitGroupInfo(groupi); } } if (warn) { log_warn(info->ctx, XKB_WARNING_MULTIPLE_GROUPS_AT_ONCE, "For the map %s the explicit group %"PRIu32" is specified, " "but key %s has more than one group defined; " "All groups except first one will be ignored\n", info->name, info->explicit_group + 1, KeyInfoText(info, keyi)); } darray_resize0(keyi->groups, info->explicit_group + 1); if (info->explicit_group > 0) { darray_item(keyi->groups, info->explicit_group) = darray_item(keyi->groups, 0); InitGroupInfo(&darray_item(keyi->groups, 0)); } return true; } static bool HandleSymbolsDef(SymbolsInfo *info, SymbolsDef *stmt) { KeyInfo keyi; keyi = info->default_key; darray_init(keyi.groups); darray_copy(keyi.groups, info->default_key.groups); for (xkb_layout_index_t i = 0; i < darray_size(keyi.groups); i++) CopyGroupInfo(&darray_item(keyi.groups, i), &darray_item(info->default_key.groups, i)); keyi.merge = stmt->merge; keyi.name = stmt->keyName; if (HandleSymbolsBody(info, stmt->symbols, &keyi) && SetExplicitGroup(info, &keyi) && AddKeySymbols(info, &keyi, true)) { return true; } ClearKeyInfo(&keyi); info->errorCount++; return false; } static bool HandleModMapDef(SymbolsInfo *info, ModMapDef *def) { ModMapEntry tmp; xkb_mod_index_t ndx; bool ok; struct xkb_context *ctx = info->ctx; const char *modifier_name = xkb_atom_text(ctx, def->modifier); if (istreq(modifier_name, "none")) { /* Handle special "None" entry */ ndx = XKB_MOD_NONE; } else { /* Handle normal entry */ ndx = XkbModNameToIndex(&info->mods, def->modifier, MOD_REAL); if (ndx == XKB_MOD_INVALID) { log_err(info->ctx, XKB_ERROR_INVALID_REAL_MODIFIER, "Illegal modifier map definition; " "Ignoring map for non-modifier \"%s\"\n", xkb_atom_text(ctx, def->modifier)); return false; } } ok = true; tmp.modifier = ndx; tmp.merge = def->merge; for (ExprDef *key = def->keys; key; key = (ExprDef *) key->common.next) { if (key->common.type == STMT_EXPR_KEYNAME_LITERAL) { tmp.haveSymbol = false; tmp.u.keyName = key->key_name.key_name; } else if (key->common.type == STMT_EXPR_KEYSYM_LITERAL) { if (key->keysym.keysym == XKB_KEY_NoSymbol) { /* Invalid keysym: ignore. Error message already printed */ continue; } else { tmp.haveSymbol = true; tmp.u.keySym = key->keysym.keysym; } } else { log_err(info->ctx, XKB_ERROR_INVALID_MODMAP_ENTRY, "Modmap entries may contain only key names or keysyms; " "Illegal definition for %s modifier ignored\n", ModIndexText(info->ctx, &info->mods, tmp.modifier)); continue; } ok = AddModMapEntry(info, &tmp) && ok; } return ok; } static void HandleSymbolsFile(SymbolsInfo *info, XkbFile *file) { bool ok; free(info->name); info->name = strdup_safe(file->name); for (ParseCommon *stmt = file->defs; stmt; stmt = stmt->next) { switch (stmt->type) { case STMT_INCLUDE: ok = HandleIncludeSymbols(info, (IncludeStmt *) stmt); break; case STMT_SYMBOLS: ok = HandleSymbolsDef(info, (SymbolsDef *) stmt); break; case STMT_VAR: ok = HandleGlobalVar(info, (VarDef *) stmt); break; case STMT_VMOD: ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt); break; case STMT_MODMAP: ok = HandleModMapDef(info, (ModMapDef *) stmt); break; default: log_err(info->ctx, XKB_ERROR_WRONG_STATEMENT_TYPE, "Symbols files may not include other types; " "Ignoring %s\n", stmt_type_to_string(stmt->type)); ok = false; break; } if (!ok) info->errorCount++; if (info->errorCount > 10) { log_err(info->ctx, XKB_ERROR_INVALID_XKB_SYNTAX, "Abandoning symbols file \"%s\"\n", safe_map_name(file)); break; } } } /** * Given a keysym @sym, return a key which generates it, or NULL. * This is used for example in a modifier map definition, such as: * modifier_map Lock { Caps_Lock }; * where we want to add the Lock modifier to the modmap of the key * which matches the keysym Caps_Lock. * Since there can be many keys which generates the keysym, the key * is chosen first by lowest group in which the keysym appears, than * by lowest level and than by lowest key code. */ static struct xkb_key * FindKeyForSymbol(struct xkb_keymap *keymap, xkb_keysym_t sym) { bool got_one_group; xkb_layout_index_t group = 0; do { xkb_level_index_t level = 0; got_one_group = false; bool got_one_level; do { got_one_level = false; struct xkb_key *key; xkb_keys_foreach(key, keymap) { if (group < key->num_groups && level < XkbKeyNumLevels(key, group)) { got_one_group = got_one_level = true; const xkb_keysym_count_t num_syms = key->groups[group].levels[level].num_syms; if (num_syms > 1) { for (xkb_keysym_count_t k = 0; k < num_syms; k++) { if (key->groups[group].levels[level].s.syms[k] == sym) return key; } } else if (num_syms && key->groups[group].levels[level].s.sym == sym) { return key; } } } level++; } while (got_one_level); group++; } while (got_one_group); return NULL; } /* * Find an appropriate type for a group and return its name. * * Simple recipe: * - ONE_LEVEL for width 0/1 * - ALPHABETIC for 2 shift levels, with lower/upercase keysyms * - KEYPAD for keypad keys. * - TWO_LEVEL for other 2 shift level keys. * and the same for four level keys. * * FIXME: Decide how to handle multiple-syms-per-level, and do it. */ static xkb_atom_t FindAutomaticType(struct xkb_context *ctx, GroupInfo *groupi) { xkb_keysym_t sym0, sym1; const xkb_level_index_t width = darray_size(groupi->levels); #define GET_SYM(level) \ (darray_item(groupi->levels, level).num_syms == 0 ? \ XKB_KEY_NoSymbol : \ darray_item(groupi->levels, level).num_syms == 1 ? \ darray_item(groupi->levels, level).s.sym : \ /* num_syms > 1 */ \ darray_item(groupi->levels, level).s.syms[0]) if (width == 1 || width <= 0) return xkb_atom_intern_literal(ctx, "ONE_LEVEL"); sym0 = GET_SYM(0); sym1 = GET_SYM(1); if (width == 2) { if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper_or_title(sym1)) return xkb_atom_intern_literal(ctx, "ALPHABETIC"); if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1)) return xkb_atom_intern_literal(ctx, "KEYPAD"); return xkb_atom_intern_literal(ctx, "TWO_LEVEL"); } if (width <= 4) { if (xkb_keysym_is_lower(sym0) && xkb_keysym_is_upper_or_title(sym1)) { xkb_keysym_t sym2, sym3; sym2 = GET_SYM(2); sym3 = (width == 4 ? GET_SYM(3) : XKB_KEY_NoSymbol); if (xkb_keysym_is_lower(sym2) && xkb_keysym_is_upper_or_title(sym3)) return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_ALPHABETIC"); return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_SEMIALPHABETIC"); } if (xkb_keysym_is_keypad(sym0) || xkb_keysym_is_keypad(sym1)) return xkb_atom_intern_literal(ctx, "FOUR_LEVEL_KEYPAD"); return xkb_atom_intern_literal(ctx, "FOUR_LEVEL"); } return XKB_ATOM_NONE; #undef GET_SYM } static const struct xkb_key_type * FindTypeForGroup(struct xkb_keymap *keymap, KeyInfo *keyi, xkb_layout_index_t group, bool *explicit_type) { GroupInfo *groupi = &darray_item(keyi->groups, group); xkb_atom_t type_name = groupi->type; *explicit_type = true; if (type_name == XKB_ATOM_NONE) { if (keyi->default_type != XKB_ATOM_NONE) { type_name = keyi->default_type; } else { type_name = FindAutomaticType(keymap->ctx, groupi); if (type_name != XKB_ATOM_NONE) *explicit_type = false; } } if (type_name == XKB_ATOM_NONE) { log_warn(keymap->ctx, XKB_WARNING_CANNOT_INFER_KEY_TYPE, "Couldn't find an automatic type for key '%s' " "group %"PRIu32" with %u levels; Using the default type\n", KeyNameText(keymap->ctx, keyi->name), group + 1, darray_size(groupi->levels)); goto use_default; } darray_size_t i; for (i = 0; i < keymap->num_types; i++) if (keymap->types[i].name == type_name) break; if (i >= keymap->num_types) { log_warn(keymap->ctx, XKB_WARNING_UNDEFINED_KEY_TYPE, "The type \"%s\" for key '%s' group %"PRIu32" " "was not previously defined; Using the default type\n", xkb_atom_text(keymap->ctx, type_name), KeyNameText(keymap->ctx, keyi->name), group + 1); goto use_default; } keymap->types[i].required = true; return &keymap->types[i]; use_default: /* * Index 0 is guaranteed to contain something, usually * ONE_LEVEL or at least some default one-level type. */ keymap->types[0].required = true; return &keymap->types[0]; } static bool CopySymbolsDefToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info, KeyInfo *keyi) { struct xkb_key *key; GroupInfo *groupi; const GroupInfo *group0; xkb_layout_index_t i; /* * The name is guaranteed to be real and not an alias (see * AddKeySymbols), so 'false' is safe here. */ key = XkbKeyByName(keymap, keyi->name, false); if (!key) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_DETAILED, XKB_WARNING_UNDEFINED_KEYCODE, "Key %s not found in keycodes; Symbols ignored\n", KeyInfoText(info, keyi)); return false; } /* Find the range of groups we need. */ key->num_groups = 0; darray_enumerate(i, groupi, keyi->groups) { /* Skip groups that have no levels and no explicit type. * Such group would be filled with `NoSymbol` anyway. */ const bool has_explicit_type = (keyi->defined & KEY_FIELD_DEFAULT_TYPE) || (groupi->defined & GROUP_FIELD_TYPE); if (darray_size(groupi->levels) > 0 || has_explicit_type) key->num_groups = i + 1; if (has_explicit_type) key->explicit |= EXPLICIT_TYPES; } if (key->num_groups <= 0) { /* A key with no group may still have other fields defined */ if (keyi->defined) goto key_fields; else return false; } darray_resize(keyi->groups, key->num_groups); /* * If there are empty groups between non-empty ones, fill them with data * from the first group. * We can make a wrong assumption here. But leaving gaps is worse. */ group0 = &darray_item(keyi->groups, 0); darray_foreach_from(groupi, keyi->groups, 1) { if (groupi->defined) continue; CopyGroupInfo(groupi, group0); } key->groups = calloc(key->num_groups, sizeof(*key->groups)); /* Find and assign the groups' types in the keymap. */ darray_enumerate(i, groupi, keyi->groups) { bool explicit_type = false; const struct xkb_key_type * const type = FindTypeForGroup(keymap, keyi, i, &explicit_type); /* Always have as many levels as the type specifies. */ if (type->num_levels < darray_size(groupi->levels)) { struct xkb_level *leveli; log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_EXTRA_SYMBOLS_IGNORED, "Type \"%s\" has %"PRIu32" levels, but %s has %u levels; " "Ignoring extra symbols\n", xkb_atom_text(keymap->ctx, type->name), type->num_levels, KeyInfoText(info, keyi), darray_size(groupi->levels)); darray_foreach_from(leveli, groupi->levels, type->num_levels) clear_level(leveli); } darray_resize0(groupi->levels, type->num_levels); key->groups[i].explicit_type = explicit_type; key->groups[i].type = type; } /* Copy levels. */ darray_enumerate(i, groupi, keyi->groups) { /* * Compute the capitalization transformation of the keysyms. * This is necessary because `xkb_state_key_get_syms()` returns an * immutable array and does not use a buffer, so we must store them. * We apply only simple capitalization rules, so the keysyms count is * unchanged. */ struct xkb_level *leveli; darray_foreach(leveli, groupi->levels) { switch (leveli->num_syms) { case 0: leveli->upper = XKB_KEY_NoSymbol; break; case 1: leveli->upper = xkb_keysym_to_upper(leveli->s.sym); break; default: /* Multiple keysyms: check if there is any cased keysym */ leveli->has_upper = false; for (xkb_keysym_count_t k = 0; k < leveli->num_syms; k++) { const xkb_keysym_t upper = xkb_keysym_to_upper(leveli->s.syms[k]); if (upper != leveli->s.syms[k]) { leveli->has_upper = true; break; } } if (leveli->has_upper) { /* * Some cased keysyms: store the transformation result in * the same array, right after the original keysyms. */ leveli->s.syms = realloc(leveli->s.syms, (size_t) 2 * leveli->num_syms * sizeof(*leveli->s.syms)); if (!leveli->s.syms) return false; /* FIXME: better handling? */ for (xkb_keysym_count_t k = 0; k < leveli->num_syms; k++) { leveli->s.syms[leveli->num_syms + k] = xkb_keysym_to_upper(leveli->s.syms[k]); } } } } /* Copy the level */ darray_steal(groupi->levels, &key->groups[i].levels, NULL); if (key->groups[i].type->num_levels > 1 || key->groups[i].levels[0].num_syms > 0) key->explicit |= EXPLICIT_SYMBOLS; if (groupi->defined & GROUP_FIELD_ACTS) { // FIXME key->groups[i].explicit_actions = true; key->explicit |= EXPLICIT_INTERP; } if (key->groups[i].explicit_type) key->explicit |= EXPLICIT_TYPES; } key->out_of_range_group_number = keyi->out_of_range_group_number; key->out_of_range_group_action = keyi->out_of_range_group_action; key_fields: if (keyi->defined & KEY_FIELD_VMODMAP) { key->vmodmap = keyi->vmodmap; key->explicit |= EXPLICIT_VMODMAP; } if (keyi->repeat != KEY_REPEAT_UNDEFINED) { key->repeats = (keyi->repeat == KEY_REPEAT_YES); key->explicit |= EXPLICIT_REPEAT; } return true; } static bool CopyModMapDefToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info, ModMapEntry *entry) { struct xkb_key *key; if (!entry->haveSymbol) { key = XkbKeyByName(keymap, entry->u.keyName, true); if (!key) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_DETAILED, XKB_WARNING_UNDEFINED_KEYCODE, "Key %s not found in keycodes; " "Modifier map entry for %s not updated\n", KeyNameText(info->ctx, entry->u.keyName), ModIndexText(info->ctx, &info->mods, entry->modifier)); return false; } } else { key = FindKeyForSymbol(keymap, entry->u.keySym); if (!key) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_DETAILED, XKB_WARNING_UNRESOLVED_KEYMAP_SYMBOL, "Key \"%s\" not found in symbol map; " "Modifier map entry for %s not updated\n", KeysymText(info->ctx, entry->u.keySym), ModIndexText(info->ctx, &info->mods, entry->modifier)); return false; } } /* Skip modMap None */ if (entry->modifier != XKB_MOD_NONE) { /* Convert modifier index to modifier mask */ key->modmap |= (UINT32_C(1) << entry->modifier); } return true; } static bool CopySymbolsToKeymap(struct xkb_keymap *keymap, SymbolsInfo *info) { KeyInfo *keyi; ModMapEntry *mm; keymap->symbols_section_name = strdup_safe(info->name); XkbEscapeMapName(keymap->symbols_section_name); keymap->mods = info->mods; keymap->num_group_names = (xkb_layout_index_t)darray_size(info->group_names); darray_steal(info->group_names, &keymap->group_names, NULL); darray_foreach(keyi, info->keys) if (!CopySymbolsDefToKeymap(keymap, info, keyi)) info->errorCount++; if (xkb_context_get_log_verbosity(keymap->ctx) > 3) { struct xkb_key *key; xkb_keys_foreach(key, keymap) { if (key->name == XKB_ATOM_NONE) continue; if (key->num_groups < 1) log_info(info->ctx, XKB_LOG_MESSAGE_NO_ID, "No symbols defined for %s\n", KeyNameText(info->ctx, key->name)); } } darray_foreach(mm, info->modmaps) if (!CopyModMapDefToKeymap(keymap, info, mm)) info->errorCount++; /* XXX: If we don't ignore errorCount, things break. */ return true; } bool CompileSymbols(XkbFile *file, struct xkb_keymap *keymap) { SymbolsInfo info; InitSymbolsInfo(&info, keymap, 0, &keymap->mods); if (file !=NULL) HandleSymbolsFile(&info, file); if (info.errorCount != 0) goto err_info; if (!CopySymbolsToKeymap(keymap, &info)) goto err_info; ClearSymbolsInfo(&info); return true; err_info: ClearSymbolsInfo(&info); return false; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/types.c000066400000000000000000000662521510033435100224400ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "xkbcomp-priv.h" #include "text.h" #include "vmod.h" #include "expr.h" #include "include.h" #include "utils.h" #include "util-mem.h" enum type_field { TYPE_FIELD_MASK = (1 << 0), TYPE_FIELD_MAP = (1 << 1), TYPE_FIELD_PRESERVE = (1 << 2), TYPE_FIELD_LEVEL_NAME = (1 << 3), }; typedef struct { enum type_field defined; enum merge_mode merge; xkb_atom_t name; xkb_mod_mask_t mods; xkb_level_index_t num_levels; darray(struct xkb_key_type_entry) entries; darray(xkb_atom_t) level_names; } KeyTypeInfo; typedef struct { char *name; int errorCount; unsigned int include_depth; darray(KeyTypeInfo) types; struct xkb_mod_set mods; struct xkb_context *ctx; } KeyTypesInfo; /***====================================================================***/ static inline const char * MapEntryTxt(KeyTypesInfo *info, struct xkb_key_type_entry *entry) { return ModMaskText(info->ctx, MOD_BOTH, &info->mods, entry->mods.mods); } static inline const char * TypeTxt(KeyTypesInfo *info, KeyTypeInfo *type) { return xkb_atom_text(info->ctx, type->name); } static inline const char * TypeMaskTxt(KeyTypesInfo *info, KeyTypeInfo *type) { return ModMaskText(info->ctx, MOD_BOTH, &info->mods, type->mods); } static inline bool ReportTypeShouldBeArray(KeyTypesInfo *info, KeyTypeInfo *type, const char *field) { return ReportShouldBeArray(info->ctx, "key type", field, TypeTxt(info, type)); } static inline bool ReportTypeBadType(KeyTypesInfo *info, xkb_message_code_t code, KeyTypeInfo *type, const char *field, const char *wanted) { return ReportBadType(info->ctx, code, "key type", field, TypeTxt(info, type), wanted); } /***====================================================================***/ static void InitKeyTypesInfo(KeyTypesInfo *info, struct xkb_context *ctx, unsigned int include_depth, const struct xkb_mod_set *mods) { memset(info, 0, sizeof(*info)); info->ctx = ctx; info->include_depth = include_depth; InitVMods(&info->mods, mods, include_depth > 0); } static void ClearKeyTypeInfo(KeyTypeInfo *type) { darray_free(type->entries); darray_free(type->level_names); } static void ClearKeyTypesInfo(KeyTypesInfo *info) { free(info->name); KeyTypeInfo *type; darray_foreach(type, info->types) ClearKeyTypeInfo(type); darray_free(info->types); } static KeyTypeInfo * FindMatchingKeyType(KeyTypesInfo *info, xkb_atom_t name) { KeyTypeInfo *old; darray_foreach(old, info->types) if (old->name == name) return old; return NULL; } static bool AddKeyType(KeyTypesInfo *info, KeyTypeInfo *new, bool same_file) { KeyTypeInfo *old; const int verbosity = xkb_context_get_log_verbosity(info->ctx); old = FindMatchingKeyType(info, new->name); if (old) { if (new->merge != MERGE_AUGMENT) { if ((same_file && verbosity > 0) || verbosity > 9) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_TYPE_DEFINITIONS, "Multiple definitions of the %s key type; " "Earlier definition ignored\n", xkb_atom_text(info->ctx, new->name)); } ClearKeyTypeInfo(old); *old = *new; darray_init(new->entries); darray_init(new->level_names); return true; } if (same_file) log_vrb(info->ctx, XKB_LOG_VERBOSITY_DETAILED, XKB_WARNING_CONFLICTING_KEY_TYPE_DEFINITIONS, "Multiple definitions of the %s key type; " "Later definition ignored\n", xkb_atom_text(info->ctx, new->name)); ClearKeyTypeInfo(new); return true; } darray_append(info->types, *new); return true; } /***====================================================================***/ static void MergeIncludedKeyTypes(KeyTypesInfo *into, KeyTypesInfo *from, enum merge_mode merge) { if (from->errorCount > 0) { into->errorCount += from->errorCount; return; } MergeModSets(into->ctx, &into->mods, &from->mods, merge); if (into->name == NULL) { into->name = steal(&from->name); } if (darray_empty(into->types)) { into->types = from->types; /* Types stolen via shallow copy, so reinitialize the array */ darray_init(from->types); } else { KeyTypeInfo *type; darray_foreach(type, from->types) { type->merge = merge; if (!AddKeyType(into, type, false)) into->errorCount++; } /* Types were either shallow copied or reinitialized individually in `AddKeyType`, so we only need to free the array */ darray_free(from->types); } } static void HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file); static bool HandleIncludeKeyTypes(KeyTypesInfo *info, IncludeStmt *include) { KeyTypesInfo included; if (ExceedsIncludeMaxDepth(info->ctx, info->include_depth)) { info->errorCount += 10; return false; } InitKeyTypesInfo(&included, info->ctx, info->include_depth + 1, &info->mods); included.name = steal(&include->stmt); for (IncludeStmt *stmt = include; stmt; stmt = stmt->next_incl) { KeyTypesInfo next_incl; XkbFile *file; char path[PATH_MAX]; file = ProcessIncludeFile(info->ctx, stmt, FILE_TYPE_TYPES, path, sizeof(path)); if (!file) { info->errorCount += 10; ClearKeyTypesInfo(&included); return false; } InitKeyTypesInfo(&next_incl, info->ctx, info->include_depth + 1, &included.mods); HandleKeyTypesFile(&next_incl, file); MergeIncludedKeyTypes(&included, &next_incl, stmt->merge); ClearKeyTypesInfo(&next_incl); FreeXkbFile(file); } MergeIncludedKeyTypes(info, &included, include->merge); ClearKeyTypesInfo(&included); return (info->errorCount == 0); } /***====================================================================***/ static bool SetModifiers(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, ExprDef *value) { xkb_mod_mask_t mods = 0; if (arrayNdx) log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "The modifiers field of a key type is not an array; " "Illegal array subscript ignored\n"); if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods, &mods)) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, "Key type mask field must be a modifier mask; " "Key type definition ignored\n"); return false; } if (type->defined & TYPE_FIELD_MASK) { log_warn(info->ctx, XKB_LOG_MESSAGE_NO_ID, "Multiple modifier mask definitions for key type %s; " "Using %s, ignoring %s\n", xkb_atom_text(info->ctx, type->name), TypeMaskTxt(info, type), ModMaskText(info->ctx, MOD_BOTH, &info->mods, mods)); return false; } type->mods = mods; return true; } /***====================================================================***/ static struct xkb_key_type_entry * FindMatchingMapEntry(KeyTypeInfo *type, xkb_mod_mask_t mods) { struct xkb_key_type_entry *entry; darray_foreach(entry, type->entries) if (entry->mods.mods == mods) return entry; return NULL; } static bool AddMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, struct xkb_key_type_entry *new, bool clobber, bool report) { struct xkb_key_type_entry *old; old = FindMatchingMapEntry(type, new->mods.mods); if (old) { if (report && old->level != new->level) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_TYPE_MAP_ENTRY, "Multiple map entries for %s in %s; " "Using %"PRIu32", ignoring %"PRIu32"\n", MapEntryTxt(info, new), TypeTxt(info, type), (clobber ? new->level : old->level) + 1, (clobber ? old->level : new->level) + 1); } else { log_vrb(info->ctx, XKB_LOG_VERBOSITY_VERBOSE, XKB_WARNING_CONFLICTING_KEY_TYPE_MAP_ENTRY, "Multiple occurrences of map[%s]= %"PRIu32" in %s; Ignored\n", MapEntryTxt(info, new), new->level + 1, TypeTxt(info, type)); return true; } if (clobber) { if (new->level >= type->num_levels) type->num_levels = new->level + 1; old->level = new->level; } return true; } if (new->level >= type->num_levels) type->num_levels = new->level + 1; darray_append(type->entries, *new); return true; } static bool SetMapEntry(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, ExprDef *value) { struct xkb_key_type_entry entry; if (arrayNdx == NULL) return ReportTypeShouldBeArray(info, type, "map entry"); if (!ExprResolveModMask(info->ctx, arrayNdx, MOD_BOTH, &info->mods, &entry.mods.mods)) return ReportTypeBadType(info, XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, type, "map entry", "modifier mask"); if (entry.mods.mods & (~type->mods)) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_UNDECLARED_MODIFIERS_IN_KEY_TYPE, "Map entry for modifiers not used by type %s; " "Using %s instead of %s\n", TypeTxt(info, type), ModMaskText(info->ctx, MOD_BOTH, &info->mods, entry.mods.mods & type->mods), MapEntryTxt(info, &entry)); entry.mods.mods &= type->mods; } if (!ExprResolveLevel(info->ctx, value, &entry.level)) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL, "Level specifications in a key type must be integer; " "Ignoring malformed level specification\n"); return false; } entry.preserve.mods = 0; return AddMapEntry(info, type, &entry, true, true); } /***====================================================================***/ static bool AddPreserve(KeyTypesInfo *info, KeyTypeInfo *type, xkb_mod_mask_t mods, xkb_mod_mask_t preserve_mods) { struct xkb_key_type_entry *entry; struct xkb_key_type_entry new; darray_foreach(entry, type->entries) { if (entry->mods.mods != mods) continue; /* Map exists without previous preserve (or "None"); override. */ if (entry->preserve.mods == 0) { entry->preserve.mods = preserve_mods; return true; } /* Map exists with same preserve; do nothing. */ if (entry->preserve.mods == preserve_mods) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_VERBOSE, XKB_WARNING_DUPLICATE_ENTRY, "Identical definitions for preserve[%s] in %s; " "Ignored\n", ModMaskText(info->ctx, MOD_BOTH, &info->mods, mods), TypeTxt(info, type)); return true; } /* Map exists with different preserve; latter wins. */ log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_CONFLICTING_KEY_TYPE_PRESERVE_ENTRIES, "Multiple definitions for preserve[%s] in %s; " "Using %s, ignoring %s\n", ModMaskText(info->ctx, MOD_BOTH, &info->mods, mods), TypeTxt(info, type), ModMaskText(info->ctx, MOD_BOTH, &info->mods, preserve_mods), ModMaskText(info->ctx, MOD_BOTH, &info->mods, entry->preserve.mods)); entry->preserve.mods = preserve_mods; return true; } /* * Map does not exist, i.e. preserve[] came before map[]. * Create a map with the specified mask mapping to Level1. The level * may be overridden later with an explicit map[] statement. */ new.level = 0; new.mods.mods = mods; new.preserve.mods = preserve_mods; darray_append(type->entries, new); return true; } static bool SetPreserve(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, ExprDef *value) { if (arrayNdx == NULL) return ReportTypeShouldBeArray(info, type, "preserve entry"); xkb_mod_mask_t mods = 0; if (!ExprResolveModMask(info->ctx, arrayNdx, MOD_BOTH, &info->mods, &mods)) return ReportTypeBadType(info, XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, type, "preserve entry", "modifier mask"); if (mods & ~type->mods) { const char *before, *after; before = ModMaskText(info->ctx, MOD_BOTH, &info->mods, mods); mods &= type->mods; after = ModMaskText(info->ctx, MOD_BOTH, &info->mods, mods); log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_UNDECLARED_MODIFIERS_IN_KEY_TYPE, "Preserve entry for modifiers not used by the %s type; " "Index %s converted to %s\n", TypeTxt(info, type), before, after); } xkb_mod_mask_t preserve_mods = 0; if (!ExprResolveModMask(info->ctx, value, MOD_BOTH, &info->mods, &preserve_mods)) { log_err(info->ctx, XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, "Preserve value in a key type is not a modifier mask; " "Ignoring preserve[%s] in type %s\n", ModMaskText(info->ctx, MOD_BOTH, &info->mods, mods), TypeTxt(info, type)); return false; } if (preserve_mods & ~mods) { const char *before, *after; before = ModMaskText(info->ctx, MOD_BOTH, &info->mods, preserve_mods); preserve_mods &= mods; after = ModMaskText(info->ctx, MOD_BOTH, &info->mods, preserve_mods); log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_ILLEGAL_KEY_TYPE_PRESERVE_RESULT, "Illegal value for preserve[%s] in type %s; " "Converted %s to %s\n", ModMaskText(info->ctx, MOD_BOTH, &info->mods, mods), TypeTxt(info, type), before, after); } return AddPreserve(info, type, mods, preserve_mods); } /***====================================================================***/ static bool AddLevelName(KeyTypesInfo *info, KeyTypeInfo *type, xkb_level_index_t level, xkb_atom_t name, bool clobber) { /* New name. */ if (level >= darray_size(type->level_names)) { darray_resize0(type->level_names, level + 1); goto finish; } /* Same level, same name. */ if (darray_item(type->level_names, level) == name) { log_vrb(info->ctx, XKB_LOG_VERBOSITY_VERBOSE, XKB_WARNING_DUPLICATE_ENTRY, "Duplicate names for level %"PRIu32" of key type %s; Ignored\n", level + 1, TypeTxt(info, type)); return true; } /* Same level, different name. */ if (darray_item(type->level_names, level) != XKB_ATOM_NONE) { const char *old, *new; old = xkb_atom_text(info->ctx, darray_item(type->level_names, level)); new = xkb_atom_text(info->ctx, name); log_vrb(info->ctx, XKB_LOG_VERBOSITY_BRIEF, XKB_WARNING_CONFLICTING_KEY_TYPE_LEVEL_NAMES, "Multiple names for level %"PRIu32" of key type %s; " "Using %s, ignoring %s\n", level + 1, TypeTxt(info, type), (clobber ? new : old), (clobber ? old : new)); if (!clobber) return true; } /* FIXME: What about different level, same name? */ finish: darray_item(type->level_names, level) = name; return true; } static bool SetLevelName(KeyTypesInfo *info, KeyTypeInfo *type, ExprDef *arrayNdx, ExprDef *value) { if (arrayNdx == NULL) return ReportTypeShouldBeArray(info, type, "level name"); xkb_level_index_t level = 0; if (!ExprResolveLevel(info->ctx, arrayNdx, &level)) return ReportTypeBadType(info, XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL, type, "level name", "integer"); xkb_atom_t level_name = XKB_ATOM_NONE; if (!ExprResolveString(info->ctx, value, &level_name)) { log_err(info->ctx, XKB_ERROR_WRONG_FIELD_TYPE, "Non-string name for level %"PRIu32" in key type %s; " "Ignoring illegal level name definition\n", level + 1, xkb_atom_text(info->ctx, type->name)); return false; } return AddLevelName(info, type, level, level_name, true); } /***====================================================================***/ static bool SetKeyTypeField(KeyTypesInfo *info, KeyTypeInfo *type, const char *field, ExprDef *arrayNdx, ExprDef *value) { bool ok = false; enum type_field type_field = 0; if (istreq(field, "modifiers")) { type_field = TYPE_FIELD_MASK; ok = SetModifiers(info, type, arrayNdx, value); } else if (istreq(field, "map")) { type_field = TYPE_FIELD_MAP; ok = SetMapEntry(info, type, arrayNdx, value); } else if (istreq(field, "preserve")) { type_field = TYPE_FIELD_PRESERVE; ok = SetPreserve(info, type, arrayNdx, value); } else if (istreq(field, "levelname") || istreq(field, "level_name")) { type_field = TYPE_FIELD_LEVEL_NAME; ok = SetLevelName(info, type, arrayNdx, value); } else { log_err(info->ctx, XKB_ERROR_UNKNOWN_FIELD, "Unknown field \"%s\" in key type \"%s\"; Definition ignored\n", field, TypeTxt(info, type)); } type->defined |= type_field; return ok; } static bool HandleKeyTypeBody(KeyTypesInfo *info, VarDef *def, KeyTypeInfo *type) { bool ok = true; const char *elem, *field; ExprDef *arrayNdx; for (; def; def = (VarDef *) def->common.next) { ok = ExprResolveLhs(info->ctx, def->name, &elem, &field, &arrayNdx); if (!ok) continue; if (elem) { if (istreq(elem, "type")) { log_err(info->ctx, XKB_ERROR_INVALID_SET_DEFAULT_STATEMENT, "Support for changing the default type has been removed; " "Statement \"%s.%s\" ignored.\n", elem, field); } else { log_err(info->ctx, XKB_ERROR_GLOBAL_DEFAULTS_WRONG_SCOPE, "Cannot set global defaults for \"%s\" element within " "a key type statement: move statements to the global " "file scope. Assignment to \"%s.%s\" ignored.\n", elem, elem, field); ok = false; } continue; } ok = SetKeyTypeField(info, type, field, arrayNdx, def->value); } return ok; } static bool HandleKeyTypeDef(KeyTypesInfo *info, KeyTypeDef *def) { KeyTypeInfo type = { .defined = 0, .merge = def->merge, .name = def->name, .mods = 0, .num_levels = 1, .entries = darray_new(), .level_names = darray_new(), }; if (!HandleKeyTypeBody(info, def->body, &type) || !AddKeyType(info, &type, true)) { info->errorCount++; ClearKeyTypeInfo(&type); return false; } /* Type has been either stolen via shallow copy or reinitialized in `AddKeyType`: no need to free the arrays */ return true; } static bool HandleGlobalVar(KeyTypesInfo *info, VarDef *stmt) { const char *elem, *field; ExprDef *arrayNdx; if (!ExprResolveLhs(info->ctx, stmt->name, &elem, &field, &arrayNdx)) return false; /* internal error, already reported */ if (elem && istreq(elem, "type")) { log_err(info->ctx, XKB_ERROR_WRONG_STATEMENT_TYPE, "Support for changing the default type has been removed; " "Statement ignored\n"); return true; } else if (elem) { log_err(info->ctx, XKB_ERROR_UNKNOWN_DEFAULT_FIELD, "Default defined for unknown element \"%s\"; " "Value for field \"%s.%s\" ignored\n", elem, elem, field); } else if (field) { log_err(info->ctx, XKB_ERROR_UNKNOWN_DEFAULT_FIELD, "Default defined for unknown field \"%s\"; Ignored\n", field); } return false; } static void HandleKeyTypesFile(KeyTypesInfo *info, XkbFile *file) { bool ok; free(info->name); info->name = strdup_safe(file->name); for (ParseCommon *stmt = file->defs; stmt; stmt = stmt->next) { switch (stmt->type) { case STMT_INCLUDE: ok = HandleIncludeKeyTypes(info, (IncludeStmt *) stmt); break; case STMT_TYPE: ok = HandleKeyTypeDef(info, (KeyTypeDef *) stmt); break; case STMT_VAR: ok = HandleGlobalVar(info, (VarDef*) stmt); break; case STMT_VMOD: ok = HandleVModDef(info->ctx, &info->mods, (VModDef *) stmt); break; default: log_err(info->ctx, XKB_ERROR_WRONG_STATEMENT_TYPE, "Key type files may not include other declarations; " "Ignoring %s\n", stmt_type_to_string(stmt->type)); ok = false; break; } if (!ok) info->errorCount++; if (info->errorCount > 10) { log_err(info->ctx, XKB_ERROR_INVALID_XKB_SYNTAX, "Abandoning keytypes file \"%s\"\n", safe_map_name(file)); break; } } } /***====================================================================***/ static bool CopyKeyTypesToKeymap(struct xkb_keymap *keymap, KeyTypesInfo *info) { const darray_size_t num_types = darray_empty(info->types) ? 1 : darray_size(info->types); struct xkb_key_type *types = calloc(num_types, sizeof(*types)); if (!types) return false; /* * The following types are called “Canonical Key Types” and the XKB protocol * specifies them as mandatory in any keymap: * * - ONE_LEVEL * - TWO_LEVEL * - ALPHABETIC * - KEYPAD * * They must have specific properties defined in the appendix B of * “The X Keyboard Extension: Protocol Specification”: * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#canonical_key_types * * In the Xorg ecosystem, any missing canonical type fallbacks to a default * type supplied by libX11’s `XkbInitCanonicalKeyTypes()`, e.g. in xkbcomp. * * libxkbcommon does not require these types per se: it only requires that * all *used* types — explicit (`type="…"`) or implicit (automatic types) — * are defined, with the exception that if no key type at all is defined, * then a default `ONE_LEVEL` type is provided. * * libxkbcommon also does not require any particular order of these key * types, because they are retrieved using their name instead of their index. * * Since 1.12 (31900860c65b88e4d10ad7dd00377e2815cca0f6), libxkbcommon drops * any *unused* key type at serialization by default. Some layouts with 4+ * levels may not require e.g. the `TWO_LEVEL` nor the `ALPHABETIC` types. * * In theory, libxkbcommon would not care of the presence of the canonical * key types and could delegate the property check, fallback and ordering * work to xkbcomp, as it is the case in Xorg’s Xwayland. However the * fallback implementation is buggy: * * - https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/292 * - https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2082 * * The canonical key types are always present in the keymap generated from * xkeyboard-config and custom keymaps usually include these types too. So * to circumvent the issues of Xorg, it should suffice that libxkbcommon * ensures to never discard the canonical key types, if present, and continue * to delegate the (unlikely) type fallbacks to xkbcomp. */ /* * If no types were specified, a default ONE_LEVEL type is * used for all keys. */ if (darray_empty(info->types)) { struct xkb_key_type *type = &types[0]; type->mods.mods = 0; type->num_levels = 1; type->entries = NULL; type->num_entries = 0; type->name = xkb_atom_intern_literal(keymap->ctx, "ONE_LEVEL"); type->level_names = NULL; type->num_level_names = 0; type->required = true; } else { /* HACK to circumvent Xorg bugs (see comment above) */ const xkb_atom_t canonical_types[] = { xkb_atom_intern_literal(keymap->ctx, "ONE_LEVEL"), xkb_atom_intern_literal(keymap->ctx, "TWO_LEVEL"), xkb_atom_intern_literal(keymap->ctx, "ALPHABETIC"), xkb_atom_intern_literal(keymap->ctx, "KEYPAD"), }; for (darray_size_t i = 0; i < num_types; i++) { KeyTypeInfo *def = &darray_item(info->types, i); struct xkb_key_type *type = &types[i]; type->name = def->name; type->mods.mods = def->mods; type->num_levels = def->num_levels; type->num_level_names = (xkb_level_index_t) darray_size(def->level_names); darray_steal(def->level_names, &type->level_names, NULL); darray_steal(def->entries, &type->entries, &type->num_entries); type->required = false; /* HACK: Never drop canonical XKB key types (see comment above) */ if (type->num_levels <= 2) { for (uint8_t t = 0; t < (uint8_t) ARRAY_SIZE(canonical_types); t++) { if (type->name == canonical_types[t]) { type->required = true; break; } } } } } keymap->types_section_name = strdup_safe(info->name); XkbEscapeMapName(keymap->types_section_name); keymap->num_types = num_types; keymap->types = types; keymap->mods = info->mods; return true; } /***====================================================================***/ bool CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap) { KeyTypesInfo info; InitKeyTypesInfo(&info, keymap->ctx, 0, &keymap->mods); if (file != NULL) HandleKeyTypesFile(&info, file); if (info.errorCount != 0) goto err_info; if (!CopyKeyTypesToKeymap(keymap, &info)) goto err_info; ClearKeyTypesInfo(&info); return true; err_info: ClearKeyTypesInfo(&info); return false; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/vmod.c000066400000000000000000000144271510033435100222360ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "atom.h" #include "keymap.h" #include "text.h" #include "expr.h" #include "xkbcomp/ast.h" #include "vmod.h" void InitVMods(struct xkb_mod_set *info, const struct xkb_mod_set *mods, bool reset) { *info = *mods; if (!reset) return; struct xkb_mod *mod; xkb_mod_index_t vmod = 0; xkb_mods_enumerate(vmod, mod, info) { mod->mapping = 0; } info->explicit_vmods = 0; } void MergeModSets(struct xkb_context *ctx, struct xkb_mod_set *into, const struct xkb_mod_set *from, enum merge_mode merge) { const bool clobber = (merge != MERGE_AUGMENT); xkb_mod_index_t vmod; const struct xkb_mod *mod; assert(into->num_mods <= from->num_mods); xkb_mods_enumerate(vmod, mod, from) { const xkb_mod_mask_t mask = UINT32_C(1) << vmod; if ((mod->type != MOD_VIRT)) { /* No modifier in `from` or real modifier: nothing to do */ assert((mod->type == 0 && mod->name == XKB_ATOM_NONE) || ((mod->type & MOD_REAL) && into->mods[vmod].type == mod->type && mod->name != XKB_ATOM_NONE && into->mods[vmod].name == mod->name)); continue; } else if (into->mods[vmod].type == 0) { /* No modifier in `into`: copy the whole modifier definition */ assert(into->mods[vmod].name == XKB_ATOM_NONE); assert(mod->type == MOD_VIRT); assert(mod->name != XKB_ATOM_NONE); assert(vmod >= into->num_mods); into->mods[vmod] = *mod; if (from->explicit_vmods & mask) into->explicit_vmods |= mask; } else { /* Modifier exists in both */ assert(mod->type == MOD_VIRT); assert(mod->name != XKB_ATOM_NONE); assert(into->mods[vmod].type == mod->type); assert(into->mods[vmod].name == mod->name); if (!(from->explicit_vmods & mask)) { /* Implicit mapping in `from`: do nothing */ assert(mod->mapping == 0); } else if (!(into->explicit_vmods & mask)) { /* Implicit mapping in `into`: replace */ assert(into->mods[vmod].mapping == 0); into->mods[vmod].mapping = mod->mapping; into->explicit_vmods |= mask; } else if (mod->mapping != into->mods[vmod].mapping) { /* Handle conflicting mappings */ const xkb_mod_mask_t use = (clobber) ? mod->mapping : into->mods[vmod].mapping; const xkb_mod_mask_t ignore = (clobber) ? into->mods[vmod].mapping : mod->mapping; log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "Virtual modifier %s mapping defined multiple times; " "Using %s, ignoring %s\n", xkb_atom_text(ctx, mod->name), ModMaskText(ctx, MOD_REAL, from, use), ModMaskText(ctx, MOD_REAL, from, ignore)); into->mods[vmod].mapping = use; } } } into->num_mods = from->num_mods; } bool HandleVModDef(struct xkb_context *ctx, struct xkb_mod_set *mods, VModDef *stmt) { xkb_mod_mask_t mapping = 0; if (stmt->value) { /* * This is a statement such as 'virtualModifiers NumLock = Mod1'; * it initialize the vmod-to-real-mod[s] mapping before going * through modifier_map. */ if (!ExprResolveModMask(ctx, stmt->value, MOD_REAL, mods, &mapping)) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Declaration of %s ignored\n", xkb_atom_text(ctx, stmt->name)); return false; } } xkb_mod_index_t vmod; struct xkb_mod *mod; xkb_mods_enumerate(vmod, mod, mods) { if (mod->name == stmt->name) { if (mod->type != MOD_VIRT) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Can't add a virtual modifier named \"%s\"; there is " "already a non-virtual modifier with this name! " "Ignored\n", xkb_atom_text(ctx, mod->name)); return false; } const xkb_mod_mask_t mask = UINT32_C(1) << vmod; if (!stmt->value) { /* No new explicit mapping: do nothing */ return true; } else if (!(mods->explicit_vmods & mask)) { /* No previous explicit mapping: add mapping */ mod->mapping = mapping; } else if (mod->mapping != mapping) { /* Handle conflicting mappings */ const bool clobber = (stmt->merge != MERGE_AUGMENT); const xkb_mod_mask_t use = (clobber ? mapping : mod->mapping); const xkb_mod_mask_t ignore = (clobber ? mod->mapping : mapping); log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "Virtual modifier %s mapping defined multiple times; " "Using %s, ignoring %s\n", xkb_atom_text(ctx, stmt->name), ModMaskText(ctx, MOD_REAL, mods, use), ModMaskText(ctx, MOD_REAL, mods, ignore)); mod->mapping = use; } mods->explicit_vmods |= mask; return true; } } if (mods->num_mods >= XKB_MAX_MODS) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Cannot define virtual modifier %s: " "too many modifiers defined (maximum %u)\n", xkb_atom_text(ctx, stmt->name), XKB_MAX_MODS); return false; } mods->mods[mods->num_mods].name = stmt->name; mods->mods[mods->num_mods].type = MOD_VIRT; mods->mods[mods->num_mods].mapping = mapping; if (stmt->value) { const xkb_mod_mask_t mask = UINT32_C(1) << mods->num_mods; mods->explicit_vmods |= mask; } mods->num_mods++; return true; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/vmod.h000066400000000000000000000010421510033435100222300ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #pragma once #include "config.h" #include "xkbcommon/xkbcommon.h" #include #include "ast.h" #include "keymap.h" void InitVMods(struct xkb_mod_set *info, const struct xkb_mod_set *mods, bool reset); void MergeModSets(struct xkb_context *ctx, struct xkb_mod_set *into, const struct xkb_mod_set *from, enum merge_mode merge); bool HandleVModDef(struct xkb_context *ctx, struct xkb_mod_set *mods, VModDef *stmt); xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/xkbcomp-priv.h000066400000000000000000000057701510033435100237200ustar00rootroot00000000000000/* * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. * SPDX-License-Identifier: HPND */ #pragma once #include "config.h" #include "keymap.h" #include "ast.h" #include "scanner-utils.h" char * text_v1_keymap_get_as_string(struct xkb_keymap *keymap, enum xkb_keymap_format format, enum xkb_keymap_serialize_flags flags); XkbFile * XkbParseFile(struct xkb_context *ctx, FILE *file, const char *file_name, const char *map); bool XkbParseStringInit(struct xkb_context *ctx, struct scanner *scanner, const char *string, size_t len, const char *file_name, const char *map); XkbFile * XkbParseString(struct xkb_context *ctx, const char *string, size_t len, const char *file_name, const char *map); bool XkbParseStringNext(struct xkb_context *ctx, struct scanner *scanner, const char *map, XkbFile **out); void FreeXkbFile(XkbFile *file); XkbFile * XkbFileFromComponents(struct xkb_context *ctx, const struct xkb_component_names *kkctgs); bool CompileKeycodes(XkbFile *file, struct xkb_keymap *keymap); bool CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap); bool CompileCompatMap(XkbFile *file, struct xkb_keymap *keymap); bool CompileSymbols(XkbFile *file, struct xkb_keymap *keymap); bool CompileKeymap(XkbFile *file, struct xkb_keymap *keymap); extern const struct xkb_sym_interpret default_interpret; /***====================================================================***/ static inline bool ReportNotArray(struct xkb_context *ctx, const char *type, const char *field, const char *name) { log_err(ctx, XKB_ERROR_WRONG_FIELD_TYPE, "The %s %s field is not an array; " "Ignoring illegal assignment in %s\n", type, field, name); return false; } static inline bool ReportShouldBeArray(struct xkb_context *ctx, const char *type, const char *field, const char *name) { log_err(ctx, XKB_ERROR_EXPECTED_ARRAY_ENTRY, "Missing subscript for %s %s; " "Ignoring illegal assignment in %s\n", type, field, name); return false; } static inline bool ReportBadType(struct xkb_context *ctx, xkb_message_code_t code, const char *type, const char *field, const char *name, const char *wanted) { log_err(ctx, code, "The %s %s field must be a %s; " "Ignoring illegal assignment in %s\n", type, field, wanted, name); return false; } static inline bool ReportBadField(struct xkb_context *ctx, const char *type, const char *field, const char *name) { log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "Unknown %s field \"%s\" in %s; " "Ignoring assignment to unknown field in %s\n", type, field, name, name); return false; } static inline const char* safe_map_name(XkbFile *file) { return file->name ? file->name : "(unnamed map)"; } xkbcommon-libxkbcommon-54ee7ac/src/xkbcomp/xkbcomp.c000066400000000000000000000173601510033435100227330ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT * * Author: Dan Nicholson * Author: Ran Benita * Author: Daniel Stone */ #include "config.h" #include #include "darray.h" #include "utils.h" #include "xkbcommon/xkbcommon.h" #include "xkbcomp-priv.h" #include "keymap.h" #include "rules.h" #include "rmlvo.h" bool xkb_components_names_from_rules(struct xkb_context *ctx, const struct xkb_rule_names *rmlvo_in, struct xkb_rule_names *rmlvo_out, struct xkb_component_names *components_out) { /* Resolve default RMLVO values. We need a mutable copy of the input. */ struct xkb_rule_names rmlvo = *rmlvo_in; xkb_context_sanitize_rule_names(ctx, &rmlvo); if (rmlvo_out) { /* Copy the sanitized RMLVO, if required. */ *rmlvo_out = rmlvo; } if (!components_out) { /* KcCGST not required. * While RMLVO and KcCGST outputs are both optional, at least one must * be provided. */ return !!rmlvo_out; } /* Resolve the RMLVO names to KcCGST components */ *components_out = (struct xkb_component_names){ 0 }; return xkb_components_from_rules_names(ctx, &rmlvo, components_out, NULL); } static bool compile_keymap_file(struct xkb_keymap *keymap, XkbFile *file) { if (file->file_type != FILE_TYPE_KEYMAP) { log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Cannot compile a %s file alone into a keymap\n", xkb_file_type_to_string(file->file_type)); return false; } if (!CompileKeymap(file, keymap)) { log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Failed to compile keymap\n"); return false; } return true; } static bool text_v1_keymap_new_from_rmlvo(struct xkb_keymap *keymap, const struct xkb_rmlvo_builder *rmlvo) { bool ok; struct xkb_component_names kccgst; XkbFile *file; if (keymap->ctx->log_level >= XKB_LOG_LEVEL_DEBUG) { struct xkb_rule_names names = { 0 }; const size_t buf_size = sizeof(rmlvo->ctx->text_buffer) - 1; char *buf = xkb_context_get_buffer(rmlvo->ctx, buf_size); if (unlikely(!buf)) return false; ok = xkb_rmlvo_builder_to_rules_names(rmlvo, &names, buf, buf_size); if (unlikely(!ok)) return false; log_dbg(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Compiling from RMLVO builder: rules '%s', model '%s', layout '%s', " "variant '%s', options '%s'\n", names.rules, names.model, names.layout, names.variant, names.options); } /* Resolve the RMLVO components to KcCGST components and get the * expected number of layouts */ ok = xkb_components_from_rmlvo_builder(rmlvo, &kccgst, &keymap->num_groups); if (!ok) { struct xkb_rule_names names = { 0 }; const size_t buf_size = sizeof(rmlvo->ctx->text_buffer); char *buf = xkb_context_get_buffer(rmlvo->ctx, buf_size); if (unlikely(!buf)) return false; ok = xkb_rmlvo_builder_to_rules_names(rmlvo, &names, buf, buf_size); if (unlikely(!ok)) return false; log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Couldn't look up rules '%s', model '%s', layout '%s', " "variant '%s', options '%s'\n", names.rules, names.model, names.layout, names.variant, names.options); return false; } const xkb_layout_index_t max_groups = format_max_groups(keymap->format); if (keymap->num_groups > max_groups) keymap->num_groups = max_groups; log_dbg(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Compiling from KcCGST: keycodes '%s', types '%s', " "compat '%s', symbols '%s'\n", kccgst.keycodes, kccgst.types, kccgst.compatibility, kccgst.symbols); file = XkbFileFromComponents(keymap->ctx, &kccgst); free(kccgst.keycodes); free(kccgst.types); free(kccgst.compatibility); free(kccgst.symbols); free(kccgst.geometry); if (!file) { log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Failed to generate parsed XKB file from components\n"); return false; } ok = compile_keymap_file(keymap, file); FreeXkbFile(file); return ok; } static bool text_v1_keymap_new_from_names(struct xkb_keymap *keymap, const struct xkb_rule_names *rmlvo) { bool ok; struct xkb_component_names kccgst; XkbFile *file; log_dbg(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Compiling from RMLVO: rules '%s', model '%s', layout '%s', " "variant '%s', options '%s'\n", rmlvo->rules, rmlvo->model, rmlvo->layout, rmlvo->variant, rmlvo->options); /* Resolve the RMLVO components to KcCGST components and get the * expected number of layouts */ ok = xkb_components_from_rules_names(keymap->ctx, rmlvo, &kccgst, &keymap->num_groups); if (!ok) { log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Couldn't look up rules '%s', model '%s', layout '%s', " "variant '%s', options '%s'\n", rmlvo->rules, rmlvo->model, rmlvo->layout, rmlvo->variant, rmlvo->options); return false; } const xkb_layout_index_t max_groups = format_max_groups(keymap->format); if (keymap->num_groups > max_groups) keymap->num_groups = max_groups; log_dbg(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, "Compiling from KcCGST: keycodes '%s', types '%s', " "compat '%s', symbols '%s'\n", kccgst.keycodes, kccgst.types, kccgst.compatibility, kccgst.symbols); file = XkbFileFromComponents(keymap->ctx, &kccgst); free(kccgst.keycodes); free(kccgst.types); free(kccgst.compatibility); free(kccgst.symbols); free(kccgst.geometry); if (!file) { log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Failed to generate parsed XKB file from components\n"); return false; } ok = compile_keymap_file(keymap, file); FreeXkbFile(file); return ok; } static bool text_v1_keymap_new_from_string(struct xkb_keymap *keymap, const char *string, size_t len) { bool ok; XkbFile *xkb_file; xkb_file = XkbParseString(keymap->ctx, string, len, "(input string)", NULL); if (!xkb_file) { log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Failed to parse input xkb string\n"); return false; } ok = compile_keymap_file(keymap, xkb_file); FreeXkbFile(xkb_file); return ok; } static bool text_v1_keymap_new_from_file(struct xkb_keymap *keymap, FILE *file) { bool ok; XkbFile *xkb_file; xkb_file = XkbParseFile(keymap->ctx, file, "(unknown file)", NULL); if (!xkb_file) { log_err(keymap->ctx, XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Failed to parse input xkb file\n"); return false; } ok = compile_keymap_file(keymap, xkb_file); FreeXkbFile(xkb_file); return ok; } const struct xkb_keymap_format_ops text_v1_keymap_format_ops = { .keymap_new_from_rmlvo = text_v1_keymap_new_from_rmlvo, .keymap_new_from_names = text_v1_keymap_new_from_names, .keymap_new_from_string = text_v1_keymap_new_from_string, .keymap_new_from_file = text_v1_keymap_new_from_file, .keymap_get_as_string = text_v1_keymap_get_as_string, }; xkbcommon-libxkbcommon-54ee7ac/test/000077500000000000000000000000001510033435100176425ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/atom.c000066400000000000000000000120321510033435100207440ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "test.h" #include "atom.h" #define INTERN_LITERAL(table, literal) \ atom_intern(table, literal, sizeof(literal) - 1, true) #define LOOKUP_LITERAL(table, literal) \ atom_intern(table, literal, sizeof(literal) - 1, false) static void random_string(char **str_out, size_t *len_out) { /* Keep this small, so collisions might happen. */ static const char random_chars[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' }; size_t len; char *str; len = rand() % 15; str = malloc(len + 1); assert(str); for (size_t i = 0; i < len; i++) str[i] = random_chars[rand() % ARRAY_SIZE(random_chars)]; /* Don't always terminate it; should work without. */ if (rand() % 2 == 0) str[len] = '\0'; *str_out = str; *len_out = len; } static void test_random_strings(void) { struct atom_string { xkb_atom_t atom; char *string; size_t len; }; struct atom_table *table; struct atom_string *arr; int N; xkb_atom_t atom; const char *string; table = atom_table_new(); assert(table); N = 1 + rand() % 100000; arr = calloc(N, sizeof(*arr)); assert(arr); for (int i = 0; i < N; i++) { random_string(&arr[i].string, &arr[i].len); atom = atom_intern(table, arr[i].string, arr[i].len, false); if (atom != XKB_ATOM_NONE) { string = atom_text(table, atom); assert(string); if (arr[i].len != strlen(string) || strncmp(string, arr[i].string, arr[i].len) != 0) { fprintf(stderr, "got a collision, but strings don't match!\n"); fprintf(stderr, "existing length %zu, string %s\n", strlen(string), string); fprintf(stderr, "new length %zu, string %.*s\n", arr[i].len, (int) arr[i].len, arr[i].string); assert(false); } /* OK, got a real collision. */ free(arr[i].string); i--; continue; } arr[i].atom = atom_intern(table, arr[i].string, arr[i].len, true); if (arr[i].atom == XKB_ATOM_NONE) { fprintf(stderr, "failed to intern! len: %zu, string: %.*s\n", arr[i].len, (int) arr[i].len, arr[i].string); assert(false); } } for (int i = 0; i < N; i++) { string = atom_text(table, arr[i].atom); assert(string); if (arr[i].len != strlen(string) || strncmp(string, arr[i].string, arr[i].len) != 0) { fprintf(stderr, "looked-up string doesn't match!\n"); fprintf(stderr, "found length %zu, string %s\n", strlen(string), string); fprintf(stderr, "expected length %zu, string %.*s\n", arr[i].len, (int) arr[i].len, arr[i].string); /* Since this is random, we need to dump the failing data, * so we might have some chance to reproduce. */ fprintf(stderr, "START dump of arr, N=%d\n", N); for (int j = 0; j < N; j++) { fprintf(stderr, "%u\t\t%zu\t\t%.*s\n", arr[i].atom, arr[i].len, (int) arr[i].len, arr[i].string); } fprintf(stderr, "END\n"); assert(false); } } for (int i = 0; i < N; i++) free(arr[i].string); free(arr); atom_table_free(table); } /* CLI positional arguments: * 1. Seed for the pseudo-random generator: * - Leave it unset or set it to “-” to use current time. * - Use an integer to set it explicitly. */ int main(int argc, char *argv[]) { struct atom_table *table; xkb_atom_t atom1, atom2, atom3; test_init(); /* Initialize pseudo-random generator with program arg or current time */ unsigned int seed; if (argc >= 2 && !streq(argv[1], "-")) { seed = (unsigned int) atoi(argv[1]); } else { seed = (unsigned int) time(NULL); } fprintf(stderr, "Seed for the pseudo-random generator: %u\n", seed); srand(seed); table = atom_table_new(); assert(table); assert(atom_text(table, XKB_ATOM_NONE) == NULL); assert(atom_intern(table, NULL, 0, false) == XKB_ATOM_NONE); atom1 = INTERN_LITERAL(table, "hello"); assert(atom1 != XKB_ATOM_NONE); assert(atom1 == LOOKUP_LITERAL(table, "hello")); assert(streq(atom_text(table, atom1), "hello")); atom2 = atom_intern(table, "hello", 3, true); assert(atom2 != XKB_ATOM_NONE); assert(atom1 != atom2); assert(streq(atom_text(table, atom2), "hel")); assert(LOOKUP_LITERAL(table, "hel") == atom2); assert(LOOKUP_LITERAL(table, "hell") == XKB_ATOM_NONE); assert(LOOKUP_LITERAL(table, "hello") == atom1); atom3 = atom_intern(table, "", 0, true); assert(atom3 != XKB_ATOM_NONE); assert(LOOKUP_LITERAL(table, "") == atom3); atom_table_free(table); test_random_strings(); return 0; } xkbcommon-libxkbcommon-54ee7ac/test/buffercomp.c000066400000000000000000003141261510033435100221450ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include "keymap.h" #include "src/keysym.h" #include "test/keysym.h" #include "test.h" #include "utils.h" #include "xkbcommon/xkbcommon.h" #include "test-config.h" #define GOLDEN_TESTS_OUTPUTS "keymaps/" struct keymap_test_data { /** Keymap string to compile */ const char * const keymap; /** Resulting file *path* to reference serialization, * or NULL if the keymap string should not compile. */ const char * const expected; /** Optionally skip the test */ bool skip; }; /* Our keymap compiler is the xkbcommon buffer compiler */ static struct xkb_keymap * compile_buffer(struct xkb_context *context, enum xkb_keymap_format format, const char *buf, size_t len, void *private) { return test_compile_buffer(context, format, buf, len); } static void test_encodings(struct xkb_context *ctx) { struct xkb_keymap *keymap; /* Accept UTF-8 encoded BOM (U+FEFF) */ const char utf8_with_bom[] = "\xef\xbb\xbfxkb_keymap {};"; keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, utf8_with_bom, sizeof(utf8_with_bom)); assert(keymap); xkb_keymap_unref(keymap); /* Reject UTF-16LE encoded string */ const char utf16_le[] = "x\0k\0b\0_\0k\0e\0y\0m\0a\0p\0 \0{\0}\0;\0"; keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, utf16_le, sizeof(utf16_le)); assert(!keymap); /* Reject UTF-16LE with BOM encoded string */ const char utf16_le_with_bom[] = "\xff\xfex\0k\0b\0_\0k\0e\0y\0m\0a\0p\0 \0{\0}\0;\0"; keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, utf16_le_with_bom, sizeof(utf16_le_with_bom)); assert(!keymap); /* Reject UTF-16BE encoded string */ const char utf16_be[] = "\0x\0k\0b\0_\0k\0e\0y\0m\0a\0p\0 \0{\0}\0;"; keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, utf16_be, sizeof(utf16_be)); assert(!keymap); } struct keymap_simple_test_data { const char * const keymap; bool valid; }; static void test_floats(struct xkb_context *ctx) { const struct keymap_simple_test_data tests[] = { /* Valid floats */ { .keymap = "xkb_keymap {\n" " xkb_geometry {\n" " width=123.456;\n" " width=123.0;\n" " width=123.;\n" " width=01.234;\n" " width=01.0;\n" " width=01.;\n" " width=001.234;\n" " width=001.0;\n" " width=001.;\n" " };" "};", .valid = true }, /* Invalid: missing integer part */ { .keymap = "xkb_keymap { xkb_geometry { width=.123; }; };", .valid = false }, /* Invalid: comma decimal separator */ { .keymap = "xkb_keymap { xkb_geometry { width=1,23; }; };", .valid = false }, /* Invalid: exponent */ { .keymap = "xkb_keymap { xkb_geometry { width=1.23e2; }; };", .valid = false }, }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, tests[k].keymap, strlen(tests[k].keymap)); assert(tests[k].valid ^ !keymap); xkb_keymap_unref(keymap); } } static void test_component_syntax_error(struct xkb_context *ctx) { /* The following used to trigger memory leak */ const char* const keymaps[] = { "xkb_keymap {" " xkb_keycodes {};" "};" "};", /* Syntax error, keymap “complete” */ "xkb_keymap {" " xkb_keycodes {};" " xkb_types {};" " xkb_compat {};" " xkb_symbols {};" "};" "};"/* Syntax error, keymap complete */, "xkb_keymap {" " xkb_keycodes {};" "}" /* Syntax error, incomplete map */ " xkb_types {};" " xkb_compat {};" " xkb_symbols {};" "};", "xkb_keymap {" " xkb_keycodes {};" ";" /* Syntax error, incomplete map */ " xkb_types {};" " xkb_compat {};" " xkb_symbols {};" "};", }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); const struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymaps[k], strlen(keymaps[k])); assert(!keymap); } } /** Test that any component is optional and can be empty */ static void test_optional_components(struct xkb_context *ctx, bool update_output_files) { const struct keymap_test_data keymaps[] = { /* * Optional or empty */ { .keymap = "xkb_keymap {};", .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb" }, { .keymap = "xkb_keymap { xkb_keycodes {}; };", .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb" }, { .keymap = "xkb_keymap { xkb_types {}; };", .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb" }, { .keymap = "xkb_keymap { xkb_compat {}; };", .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb" }, { .keymap = "xkb_keymap { xkb_symbols {}; };", .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb" }, /* * Some content, to check we handle missing data correctly */ { /* Indicator not defined in keycodes */ .keymap = "xkb_keymap {\n" " xkb_compat { indicator \"XXX\" { modifiers=Lock; }; };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "optional-components-no-real-led.xkb" }, { /* Key not defined */ .keymap = "xkb_keymap {\n" " xkb_symbols { key <> { [a] }; };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "optional-components-none.xkb" }, { /* Key type not defined */ .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };" " xkb_symbols { key <> { [a], type=\"XXX\" }; };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "optional-components-basic.xkb" }, { /* Virtual modifier not defined */ .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };" " xkb_symbols { key <> { vmods=XXX, [a] }; };\n" "};", .expected = NULL }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_bidi_chars(struct xkb_context *ctx, bool update_output_files) { const struct keymap_test_data keymaps[] = { /* Invalid: first char must be ASCII */ { .keymap = u8"\u200Exkb_keymap {};", .expected = NULL }, { .keymap = u8"\u200Fxkb_keymap {};", .expected = NULL }, /* Valid */ { .keymap = u8" \u200Fxkb_keymap\u200E\u200F\n\u200E{ " u8"\u200Exkb_keycodes \u200F{ " u8"<>\u200E= \u200F1\u200E;\u200F" u8"}\u200E ;" u8"};\u200E", .expected = GOLDEN_TESTS_OUTPUTS "bidi.xkb" } }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_recursive_includes(struct xkb_context *ctx) { struct xkb_keymap *keymap; const char* const keymaps[] = { /* Recursive keycodes */ "Keycodes: recursive", "xkb_keymap {" " xkb_keycodes { include \"evdev+recursive\" };" " xkb_types { include \"complete\" };" " xkb_compat { include \"complete\" };" " xkb_symbols { include \"pc\" };" "};", "Keycodes: recursive(bar)", "xkb_keymap {" " xkb_keycodes { include \"evdev+recursive(bar)\" };" " xkb_types { include \"complete\" };" " xkb_compat { include \"complete\" };" " xkb_symbols { include \"pc\" };" "};", /* Recursive key types */ "Key types: recursive", "xkb_keymap {" " xkb_keycodes { include \"evdev\" };" " xkb_types { include \"recursive\" };" " xkb_compat { include \"complete\" };" " xkb_symbols { include \"pc\" };" "};", "Key types: recursive(bar)", "xkb_keymap {" " xkb_keycodes { include \"evdev\" };" " xkb_types { include \"recursive(bar)\" };" " xkb_compat { include \"complete\" };" " xkb_symbols { include \"pc\" };" "};", /* Recursive compat */ "Compat: recursive", "xkb_keymap {" " xkb_keycodes { include \"evdev\" };" " xkb_types { include \"recursive\" };" " xkb_compat { include \"complete\" };" " xkb_symbols { include \"pc\" };" "};", "Compat: recursive(bar)", "xkb_keymap {" " xkb_keycodes { include \"evdev\" };" " xkb_types { include \"complete\" };" " xkb_compat { include \"recursive(bar)\" };" " xkb_symbols { include \"pc\" };" "};", /* Recursive symbols */ "Symbols: recursive", "xkb_keymap {" " xkb_keycodes { include \"evdev\" };" " xkb_types { include \"complete\" };" " xkb_compat { include \"complete\" };" " xkb_symbols { include \"recursive\" };" "};", "Symbols: recursive(bar)", "xkb_keymap {" " xkb_keycodes { include \"evdev\" };" " xkb_types { include \"complete\" };" " xkb_compat { include \"complete\" };" " xkb_symbols { include \"recursive(bar)\" };" "};" }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u %s ***\n", __func__, k, keymaps[k]); k++; keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymaps[k], strlen(keymaps[k])); assert(!keymap); } } static void test_include_paths(struct xkb_context *ctx) { struct xkb_keymap *keymap; const char simple_str[] = "xkb_keymap {\n" " xkb_keycodes \"test\" { include \"evdev\" };\n" " xkb_types \"test\" { include \"complete\" };\n" " xkb_symbols \"test\" { include \"pc+us(basic)+" "level5\" };\n" "};"; keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, simple_str, sizeof(simple_str)); char *expected = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); xkb_keymap_unref(keymap); static const char* keymaps[] = { "xkb_keymap {\n" " xkb_keycodes \"test\" { include \"%S/evdev\" };\n" " xkb_types \"test\" { include \"%S/complete\" };\n" " xkb_symbols \"test\" { include \"%S/pc+%S/us(basic)+" "%S/level5\" };\n" "};", /* Windows absolute path contains “:”, which has special meaning in XKB includes, * so skip it. */ #ifndef _WIN32 "xkb_keymap {\n" " xkb_keycodes \"test\" { include \"" TEST_XKB_CONFIG_ROOT "/keycodes/evdev\" };\n" " xkb_types \"test\" { include \"" TEST_XKB_CONFIG_ROOT "/types/complete\" };\n" " xkb_symbols \"test\" { include \"" TEST_XKB_CONFIG_ROOT "/symbols/pc+" TEST_XKB_CONFIG_ROOT "/symbols/us(basic)+" TEST_XKB_CONFIG_ROOT "/symbols/level5\" };\n" "};", #endif }; /* Relative path, which does not work as expected, because it is * not resolved before %-expansion. */ setenv("XKB_CONFIG_ROOT", "..", 1); keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymaps[0], strlen(keymaps[0])); assert(!keymap); setenv("XKB_CONFIG_ROOT", TEST_XKB_CONFIG_ROOT, 1); for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymaps[k], strlen(keymaps[k])); assert(keymap); char *got = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); assert_streq_not_null("test_include_paths", expected, got); free(got); xkb_keymap_unref(keymap); } free(expected); } static void test_include_default_maps(bool update_output_files) { struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES); assert(ctx); /* “User” config */ char *include_path = test_get_path("extra"); assert(include_path); assert(xkb_context_include_path_append(ctx, include_path)); free(include_path); /* “System” config */ include_path = test_get_path(""); assert(include_path); assert(xkb_context_include_path_append(ctx, include_path)); free(include_path); const struct keymap_test_data keymaps[] = { { /* Use system explicit default map */ .keymap = "xkb_keymap {\n" " xkb_keycodes { = 66; };\n" " xkb_symbols { include \"capslock\" };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "include-capslock-system.xkb" }, { /* Use custom named map */ .keymap = "xkb_keymap {\n" " xkb_keycodes { = 66; };\n" " xkb_symbols { include \"capslock(custom)\" };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "include-capslock-custom.xkb" }, { /* Use custom *explicit* default map */ .keymap = "xkb_keymap {\n" " xkb_keycodes { = 108; = 92; };\n" " xkb_types { include \"basic\" };\n" " xkb_symbols { include \"level3\" };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "include-level3-explicit-default.xkb" }, { /* Use custom *implicit* default map */ .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { include \"banana\" };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "include-banana-implicit-default.xkb" }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } xkb_context_unref(ctx); } /* Test some limits related to allocations */ static void test_alloc_limits(struct xkb_context *ctx, bool update_output_files) { const struct keymap_test_data keymaps[] = { /* Keycodes */ { .keymap = "xkb_keymap {\n" /* Valid & supported high keycode value */ " xkb_keycodes { <> = 0xfffffffe; };\n" " xkb_symbols { key <> {[a]}; };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "high-keycodes-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 0xfffffffe;\n" " <> = 0xfffffffd;\n" " <> = 0xfffffffe;\n" " };\n" " xkb_symbols { key <> {[a]}; };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "high-keycodes-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " <> = 7;\n" " <> = 8;\n" " <> = 0xfffffffd;\n" " <> = 0xfffffffe;\n" " };\n" " xkb_symbols { key <> {[a]}; };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "high-keycodes-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " <> = 0xfffffffd;\n" " <> = 0xfffffffe;\n" " <> = 7;\n" " <> = 8;\n" " };\n" " xkb_symbols { key <> {[a]}; };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "high-keycodes-2.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 0xfffffffd;\n" " = 0xfffffffe;\n" " };\n" " xkb_symbols {\n" " key {[a]};\n" " key {[b]};\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "high-keycodes-3.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 0xfffffffe;\n" " = 0xfffffffd;\n" " };\n" " xkb_symbols {\n" " key {[a]};\n" " key {[b]};\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "high-keycodes-3.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 0xf;\n" " = 0x4000;\n" " = 0xfffffffe;\n" " = 0x2000;\n" " = 0xfff;\n" " };\n" " xkb_symbols {\n" " key {[a]};\n" " key {[b]};\n" " key {[c]};\n" " key {[d]};\n" " key {[e]};\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "high-keycodes-4.xkb" }, /* Key types */ { .keymap = "xkb_keymap {\n" " xkb_types {\n" /* Invalid level index */ " type \"X\" { map[none] = 0xfffffffe; };\n" " };\n" "};", .expected = NULL }, { .keymap = "xkb_keymap {\n" " xkb_types {\n" /* Invalid level index */ " type \"X\" {levelname[0xfffffffe]=\"x\";};\n" " };\n" "};", .expected = NULL } }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_integers(struct xkb_context *ctx, bool update_output_files) { /* Using a buffer without a terminating NULL. The following is a obvious * syntax error, but it should still exit *cleanly*, not as previously where * the use of strtoll would trigger a memory violation. */ const char not_null_terminated[] = { '1' }; assert(!test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, not_null_terminated, sizeof(not_null_terminated))); const bool skipOverflow = sizeof(int64_t) >= sizeof (long long); if (skipOverflow) { fprintf(stderr, "[WARNING] %s: cannot use checked arithmetic\n", __func__); } const struct keymap_test_data keymaps[] = { { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" /* Out of range (expect 32 bits, got > 64 bits) */ " <> = 0x10000000000000000;\n" " };\n" "};", .expected = NULL }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_compat {\n" " };\n" " xkb_symbols {\n" " key <> {\n" /* Checked int64_t underflow */ " [MovePointer(x=-0x7fffffffffffffff - 2,\n" " y=0)]\n" " };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "integers-overflow.xkb", .skip = skipOverflow }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_compat {\n" " };\n" " xkb_symbols {\n" " key <> {\n" /* Checked int64_t underflow */ " [MovePointer(x=-0x7fffffffffffffff * 2,\n" " y=0)]\n" " };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "integers-overflow.xkb", .skip = skipOverflow }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_compat {\n" " };\n" " xkb_symbols {\n" " key <> {\n" " [MovePointer(x=0,\n" /* Checked int64_t overflow */ " y=0x7fffffffffffffff + 1)]\n" " };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "integers-overflow.xkb", .skip = skipOverflow }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_compat {\n" " };\n" " xkb_symbols {\n" " key <> {\n" " [MovePointer(x=0,\n" /* Checked int64_t overflow */ " y=0x7fffffffffffffff * 2)]\n" " };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "integers-overflow.xkb", .skip = skipOverflow }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " <> = 1;\n" " indicator 32 = \"xxx\";\n" " };\n" " xkb_compat {\n" " group 0xffffffff = Mod5;\n" " };\n" " xkb_symbols {\n" /* Computations with 64 bit ints that then fit into 16 bits */ " key <> {\n" " actions[1 + -~0x100000001 / 0x100000000]=\n" " [MovePointer(x=0x100000000 - 0xfffffffe,\n" " y=~-0x7fff * 0x30000 / 0x2ffff)],\n" /* Test (INT64_MIN + 1) and INT64_MAX */ " [MovePointer(x=-9223372036854775807\n" " +9223372036854775807)]\n" " };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "integers.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols {\n" /* We cannot parse INT64_MIN literal. * If we could, the following should fit into 16 bits. */ " key <> {\n" " [MovePointer(x=-9223372036854775808\n" " +9223372036854775807)]\n" " };\n" " };\n" "};", .expected = NULL }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " <0> = 10;\n" " <1> = 11;\n" " <2> = 12;\n" " = 20;\n" " = 21;\n" " = 22;\n" " };\n" " xkb_types {\n" " type \"FOUR_LEVEL\" {\n" " modifiers = Shift + Control;\n" " map[None] = 01;\n" " map[Shift] = 2;\n" " map[Control] = 3;\n" " };\n" " }\n;" " xkb_compat {\n" " interpret 0 { action = LockGroup(group=2); };\n" " interpret 00 { action = LockGroup(group=3); };\n" " interpret 0x0 { action = LockGroup(group=4); };\n" " interpret 1 { action = LockGroup(group=-1); };\n" " interpret 01 { action = LockGroup(group=1); };\n" " interpret 2 { action = LockGroup(group=-2); };\n" " interpret 02 { action = LockGroup(group=2); };\n" " interpret 3 { action = LockGroup(group=-3); };\n" " interpret 0x3 { action = LockGroup(group=3); };\n" " };\n" " xkb_symbols {\n" /* Various numeric keysyms forms. * Single digits have a special interpretation in symbols */ " key <0> { [ 0, 00, 0x0] };\n" " key <1> { [ 1, 01, 0x1] };\n" " key <2> { [ 2, 02, 0x2] };\n" " key { [ 3 ] };\n" " key { [ 04 ] };\n" " key { [ 0x5 ] };\n" " modifier_map Shift { 0, 3 };\n" " modifier_map Lock { 00, 04 };\n" " modifier_map Control { 0x0, 0x5 };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "digits.xkb" }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); if (keymaps[k].skip) { fprintf(stderr, "INFO: skip test\n"); continue; } assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_keycodes(struct xkb_context *ctx, bool update_output_files) { const struct keymap_test_data keymaps[] = { /* * Ensure keycodes bound are correctly updated. * * Since expanding bounds is tested in the rest of the code, we test * only shrinking here. */ /* Single keycode */ { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 0;\n" " override = 1;\n" " augment = 300;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 300;\n" " override = 1;\n" " augment = 0;\n" " };\n" "};", /* NOTE: same as previous */ .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 0;\n" " override = 1;\n" " override = 301;\n" " override = 300;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-2.xkb" }, /* Multiple keycodes to single keycode */ { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 300;\n" " = 1;\n" " augment = 301;\n" " override = 1;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 0;\n" " = 1;\n" " augment = 300;\n" " override = 1;\n" " };\n" "};", /* NOTE: same as previous */ .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-1.xkb" }, /* Multiple keycodes to multiple keycodes */ { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " = 0;\n" " override = 300;\n" " augment = 0;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-multiple-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 301;\n" " = 300;\n" " override = 1;\n" " augment = 302;\n" " };\n" "};", /* NOTE: same as previous */ .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-multiple-1.xkb" }, /* High keycodes */ { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " include \"high\"\n" " = 2;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-multiple-2.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 0x10000;\n" " = 0x10001;\n" " = 1;\n" " = 0x10002;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-multiple-3.xkb" }, /* Aliases */ { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " = 1;\n" " alias = ;\n" /* C target is invalid */ " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " alias = ;\n" /* C target is invalid */ " = 1;\n" " = 1;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " = 1;\n" " alias = ;\n" /* C target is valid */ " = 2;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-aliases-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " alias = ;\n" /* C target is valid */ " = 1;\n" " = 1;\n" " = 2;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-aliases-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " alias = ;\n" " = 1;\n" /* Override alias */ " = 300;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-multiple-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " alias = ;\n" " augment = 3;\n" /* Do not override alias */ " = 1;\n" " = 2;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-aliases-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " = 3;\n" " alias = ;\n" /* Override key */ " = 2;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-aliases-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " augment alias = ;\n" /* Do not override key */ " = 300;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-multiple-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " = 2;\n" " alias = ;\n" /* Override key, even if invalid entry */ " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " alias = ;\n" " = 1;\n" /* Override both alias and key */ " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-bounds-single-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" /* * Multiple aliases *before* names: check that the key name LUT * overwrite is done properly. */ " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias = ;\n" " alias

= 33;\n" " = 38;\n" " = 39;\n" " = 40;\n" " = 41;\n" " = 42;\n" " = 43;\n" " = 52;\n" " = 53;\n" " = 54;\n" " = 55;\n" " = 56;\n" " = 57;\n" " = 58;\n" " };\n" " xkb_types {\n" " type \"t1\" {};\n" " type \"t2\" { modifiers = Shift; map[Shift] = 2; };\n" " };\n" " xkb_compat {\n" " virtual_modifiers M1, M2;\n" " indicator \"xxx\" {};\n" " indicator.modifiers = Shift;" " indicator \"yyy\" {};\n" "\n" " interpret q {};\n" " interpret.repeat = true;\n" " interpret w {};\n" " };\n" " xkb_symbols {\n" " key { [q] };\n" " key { [SetMods()] };\n" " key { [e], type = \"t1\" };\n" /* Empty key */ " key {};\n" /* Empty key, same as previous */ " key { [] };\n" /* Override empty key with another */ " key {};\n" " key { [] };\n" /* Override empty key with some symbols */ " key {};\n" " key { [], [u] };\n" /* Override non-empty key with an empty key */ " key { [i] };\n" " key {};\n" /* Empty symbols/actions */ " key { [NoSymbol] };\n" " key

{ [NoAction()] };\n" /* No symbols nor actions: other properties */ " key { vmods = M1 };\n" " key { repeat = false };\n" " key { type = \"t2\" };\n" " key { [], type = \"t2\" };\n" " key { type[1] = \"t2\" };\n" " key { type[1] = \"t1\", type[2] = \"t2\" };\n" /* Test key defaults / modmaps */ " key {};\n" " key.vmods = M1;\n" " key {};\n" " key { vmods = M2 };\n" " key.type = \"t2\";\n" " key { vmods = 0 };\n" " key { [], vmods = 0 };\n" " key.type[1] = \"t1\";\n" " key { vmods = 0 };\n" " key { [], [], vmods = 0 };\n" " modmap Shift { };\n" " modmap Lock { };\n" " modmap Control { };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "empty-compound-statements.xkb" }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_escape_sequences(struct xkb_context *ctx, bool update_output_files) { /* Similarly to `test_integers`, test that escape sequences at the end of * a buffer raise a syntax error but no memory violation */ const char bad_octal[] = { '"', '\\', '1' }; assert(!test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, bad_octal, sizeof(bad_octal))); const char bad_unicode[] = { '"', '\\', 'u', '{', '1' }; assert(!test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, bad_unicode, sizeof(bad_unicode))); const char keymap[] = "default xkb_keymap \"\" {\n" " xkb_keycodes " "\"\\u{0}La paix est la seule\\tbataille " "qui vaille la peine d\\u{02019}\\u{Ea}tre men\\303\\251e.\\n\" {\n" " <> = 1;\n" " indicator 1 = \"\\0\\n\\u{2328}\\u{fe0f}\";\n" " indicator 2 = \"surrogates: \\u{d800} \\u{dfff}\";\n" " indicator 3 = \"noncharacters: \\u{fdd0} \\u{fdef} \\u{fffe} \\u{ffff}\";\n" " indicator 4 = \"noncharacters: \\u{1fffe} \\u{1ffff} \\u{10fffe} \\u{10ffff}\";\n" " indicator 5 = \"out of range: \\u{0} a \\u{110000} \\u{ffffffffffff}\";\n" " indicator 6 = \"invalid: \\u a \\uA b \\u{} c \\u{ d \\u} e \\u{1\";\n" " indicator 7 = \"invalid: \\u{1234x\\\" y \";\n" " indicator 8 = \"invalid: \\u{ 2} x \\u{3 } y\";\n" " indicator 9 = \"\\u{+1} \\u{-1} \\u{x} \\u{#} \\u{\\0} \\u{\\}\";\n" " };\n" " xkb_types \"\\00001\\\\\\00427\\u{22}\\r\\n\" {\n" " type \"\\0\\00451\\u{1F3BA}\\u{2728}\\u{01F54a}\\u{0fE0f}\\f\" {\n" " modifiers = Shift;\n" " map[Shift] = 2;\n" " level_name[1] = " "\"O\\u{f9} ils ont fait un \\u{22}d\\303\\251sert\\u{22}, \\e" "ils disent qu\\u{002019}ils \\12ont fait la \\42paix\\042.\\b\\n\";\n" " level_name[2] = " "\"\\u{0000}Science \\u{73}\\141ns conscience " "n\\u{2019}est que rui\\\\ne\\u{A} de l\\u{02019}\\u{E2}me.\\r\";\n" " };\n" " };\n" " xkb_compat " "\"Le c\\u{153}ur a \\v ses raisons " "que la raison ne con\\u{5C}na\\u{EE}t point\" {\n" " indicator \"\\n\\u{2328}\\0\\u{fe0f}\" { modifiers = Shift; };\n" " };\n" " xkb_symbols " "\"La libert\\u{00e9} commence " "o\\u{0000f9} l\\342\\200\\231ignorance finit.\" {\n" " name[1] = \"\\n\\0377\\3760\";\n" " name[2] = \"\\00427\";\n" " key <> {\n" " symbols[1]=[a, A],\n" " type[1]=\"%1\\u{1F3BA}\\u{2728}\\u{00001F54a}\\u{0fE0f}\\u{0C}\",\n" " actions[2]=[Private(type=123, data=\"\0abcdefg\")]" " };\n" " };\n" "};"; const char expected[] = GOLDEN_TESTS_OUTPUTS "escape-sequences.xkb"; assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymap, ARRAY_SIZE(keymap), expected, update_output_files)); } static void test_unicode_keysyms(struct xkb_context *ctx, bool update_output_files) { struct keymap_test_data keymaps[] = { { .keymap = "xkb_keymap {\n" " xkb_keycodes { include \"evdev\" };\n" " xkb_types { include \"basic\" };\n" " xkb_symbols {\n" /* C0 Control characters */ " key { [U0000, 0x01000000 ] };\n" " key { [U0001, 0x01000001 ] };\n" " key { [U000A, 0x0100000a ] };\n" " key { [U001F, 0x0100001f ] };\n" /* Printable ASCII characters */ " key { [U0020, 0x01000020 ] };\n" " key { [U007E, 0x0100007e ] };\n" /* C0/C1 control characters */ " key { [U007F, 0x0100007f ] };\n" " key { [U0080, 0x01000080 ] };\n" " key { [U009F, 0x0100009f ] };\n" /* Latin-1 printable characters */ " key { [U00A0, 0x010000a0 ] };\n" " key { [U00FF, 0x010000ff ] };\n" /* Misc: bounds */ " key { [U0100, 0x01000100 ] };\n" " key { [UD7FF, 0x0100d7ff ] };\n" /* Surrogates */ " key { [UD800, 0x0100d800 ] };\n" " key { [UDFFF, 0x0100dfff ] };\n" /* Misc: bounds */ " key { [UE000, 0x0100e000 ] };\n" " key { [UFDCF, 0x0100fdcf ] };\n" /* Noncharacters */ " key { [UFDD0, 0x0100fdd0 ] };\n" " key { [UFDEF, 0x0100fdef ] };\n" /* Misc: bounds */ " key { [UFDF0, 0x0100fdf0 ] };\n" " key { [UFFFD, 0x0100fffd ] };\n" /* Noncharacters */ " key { [UFFFE, 0x0100fffe ] };\n" " key { [UFFFF, 0x0100ffff ] };\n" /* Misc: bounds */ " key { [U10000, 0x01010000 ] };\n" /* Noncharacters */ " key { [U1FFFE , 0x0101fffe ] };\n" " key { [U1FFFF , 0x0101ffff ] };\n" " key { [U10FFFE, 0x0110fffe ] };\n" /* Max Unicode */ " key { [U10FFFF, 0x0110ffff ] };\n" /* Max Unicode + 1 */ " key { [U110000, 0x01110000 ] };\n" /* Misc */ " key { [U0174, 0x01000174 ] };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "unicode-keysyms.xkb" }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_no_action_void_action(struct xkb_context *ctx, bool update_output_files) { const char keymap_str[] = "xkb_keymap {\n" " xkb_keycodes { <1> = 1; <2> = 2; <3> = 3; };\n" " xkb_symbols {\n" /* These actions take no argument */ " key <1> { [x], [NoAction(mods=1)] };\n" " key <2> { [y], [VoidAction(mods=1)] };\n" /* Check that we can overwrite NoAction, but not the contrary */ " key <3> { [NoAction()] };\n" " key <3> { [VoidAction()] };\n" " key <3> { [NoAction()] };\n" " };\n" "};"; /* v1 → v1 */ assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymap_str, sizeof(keymap_str), GOLDEN_TESTS_OUTPUTS "no_void_action-v1.xkb", update_output_files)); /* v1 → v2 */ assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_FORMAT_TEXT_V2, compile_buffer, NULL, __func__, keymap_str, sizeof(keymap_str), GOLDEN_TESTS_OUTPUTS "no_void_action-v2.xkb", update_output_files)); /* v2 → v2 */ assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymap_str, sizeof(keymap_str), GOLDEN_TESTS_OUTPUTS "no_void_action-v2.xkb", update_output_files)); /* v2 → v1 */ assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_FORMAT_TEXT_V1, compile_buffer, NULL, __func__, keymap_str, sizeof(keymap_str), GOLDEN_TESTS_OUTPUTS "no_void_action-v1.xkb", update_output_files)); } static void test_prebuilt_keymap_roundtrip(struct xkb_context *ctx, bool update_output_files) { /* Load in a prebuilt keymap, make sure we can compile it from memory, * then compare it to make sure we get the same result when dumping it * to a string. */ static const struct { const char* path; enum xkb_keymap_format format; enum xkb_keymap_serialize_flags serialize_flags; } data[] = { { .path = "keymaps/stringcomp-v1.xkb", .format = XKB_KEYMAP_FORMAT_TEXT_V1, .serialize_flags = TEST_KEYMAP_SERIALIZE_FLAGS }, { .path = "keymaps/stringcomp-v1-no-prettyfied.xkb", .format = XKB_KEYMAP_FORMAT_TEXT_V1, .serialize_flags = TEST_KEYMAP_SERIALIZE_FLAGS & ~XKB_KEYMAP_SERIALIZE_PRETTY }, { .path = "keymaps/stringcomp-v2.xkb", .format = XKB_KEYMAP_FORMAT_TEXT_V2, .serialize_flags = TEST_KEYMAP_SERIALIZE_FLAGS }, }; for (unsigned int k = 0; k < ARRAY_SIZE(data); k++) { char *original = test_read_file(data[k].path); assert(original); /* Load a prebuild keymap, once without, once with the trailing \0 */ for (unsigned int i = 0; i <= 1; i++) { assert(test_compile_output2(ctx, data[k].format, XKB_KEYMAP_USE_ORIGINAL_FORMAT, data[k].serialize_flags, compile_buffer, NULL, "Round-trip", original, strlen(original) + i, data[k].path, update_output_files)); } free(original); } } static void test_keymap_from_rules(struct xkb_context *ctx) { /* Make sure we can recompile our output for a normal keymap from rules. */ fprintf(stderr, "------\n*** %s ***\n", __func__); struct xkb_keymap *keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, NULL, NULL, "ru,ca,de,us", ",multix,neo,intl", NULL); assert(keymap); char *dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); assert(dump); xkb_keymap_unref(keymap); keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, dump, strlen(dump)); assert(keymap); xkb_keymap_unref(keymap); free(dump); } static void test_unsupported_legacy_x11_actions(struct xkb_context *ctx, bool update_output_files) { const char keymap_str[] = "xkb_keymap {\n" " xkb_keycodes {\n" " <1> = 1;\n" " <2> = 2;\n" " <3> = 3;\n" " <4> = 4;\n" " <5> = 5;\n" " <6> = 6;\n" " };\n" " xkb_compat {\n" " RedirectKey.key = <1>;\n" " RedirectKey.data = <1>;\n" /* invalid field */ " ISOLock.modifiers = modMapMods;\n" " DeviceButton.data = <1>;\n" /* invalid field */ " LockDeviceButton.data = <1>;\n" /* invalid field */ " DeviceValuator.data = <1>;\n" /* invalid field */ " ActionMessage.data = <1>;\n" /* invalid field */ " interpret ISO_Lock {\n" " action=ISOLock(affect=all);\n" " };\n" " interpret VoidSymbol {\n" " action=RedirectKey(data=<1>);\n" /* invalid field */ " };\n" " };\n" " xkb_symbols {\n" " key <1> { [ISOLock(affect=all)] };\n" " key <2> { [RedirectKey(data=<1>)] };\n" /* invalid field */ " key <3> { [DeviceButton(data=<1>)] };\n" /* invalid field */ " key <4> { [LockDeviceButton(data=<1>)] };\n" /* invalid field */ " key <5> { [DeviceValuator(data=<1>)] };\n" /* invalid field */ " key <6> { [ActionMessage(data=<1>)] };\n" /* invalid field */ " };\n" "};"; assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymap_str, sizeof(keymap_str), GOLDEN_TESTS_OUTPUTS "unsupported-x11-actions", update_output_files)); } static void test_extended_layout_indices(struct xkb_context *ctx, bool update_output_files) { const struct { const char* keymap; bool no_output; union { struct { bool compiles_v1; bool compiles_v2; }; struct { const char* expected_v1; const char* expected_v1_2; const char* expected_v2; const char* expected_v2_1; }; }; } tests[] = { { .keymap = "xkb_keymap {\n" " xkb_compat { interpret a { action = SetGroup(group=5); }; };\n" "};", .no_output = true, .compiles_v1 = false, .compiles_v2 = true, }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { indicator 1 = \"a\"; };\n" " xkb_compat { indicator \"a\" { groups=All-5; }; };\n" "};", .no_output = true, .compiles_v1 = true, .compiles_v2 = true, }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { name[5] = \"5\"; };\n" "};", .no_output = true, .compiles_v1 = false, .compiles_v2 = true, }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { key <> { [1], [2], [3], [4], [5] }; };\n" "};", .no_output = true, .compiles_v1 = false, .compiles_v2 = true, }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " = 2;\n" " = 3;\n" " indicator 1 = \"a\";\n" " };\n" " xkb_compat {\n" " interpret a { action = SetGroup(group=5); };\n" " indicator \"a\" { groups=All-5; };\n" " };\n" " xkb_symbols {\n" " name[5] = \"G5\";\n" " name[1] = \"G1\";\n" " key { symbols[1]=[a], symbols[5]=[Greek_alpha] };\n" " key { actions[1]=[Latchgroup(group=-5)], actions[5]=[LockGroup(group=5)], [SetGroup(+9)] };\n" " key { [1], [2], [3], [4], [5], [6], [7], [8], [9] };\n" " };\n" "};", .expected_v1 = NULL, .expected_v1_2 = NULL, .expected_v2 = GOLDEN_TESTS_OUTPUTS "extended-layout-indices-v2.xkb", .expected_v2_1 = GOLDEN_TESTS_OUTPUTS "extended-layout-indices-v1.xkb", } }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); if (tests[k].no_output) { struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, tests[k].keymap, strlen(tests[k].keymap)); assert(!!keymap == tests[k].compiles_v1); xkb_keymap_unref(keymap); keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, tests[k].keymap, strlen(tests[k].keymap)); assert(!!keymap == tests[k].compiles_v2); xkb_keymap_unref(keymap); continue; } /* v1 → v1 */ assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, tests[k].keymap, strlen(tests[k].keymap), tests[k].expected_v1, update_output_files)); /* v1 → v2 */ assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_FORMAT_TEXT_V2, compile_buffer, NULL, __func__, tests[k].keymap, strlen(tests[k].keymap), tests[k].expected_v1_2, update_output_files)); /* v2 → v2 */ assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, tests[k].keymap, strlen(tests[k].keymap), tests[k].expected_v2, update_output_files)); /* v2 → v1 */ assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_FORMAT_TEXT_V1, compile_buffer, NULL, __func__, tests[k].keymap, strlen(tests[k].keymap), tests[k].expected_v2_1, update_output_files)); } } int main(int argc, char *argv[]) { test_init(); bool update_output_files = false; /* Default seed for pseudo-random generator */ unsigned int seed = (unsigned int) time(NULL); int arg_index = 0; while (++arg_index < argc) { if (streq(argv[arg_index], "update")) { /* Update files with *obtained* results */ update_output_files = true; } else if (streq(argv[arg_index], "--seed") && arg_index + 1 < argc) { seed = (unsigned int) atoi(argv[arg_index + 1]); } else { fprintf(stderr, "ERROR: unsupported argument: \"%s\".\n", argv[arg_index]); exit(EXIT_INVALID_USAGE); } } /* Initialize pseudo-random generator with program arg or current time */ fprintf(stderr, "Seed for the pseudo-random generator: %u\n", seed); srand(seed); struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); /* Make sure we can't (falsely claim to) compile an empty string. */ struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "", 0); assert(!keymap); test_encodings(ctx); test_floats(ctx); test_component_syntax_error(ctx); test_optional_components(ctx, update_output_files); test_bidi_chars(ctx, update_output_files); test_recursive_includes(ctx); test_include_paths(ctx); test_include_default_maps(update_output_files); test_alloc_limits(ctx, update_output_files); test_integers(ctx, update_output_files); test_keycodes(ctx, update_output_files); test_masks(ctx, update_output_files); test_interpret(ctx, update_output_files); test_group_indices_names(ctx, update_output_files); test_level_indices_names(ctx, update_output_files); test_multi_keysyms_actions(ctx, update_output_files); test_key_keysyms_as_strings(ctx, update_output_files); test_invalid_symbols_fields(ctx); test_modifier_maps(ctx, update_output_files); test_empty_compound_statements(ctx, update_output_files); test_escape_sequences(ctx, update_output_files); test_unicode_keysyms(ctx, update_output_files); test_no_action_void_action(ctx, update_output_files); test_prebuilt_keymap_roundtrip(ctx, update_output_files); test_keymap_from_rules(ctx); test_unsupported_legacy_x11_actions(ctx, update_output_files); test_extended_layout_indices(ctx, update_output_files); xkb_context_unref(ctx); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/common.c000066400000000000000000000624411510033435100213050ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT-open-group * * Author: Dan Nicholson * Daniel Stone * Ran Benita */ #include "config.h" #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #include #else #include #include #endif #include "xkbcommon/xkbcommon.h" #include "darray.h" #include "keymap.h" #include "test.h" #include "utils.h" #include "utils-paths.h" #include "src/keysym.h" #include "src/xkbcomp/rules.h" #include "src/utils-numbers.h" #include "tools/tools-common.h" /* Setup test */ void test_init(void) { /* Make stdout always unbuffered, to ensure we always get it entirely */ setvbuf(stdout, NULL, _IONBF, BUFSIZ); /* Enable to use another locale than C or en_US, so we can catch * locale-specific bugs */ setlocale(LC_ALL, ""); } void print_detailed_state(struct xkb_state *state) { fprintf(stderr, " Layout: base: %"PRId32", latched: %"PRId32", locked: %"PRId32", " "effective: %"PRIu32"\n", xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED), xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED), xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED), xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE)); fprintf(stderr, " Modifiers: base: %#"PRIx32", latched: %#"PRIx32", " "locked: %#"PRIx32", effective: %#"PRIx32"\n", xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED), xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED), xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED), xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE)); /* There is currently no xkb_state_serialize_leds */ struct xkb_keymap *keymap = xkb_state_get_keymap(state); xkb_led_mask_t leds = 0; for (xkb_led_index_t led = 0; led < xkb_keymap_num_leds(keymap); led++) { if (xkb_state_led_index_is_active(state, led) > 0) leds |= UINT32_C(1) << led; } fprintf(stderr, " LEDs: 0x%x\n", leds); } /* * Test a sequence of keysyms, resulting from a sequence of key presses, * against the keysyms they're supposed to generate. * * - Each test runs with a clean state. * - Each line in the test is made up of: * + A keycode, given as a KEY_* from linux/input.h. * + A direction - DOWN for press, UP for release, BOTH for * immediate press + release, REPEAT to just get the syms. * + A sequence of keysyms that should result from this keypress. * * The vararg format is: * * * See below for examples. */ int test_key_seq_va(struct xkb_keymap *keymap, va_list ap) { struct xkb_state *state; xkb_keycode_t kc; int op; xkb_keysym_t keysym; const xkb_keysym_t *syms; xkb_keysym_t sym; char ksbuf[XKB_KEYSYM_NAME_MAX_SIZE]; const char *opstr = NULL; fprintf(stderr, "----\n"); state = xkb_state_new(keymap); assert(state); for (;;) { kc = va_arg(ap, int) + EVDEV_OFFSET; op = va_arg(ap, int); switch (op) { case DOWN: opstr = "DOWN"; break; case REPEAT: opstr = "REPEAT"; break; case UP: opstr = "UP"; break; case BOTH: opstr = "BOTH"; break; case NEXT: opstr = "NEXT"; break; case FINISH: opstr = "FINISH"; break; default: fprintf(stderr, "ERROR: Unsupported operation: %d\n", op); goto fail; } const int nsyms = xkb_state_key_get_syms(state, kc, &syms); if (nsyms == 1) { sym = xkb_state_key_get_one_sym(state, kc); syms = &sym; } if (op == DOWN || op == BOTH) xkb_state_update_key(state, kc, XKB_KEY_DOWN); if (op == UP || op == BOTH) xkb_state_update_key(state, kc, XKB_KEY_UP); #if HAVE_TOOLS tools_print_keycode_state("", state, NULL, kc, (op == DOWN ? XKB_KEY_DOWN : XKB_KEY_UP), XKB_CONSUMED_MODE_XKB, PRINT_ALL_FIELDS | PRINT_UNILINE); #endif fprintf(stderr, "op %-6s got %d syms for keycode %3"PRIu32": [", opstr, nsyms, kc); for (int i = 0; i < nsyms; i++) { keysym = va_arg(ap, int); xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf)); fprintf(stderr, "%s%s", (i != 0) ? ", " : "", ksbuf); if (keysym == FINISH || keysym == NEXT) { xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf)); fprintf(stderr, "\nERROR: Did not expect keysym: %s.\n", ksbuf); goto fail; } if (keysym != syms[i]) { xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf)); fprintf(stderr, "\nERROR: Expected keysym: %s. ", ksbuf);; xkb_keysym_get_name(syms[i], ksbuf, sizeof(ksbuf)); fprintf(stderr, " Got keysym: %s.\n", ksbuf);; goto fail; } } if (nsyms == 0) { keysym = va_arg(ap, int); if (keysym != XKB_KEY_NoSymbol) { xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf)); fprintf(stderr, "\nERROR: Expected %s, but got no keysyms.\n", ksbuf); goto fail; } } fprintf(stderr, "]\n"); keysym = va_arg(ap, int); if (keysym == NEXT) continue; if (keysym == FINISH) break; xkb_keysym_get_name(keysym, ksbuf, sizeof(ksbuf)); fprintf(stderr, "\nERROR: Expected keysym: %s. Didn't get it.\n", ksbuf); goto fail; } xkb_state_unref(state); return 1; fail: fprintf(stderr, "Current state:\n"); print_detailed_state(state); xkb_state_unref(state); return 0; } int test_key_seq(struct xkb_keymap *keymap, ...) { va_list ap; int ret; va_start(ap, keymap); ret = test_key_seq_va(keymap, ap); va_end(ap); return ret; } char * test_makedir(const char *parent, const char *path) { char *dirname; int err; dirname = asprintf_safe("%s/%s", parent, path); assert(dirname); #ifdef _WIN32 err = _mkdir(dirname); #else err = mkdir(dirname, 0777); #endif assert(err == 0); return dirname; } char * test_maketempdir(const char *template) { #ifdef _WIN32 const char *basetmp = getenv("TMP"); if (basetmp == NULL) { basetmp = getenv("TEMP"); } if (basetmp == NULL) { basetmp = getenv("top_builddir"); } assert(basetmp != NULL); char *tmpdir = asprintf_safe("%s/%s", basetmp, template); assert(tmpdir != NULL); char *tmp = _mktemp(tmpdir); assert(tmp == tmpdir); int ret = _mkdir(tmp); assert(ret == 0); return tmpdir; #else char *tmpdir = asprintf_safe("/tmp/%s", template); assert(tmpdir != NULL); char *tmp = mkdtemp(tmpdir); assert(tmp == tmpdir); return tmpdir; #endif } char * test_get_path(const char *path_rel) { char *path; const char *srcdir; srcdir = getenv("top_srcdir"); if (!srcdir) srcdir = "."; if (is_absolute_path(path_rel)) return strdup(path_rel); path = asprintf_safe("%s/test/data%s%s", srcdir, path_rel[0] ? "/" : "", path_rel); if (!path) { fprintf(stderr, "Failed to allocate path for %s\n", path_rel); return NULL; } return path; } char * read_file(const char *path, FILE *file) { if (!file) return NULL; const int fd = fileno(file); if (fd < 0) return NULL; struct stat info; if (fstat(fd, &info) != 0) { fclose(file); return NULL; } char* ret = malloc(info.st_size + 1); if (!ret) { fclose(file); return NULL; } const size_t size = info.st_size; const size_t count = fread(ret, sizeof(*ret), size, file); if (count != size) { if (!feof(file)) printf("Error reading file %s: unexpected end of file\n", path); else if (ferror(file)) perror("Error reading file"); fclose(file); free(ret); return NULL; } ret[count] = '\0'; return ret; } char * test_read_file(const char *path_rel) { char *path = test_get_path(path_rel); if (!path) return NULL; FILE* file = fopen(path, "rb"); char *ret = NULL; if (!file) goto out; ret = read_file(path, file); out: if (file) fclose(file); free(path); return ret; } struct xkb_context * test_get_context(enum test_context_flags test_flags) { enum xkb_context_flags ctx_flags; struct xkb_context *ctx; char *path; ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES; if (test_flags & CONTEXT_ALLOW_ENVIRONMENT_NAMES) { unsetenv("XKB_DEFAULT_RULES"); unsetenv("XKB_DEFAULT_MODEL"); unsetenv("XKB_DEFAULT_LAYOUT"); unsetenv("XKB_DEFAULT_VARIANT"); unsetenv("XKB_DEFAULT_OPTIONS"); } else { ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES; } ctx = xkb_context_new(ctx_flags); if (!ctx) return NULL; path = test_get_path(""); if (!path) { xkb_context_unref(ctx); return NULL; } xkb_context_include_path_append(ctx, path); free(path); return ctx; } struct xkb_keymap * test_compile_file(struct xkb_context *context, enum xkb_keymap_format format, const char *path_rel) { struct xkb_keymap *keymap; FILE *file; char *path; path = test_get_path(path_rel); if (!path) return NULL; file = fopen(path, "rb"); if (!file) { fprintf(stderr, "Failed to open path: %s\n", path); free(path); return NULL; } assert(file != NULL); keymap = xkb_keymap_new_from_file(context, file, format, XKB_KEYMAP_COMPILE_NO_FLAGS); fclose(file); if (!keymap) { fprintf(stderr, "Failed to compile path: %s\n", path); free(path); return NULL; } fprintf(stderr, "Successfully compiled path: %s\n", path); free(path); return keymap; } struct xkb_keymap * test_compile_string(struct xkb_context *context, enum xkb_keymap_format format, const char *string) { struct xkb_keymap *keymap; keymap = xkb_keymap_new_from_string(context, string, format, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { fprintf(stderr, "Failed to compile string\n"); return NULL; } return keymap; } struct xkb_keymap * test_compile_buffer(struct xkb_context *context, enum xkb_keymap_format format, const char *buf, size_t len) { struct xkb_keymap *keymap; keymap = xkb_keymap_new_from_buffer(context, buf, len, format, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { fprintf(stderr, "Failed to compile keymap from memory buffer\n"); return NULL; } return keymap; } struct xkb_keymap * test_compile_rules(struct xkb_context *context, enum xkb_keymap_format format, const char *rules, const char *model, const char *layout, const char *variant, const char *options) { struct xkb_keymap *keymap; struct xkb_rule_names rmlvo = { .rules = isempty(rules) ? NULL : rules, .model = isempty(model) ? NULL : model, .layout = isempty(layout) ? NULL : layout, .variant = isempty(variant) ? NULL : variant, .options = isempty(options) ? NULL : options }; if (!rules && !model && !layout && !variant && !options) keymap = xkb_keymap_new_from_names2(context, NULL, format, XKB_KEYMAP_COMPILE_NO_FLAGS); else keymap = xkb_keymap_new_from_names2(context, &rmlvo, format, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { fprintf(stderr, "Failed to compile RMLVO: '%s', '%s', '%s', '%s', '%s'\n", rules, model, layout, variant, options); return NULL; } return keymap; } static struct xkb_rmlvo_builder * xkb_rules_names_to_rmlvo_builder(struct xkb_context *context, const struct xkb_rule_names *names) { struct xkb_rmlvo_builder *rmlvo = xkb_rmlvo_builder_new(context, names->rules, names->model, XKB_RMLVO_BUILDER_NO_FLAGS); if (!rmlvo) { fprintf(stderr, "ERROR: xkb_rmlvo_builder_new() failed\n"); return NULL; } char buf[1024] = { 0 }; /* First parse options, and gather the layout-specific ones and * append the others to the builder */ typedef darray(char *) darray_string; darray(darray_string) loptions = darray_new(); if (!isempty(names->options)) { const char *o = names->options; while (*o != '\0') { /* Get option name */ const char *option = o; while (*o != '\0' && *o != ',' && *o != OPTIONS_GROUP_SPECIFIER_PREFIX) { o++; }; const size_t len = o - option; if (len >= sizeof(buf)) goto error; memcpy(buf, option, len); buf[len] = '\0'; /* Check if layout-specific option */ xkb_layout_index_t layout = XKB_LAYOUT_INVALID; if (*o == OPTIONS_GROUP_SPECIFIER_PREFIX) { o++; int count = parse_dec_to_uint32_t(o, SIZE_MAX, &layout); if (count > 0 && layout > 0 && layout <= XKB_MAX_GROUPS) { o += count; layout--; } else { layout = XKB_LAYOUT_INVALID; } const char* const layout_index_end = o; while (*o != '\0' && *o != ',') { o++; } if (count <= 0 || layout_index_end != o) layout = XKB_LAYOUT_INVALID; } if (layout != XKB_LAYOUT_INVALID) { /* Save as layout-specific option, to be added with layout */ char *opt = strdup(buf); if (!opt) goto error; darray_resize0(loptions, layout + 1); darray_append(darray_item(loptions, layout), opt); } else { /* Append layout-agnostic option */ if (!xkb_rmlvo_builder_append_option(rmlvo, buf)) goto error; } if (*o == ',') o++; } } if (!isempty(names->layout)) { /* Process layout & variant together. * Ignore variants without corresponding layout. */ const char *l = names->layout; const char *v = names->variant; if (!names->variant) v = ""; xkb_layout_index_t layout_count = 0; while (*l != '\0') { const char *layout = l; const char *variant = v; char *start = buf; size_t buf_size = sizeof(buf); while (*l != '\0' && *l != ',') { l++; }; while (*v != '\0' && *v != ',') { v++; }; size_t len = l - layout; if (len >= buf_size) goto error; memcpy(start, layout, len); start[len] = '\0'; start += len; buf_size -= len + 1; len = v - variant; if (len >= buf_size) goto error; ++start; memcpy(start, variant, len); start[len] = '\0'; /* Get layout-specific options */ char **opts = NULL; size_t opts_count = 0; if (layout_count < darray_size(loptions)) { opts = darray_items(darray_item(loptions, layout_count)); opts_count = darray_size(darray_item(loptions, layout_count)); } if (!xkb_rmlvo_builder_append_layout(rmlvo, buf, start, (const char* *) opts, opts_count)) goto error; if (*l == ',') l++; if (*v == ',') v++; layout_count += 1; } } exit: { darray_string *opts; darray_foreach(opts, loptions) { char **opt; darray_foreach(opt, *opts) free(*opt); darray_free(*opts); } darray_free(loptions); } return rmlvo; error: fprintf(stderr, "ERROR: %s\n", __func__); xkb_rmlvo_builder_unref(rmlvo); rmlvo = NULL; goto exit; } struct xkb_keymap * test_compile_rmlvo(struct xkb_context *context, enum xkb_keymap_format format, const char *rules, const char *model, const char *layout, const char *variant, const char *options) { struct xkb_keymap *keymap = NULL; const struct xkb_rule_names names = { .rules = rules, .model = model, .layout = layout, .variant = variant, .options = options }; struct xkb_rmlvo_builder *rmlvo = xkb_rules_names_to_rmlvo_builder(context, &names); if (!rmlvo) { fprintf(stderr, "Failed to create RMLVO builder: " "'%s', '%s', '%s', '%s', '%s'\n", rules, model, layout, variant, options); return NULL; } keymap = xkb_keymap_new_from_rmlvo(rmlvo, format, XKB_KEYMAP_COMPILE_NO_FLAGS); xkb_rmlvo_builder_unref(rmlvo); if (!keymap) { fprintf(stderr, "Failed to compile RMLVO from builder: " "'%s', '%s', '%s', '%s', '%s'\n", rules, model, layout, variant, options); } return keymap; } bool test_compile_output(struct xkb_context *ctx, enum xkb_keymap_format input_format, enum xkb_keymap_format output_format, test_compile_buffer_t compile_buffer, void *compile_buffer_private, const char *test_title, const char *keymap_str, size_t keymap_len, const char *rel_path, bool update_output_files) { return test_compile_output2(ctx, input_format, output_format, TEST_KEYMAP_SERIALIZE_FLAGS, compile_buffer, compile_buffer_private, test_title, keymap_str, keymap_len, rel_path, update_output_files); } bool test_compile_output2(struct xkb_context *ctx, enum xkb_keymap_format input_format, enum xkb_keymap_format output_format, enum xkb_keymap_serialize_flags serialize_flags, test_compile_buffer_t compile_buffer, void *compile_buffer_private, const char *test_title, const char *keymap_str, size_t keymap_len, const char *rel_path, bool update_output_files) { int success = true; fprintf(stderr, "*** %s ***\n", test_title); struct xkb_keymap *keymap = compile_buffer( ctx, input_format, keymap_str, keymap_len, compile_buffer_private ); if (!rel_path) { /* No path given: expect compilation failure */ if (keymap) { char *got = xkb_keymap_get_as_string2(keymap, output_format, serialize_flags); xkb_keymap_unref(keymap); assert(got); fprintf(stderr, "Unexpected keymap compilation success:\n%s\n", got); free(got); } return !keymap; } if (!keymap) { fprintf(stderr, "Unexpected keymap compilation failure\n"); return false; } char *got = xkb_keymap_get_as_string2(keymap, output_format, serialize_flags); if (!got) { fprintf(stderr, "Unexpected keymap serialization failure\n"); return false; } xkb_keymap_unref(keymap); char* const path = test_get_path(rel_path); assert(path); if (update_output_files) { fprintf(stderr, "Writing golden test output to: %s\n", path); FILE *file = fopen(path, "wb"); assert(file); fwrite(got, 1, strlen(got), file); fclose(file); } else { fprintf(stderr, "Reading golden test output: %s\n", path); char* const expected = test_read_file(rel_path); assert(expected); static const char *label[2] = {"Golden test", "Roundtrip"}; bool test_round_trip = (output_format == input_format || output_format == XKB_KEYMAP_USE_ORIGINAL_FORMAT); for (unsigned int k = 0; k < ARRAY_SIZE(label) && success; k++) { if (streq(expected, got)) { fprintf(stderr, "%s succeeded.\n", label[k]); if (!test_round_trip) break; /* Test round trip */ keymap = compile_buffer(ctx, input_format, expected, strlen(expected), compile_buffer_private); if (!keymap) { fprintf(stderr, "Unexpected keymap roundtrip compilation failure\n"); success = false; break; } free(got); got = xkb_keymap_get_as_string2(keymap, output_format, serialize_flags); if (!got) { fprintf(stderr, "Unexpected keymap roundtrip serialization failure\n"); success = false; } xkb_keymap_unref(keymap); test_round_trip = false; } else { fprintf(stderr, "%s failed: dumped map differs from expected.\n", label[k]); fprintf(stderr, "Path to expected file: %s\n", path); fprintf(stderr, "Length: expected %zu, got: %zu\n", strlen(expected), strlen(got)); fprintf(stderr, "Dumped map:\n"); fprintf(stderr, "%s\n", got); success = false; } } free(expected); } free(got); free(path); return success; } bool test_third_pary_compile_output(test_third_party_compile_buffer_t compile_buffer, void *compile_buffer_private, const char *test_title, const char *keymap_in, size_t keymap_in_size, const char *rel_path, bool update_output_files) { int success = true; fprintf(stderr, "*** %s ***\n", test_title); char* got = NULL; size_t got_size = 0; int ret = compile_buffer(keymap_in, keymap_in_size, compile_buffer_private, &got, &got_size); if (!rel_path) { /* No path given: expect compilation failure */ if (ret == EXIT_SUCCESS) { fprintf(stderr, "Unexpected keymap compilation success:\nstdout:\n%s\n", got); } free(got); return (ret != EXIT_SUCCESS); } if (ret != EXIT_SUCCESS || isempty(got)) { fprintf(stderr, "Unexpected keymap compilation failure.\nstdout:\n%s\n", got); free(got); return false; } char *path = test_get_path(rel_path); assert(path); if (update_output_files) { fprintf(stderr, "Writing golden test output to: %s\n", path); FILE *file = fopen(path, "wb"); assert(file); fwrite(got, 1, got_size, file); fclose(file); } else { fprintf(stderr, "Reading golden test output: %s\n", path); char *expected = test_read_file(rel_path); assert(expected); const char *label[2] = {"Golden test", "Roundtrip"}; for (unsigned int k = 0; k < ARRAY_SIZE(label) && success; k++) { if (streq(expected, got)) { fprintf(stderr, "%s succeeded.\n", label[k]); if (k > 0) continue; /* Test round trip */ // TODO break; }else { fprintf(stderr, "%s failed: dumped map differs from expected.\n", label[k]); fprintf(stderr, "Path to expected file: %s\n", path); fprintf(stderr, "Length: expected %zu, got: %zu\n", strlen(expected), strlen(got)); fprintf(stderr, "Dumped map:\n"); fprintf(stderr, "%s\n", got); success = false; } } free(expected); } free(got); free(path); return success; } xkbcommon-libxkbcommon-54ee7ac/test/compose-iter.c000066400000000000000000000032061510033435100224150ustar00rootroot00000000000000/* * Copyright © 2022 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include "src/darray.h" #include #include #include #include "xkbcommon/xkbcommon-compose.h" #include "src/compose/escape.h" #include "src/compose/constants.h" #include "src/keysym.h" #include "src/utils.h" #include "test/compose-iter.h" /* Reference implentation of Compose table traversal */ static void for_each_helper(struct xkb_compose_table *table, xkb_compose_table_iter_t iter, void *data, xkb_keysym_t *syms, size_t nsyms, uint32_t p) { if (!p) { return; } const struct compose_node *node = &darray_item(table->nodes, p); for_each_helper(table, iter, data, syms, nsyms, node->lokid); syms[nsyms++] = node->keysym; if (node->is_leaf) { struct xkb_compose_table_entry entry = { .sequence = syms, .sequence_length = nsyms, .keysym = node->leaf.keysym, .utf8 = &darray_item(table->utf8, node->leaf.utf8), }; iter(&entry, data); } else { for_each_helper(table, iter, data, syms, nsyms, node->internal.eqkid); } nsyms--; for_each_helper(table, iter, data, syms, nsyms, node->hikid); } void xkb_compose_table_for_each(struct xkb_compose_table *table, xkb_compose_table_iter_t iter, void *data) { if (darray_size(table->nodes) <= 1) { return; } xkb_keysym_t syms[COMPOSE_MAX_LHS_LEN]; for_each_helper(table, iter, data, syms, 0, 1); } xkbcommon-libxkbcommon-54ee7ac/test/compose-iter.h000066400000000000000000000014031510033435100224170ustar00rootroot00000000000000/* * Copyright © 2022 Ran Benita * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include "src/compose/table.h" /** * The iterator function type used by xkb_compose_table_for_each(). */ typedef void (*xkb_compose_table_iter_t)(struct xkb_compose_table_entry *entry, void *data); /** * Run a specified function for every valid entry in the table. * * The entries are returned in lexicographic order of the left-hand * side of entries. This does not correspond to the order in which * the entries appear in the Compose file. */ void xkb_compose_table_for_each(struct xkb_compose_table *table, xkb_compose_table_iter_t iter, void *data); xkbcommon-libxkbcommon-54ee7ac/test/compose.c000066400000000000000000001327231510033435100214630ustar00rootroot00000000000000/* * Copyright © 2014 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include "xkbcommon/xkbcommon-compose.h" #include "xkbcommon/xkbcommon-keysyms.h" #include "test.h" #include "src/utf8.h" #include "src/keysym.h" #include "src/compose/constants.h" #include "src/compose/parser.h" #include "src/compose/escape.h" #include "src/compose/dump.h" #include "test/compose-iter.h" #include "test/utils-text.h" static const char * compose_status_string(enum xkb_compose_status status) { switch (status) { case XKB_COMPOSE_NOTHING: return "nothing"; case XKB_COMPOSE_COMPOSING: return "composing"; case XKB_COMPOSE_COMPOSED: return "composed"; case XKB_COMPOSE_CANCELLED: return "cancelled"; } return ""; } static const char * feed_result_string(enum xkb_compose_feed_result result) { switch (result) { case XKB_COMPOSE_FEED_IGNORED: return "ignored"; case XKB_COMPOSE_FEED_ACCEPTED: return "accepted"; } return ""; } /* * Feed a sequence of keysyms to a fresh compose state and test the outcome. * * The varargs consists of lines in the following format: * * Terminated by a line consisting only of XKB_KEY_NoSymbol. */ static bool test_compose_seq_va(struct xkb_compose_table *table, va_list ap) { int ret; struct xkb_compose_state *state; char buffer[MAX(XKB_COMPOSE_MAX_STRING_SIZE, XKB_KEYSYM_NAME_MAX_SIZE)]; state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS); assert(state); for (int i = 1; ; i++) { xkb_keysym_t input_keysym; enum xkb_compose_feed_result result, expected_result; enum xkb_compose_status status, expected_status; const char *expected_string; xkb_keysym_t keysym, expected_keysym; input_keysym = va_arg(ap, xkb_keysym_t); if (input_keysym == XKB_KEY_NoSymbol) break; expected_result = va_arg(ap, enum xkb_compose_feed_result); expected_status = va_arg(ap, enum xkb_compose_status); expected_string = va_arg(ap, const char *); expected_keysym = va_arg(ap, xkb_keysym_t); result = xkb_compose_state_feed(state, input_keysym); if (result != expected_result) { fprintf(stderr, "after feeding %d keysyms:\n", i); fprintf(stderr, "expected feed result: %s\n", feed_result_string(expected_result)); fprintf(stderr, "got feed result: %s\n", feed_result_string(result)); goto fail; } status = xkb_compose_state_get_status(state); if (status != expected_status) { fprintf(stderr, "after feeding %d keysyms:\n", i); fprintf(stderr, "expected status: %s\n", compose_status_string(expected_status)); fprintf(stderr, "got status: %s\n", compose_status_string(status)); goto fail; } ret = xkb_compose_state_get_utf8(state, buffer, sizeof(buffer)); if (ret < 0 || (size_t) ret >= sizeof(buffer)) { fprintf(stderr, "after feeding %d keysyms:\n", i); fprintf(stderr, "expected string: %s\n", expected_string); fprintf(stderr, "got error: %d\n", ret); goto fail; } if (!streq(buffer, expected_string)) { fprintf(stderr, "after feeding %d keysyms:\n", i); fprintf(stderr, "expected string: %s\n", strempty(expected_string)); fprintf(stderr, "got string: %s\n", buffer); goto fail; } keysym = xkb_compose_state_get_one_sym(state); if (keysym != expected_keysym) { fprintf(stderr, "after feeding %d keysyms:\n", i); xkb_keysym_get_name(expected_keysym, buffer, sizeof(buffer)); fprintf(stderr, "expected keysym: %s\n", buffer); xkb_keysym_get_name(keysym, buffer, sizeof(buffer)); fprintf(stderr, "got keysym (%#06"PRIx32"): %s\n", keysym, buffer); goto fail; } } xkb_compose_state_unref(state); return true; fail: xkb_compose_state_unref(state); return false; } static bool test_compose_seq(struct xkb_compose_table *table, ...) { va_list ap; bool ok; va_start(ap, table); ok = test_compose_seq_va(table, ap); va_end(ap); return ok; } static bool test_compose_seq_buffer(struct xkb_context *ctx, const char *buffer, ...) { va_list ap; bool ok; struct xkb_compose_table *table; table = xkb_compose_table_new_from_buffer(ctx, buffer, strlen(buffer), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); va_start(ap, buffer); ok = test_compose_seq_va(table, ap); va_end(ap); xkb_compose_table_unref(table); return ok; } static void test_compose_utf8_bom(struct xkb_context *ctx) { const char buffer[] = "\xef\xbb\xbf : X"; assert(test_compose_seq_buffer(ctx, buffer, XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "X", XKB_KEY_X, XKB_KEY_NoSymbol)); } static void test_invalid_encodings(struct xkb_context *ctx) { struct xkb_compose_table *table; /* ISO 8859-1 (latin1) */ const char iso_8859_1[] = " : \"\xe1\" acute"; assert(!test_compose_seq_buffer(ctx, iso_8859_1, XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "\xc3\xa1", XKB_KEY_acute, XKB_KEY_NoSymbol)); /* UTF-16LE */ const char utf_16_le[] = "<\0A\0>\0 \0:\0 \0X\0\n\0" "<\0B\0>\0 \0:\0 \0Y\0"; table = xkb_compose_table_new_from_buffer(ctx, utf_16_le, sizeof(utf_16_le), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(!table); /* UTF-16BE */ const char utf_16_be[] = "\0<\0A\0>\0 \0:\0 \0X\0\n" "\0<\0B\0>\0 \0:\0 \0Y"; table = xkb_compose_table_new_from_buffer(ctx, utf_16_be, sizeof(utf_16_be), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(!table); /* UTF-16BE with BOM */ const char utf_16_be_bom[] = "\xfe\xff" "\0<\0A\0>\0 \0:\0 \0X\0\n" "\0<\0B\0>\0 \0:\0 \0Y"; table = xkb_compose_table_new_from_buffer(ctx, utf_16_be_bom, sizeof(utf_16_be_bom), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(!table); /* UTF-32LE */ const char utf_32_le[] = "<\0\0\0A\0\0\0>\0\0\0 \0\0\0:\0\0\0 \0\0\0X\0\0\0\n\0\0\0" "<\0\0\0B\0\0\0>\0\0\0 \0\0\0:\0\0\0 \0\0\0Y\0\0\0"; table = xkb_compose_table_new_from_buffer(ctx, utf_32_le, sizeof(utf_32_le), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(!table); /* UTF-32LE with BOM */ const char utf_32_le_bom[] = "\xff\xfe\0\0" "<\0\0\0A\0\0\0>\0\0\0 \0\0\0:\0\0\0 \0\0\0X\0\0\0\n\0\0\0" "<\0\0\0B\0\0\0>\0\0\0 \0\0\0:\0\0\0 \0\0\0Y\0\0\0"; table = xkb_compose_table_new_from_buffer(ctx, utf_32_le_bom, sizeof(utf_32_le_bom), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(!table); /* UTF-32BE */ const char utf_32_be[] = "\0\0\0<\0\0\0A\0\0\0>\0\0\0 \0\0\0:\0\0\0 \0\0\0X\0\0\0\n\0\0\0" "<\0\0\0B\0\0\0>\0\0\0 \0\0\0:\0\0\0 \0\0\0Y"; table = xkb_compose_table_new_from_buffer(ctx, utf_32_be, sizeof(utf_32_be), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(!table); } static void test_seqs(struct xkb_context *ctx) { struct xkb_compose_table *table; char *path; FILE *file; path = test_get_path("locale/en_US.UTF-8/Compose"); file = fopen(path, "rb"); assert(file); free(path); table = xkb_compose_table_new_from_file(ctx, file, "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); fclose(file); assert(test_compose_seq(table, XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, XKB_KEY_NoSymbol)); assert(test_compose_seq(table, XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, XKB_KEY_NoSymbol)); assert(test_compose_seq(table, XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, XKB_KEY_NoSymbol)); assert(test_compose_seq(table, XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "'", XKB_KEY_apostrophe, XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSED, "'", XKB_KEY_apostrophe, XKB_KEY_NoSymbol)); assert(test_compose_seq(table, XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "´", XKB_KEY_acute, XKB_KEY_NoSymbol)); assert(test_compose_seq(table, XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_Shift_L, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_Control_L, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_T, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "@", XKB_KEY_at, XKB_KEY_NoSymbol)); assert(test_compose_seq(table, XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_a, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_b, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_NoSymbol)); assert(test_compose_seq(table, XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_apostrophe, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, XKB_KEY_7, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_Caps_Lock, XKB_COMPOSE_FEED_IGNORED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_NoSymbol)); xkb_compose_table_unref(table); /* Make sure one-keysym sequences work. */ assert(test_compose_seq_buffer(ctx, " : \"foo\" X \n" " : \"baz\" Y \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X, XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "baz", XKB_KEY_Y, XKB_KEY_NoSymbol)); /* No sequences at all. */ assert(test_compose_seq_buffer(ctx, "", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_Multi_key, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_NoSymbol)); /* Only keysym - string derived from keysym. */ assert(test_compose_seq_buffer(ctx, " : X \n" " : dollar \n" " : dead_acute \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "X", XKB_KEY_X, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "$", XKB_KEY_dollar, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "", XKB_KEY_dead_acute, XKB_KEY_NoSymbol)); /* Make sure a cancelling keysym doesn't start a new sequence. */ assert(test_compose_seq_buffer(ctx, " : X \n" " : Y \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, XKB_KEY_D, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_CANCELLED, "", XKB_KEY_NoSymbol, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_D, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "Y", XKB_KEY_Y, XKB_KEY_NoSymbol)); } static void test_conflicting(struct xkb_context *ctx) { // new is prefix of old assert(test_compose_seq_buffer(ctx, " : \"foo\" A \n" " : \"bar\" B \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_NoSymbol)); // old is a prefix of new assert(test_compose_seq_buffer(ctx, " : \"bar\" B \n" " : \"foo\" A \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_A, XKB_KEY_NoSymbol)); // new duplicate of old assert(test_compose_seq_buffer(ctx, " : \"bar\" B \n" " : \"bar\" B \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B, XKB_KEY_C, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_NOTHING, "", XKB_KEY_NoSymbol, XKB_KEY_NoSymbol)); // new same length as old #1 assert(test_compose_seq_buffer(ctx, " : \"foo\" A \n" " : \"bar\" B \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_B, XKB_KEY_NoSymbol)); // new same length as old #2 assert(test_compose_seq_buffer(ctx, " : \"foo\" A \n" " : \"foo\" B \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_B, XKB_KEY_NoSymbol)); // new same length as old #3: overwritable string: do not allocate assert(test_compose_seq_buffer(ctx, " : \"foo\" A \n" " : \"qu\" A \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "qu", XKB_KEY_A, XKB_KEY_NoSymbol)); // new same length as old #4: no-overwritable string: allocate assert(test_compose_seq_buffer(ctx, " : \"foo\" A \n" " : \"quux\" A \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "quux", XKB_KEY_A, XKB_KEY_NoSymbol)); // new same length as old #5: ensure string is reset assert(test_compose_seq_buffer(ctx, " : \"foo\" A \n" " : B \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "B", XKB_KEY_B, XKB_KEY_NoSymbol)); // new same length as old #6: ensure keysym is reset assert(test_compose_seq_buffer(ctx, " : \"foo\" A \n" " : \"bar\" \n", XKB_KEY_A, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_B, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_NoSymbol, XKB_KEY_NoSymbol)); } static void test_state(struct xkb_context *ctx) { struct xkb_compose_table *table; struct xkb_compose_state *state; char *path; FILE *file; path = test_get_path("locale/en_US.UTF-8/Compose"); file = fopen(path, "rb"); assert(file); free(path); table = xkb_compose_table_new_from_file(ctx, file, "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); fclose(file); state = xkb_compose_state_new(table, XKB_COMPOSE_STATE_NO_FLAGS); assert(state); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); xkb_compose_state_reset(state); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); xkb_compose_state_feed(state, XKB_KEY_NoSymbol); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); xkb_compose_state_feed(state, XKB_KEY_Multi_key); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); xkb_compose_state_reset(state); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); xkb_compose_state_feed(state, XKB_KEY_Multi_key); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); xkb_compose_state_feed(state, XKB_KEY_Multi_key); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_CANCELLED); xkb_compose_state_feed(state, XKB_KEY_Multi_key); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); xkb_compose_state_feed(state, XKB_KEY_Multi_key); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_CANCELLED); xkb_compose_state_reset(state); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); xkb_compose_state_feed(state, XKB_KEY_dead_acute); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); xkb_compose_state_feed(state, XKB_KEY_A); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSED); xkb_compose_state_reset(state); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); xkb_compose_state_feed(state, XKB_KEY_dead_acute); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSING); xkb_compose_state_feed(state, XKB_KEY_A); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_COMPOSED); xkb_compose_state_reset(state); xkb_compose_state_feed(state, XKB_KEY_NoSymbol); assert(xkb_compose_state_get_status(state) == XKB_COMPOSE_NOTHING); xkb_compose_state_unref(state); xkb_compose_table_unref(table); } static void test_XCOMPOSEFILE(struct xkb_context *ctx) { struct xkb_compose_table *table; char *path; /* Error: directory */ path = test_get_path("locale/en_US.UTF-8"); setenv("XCOMPOSEFILE", path, 1); free(path); table = xkb_compose_table_new_from_locale(ctx, "blabla", XKB_COMPOSE_COMPILE_NO_FLAGS); assert_printf(errno != ENODEV && errno != EISDIR, "Should not be an error from `map_file`\n"); assert(!table); /* OK: regular file */ path = test_get_path("locale/en_US.UTF-8/Compose"); setenv("XCOMPOSEFILE", path, 1); free(path); table = xkb_compose_table_new_from_locale(ctx, "blabla", XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); unsetenv("XCOMPOSEFILE"); assert(test_compose_seq(table, XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, XKB_KEY_NoSymbol)); xkb_compose_table_unref(table); } static void test_from_locale(struct xkb_context *ctx) { struct xkb_compose_table *table; char *path; path = test_get_path("locale"); setenv("XLOCALEDIR", path, 1); free(path); /* Direct directory name match. */ table = xkb_compose_table_new_from_locale(ctx, "en_US.UTF-8", XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); xkb_compose_table_unref(table); /* Direct locale name match. */ table = xkb_compose_table_new_from_locale(ctx, "C.UTF-8", XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); xkb_compose_table_unref(table); /* Alias. */ table = xkb_compose_table_new_from_locale(ctx, "univ.utf8", XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); xkb_compose_table_unref(table); /* Special case - C. */ table = xkb_compose_table_new_from_locale(ctx, "C", XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); xkb_compose_table_unref(table); #ifdef HAVE_NEWLOCALE /* Test custom locale. Require installing it system-wide */ /* NOTE: Keep the locale name in sync with the localedef call in our CI */ static const char * const custom_locale = "xx_YY.UTF-8"; locale_t loc = newlocale(LC_ALL, custom_locale, (locale_t) 0); table = xkb_compose_table_new_from_locale(ctx, custom_locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (loc == (locale_t) 0) { /* Locale is not installed: no fallback */ assert(!table); } else { /* Locale is installed */ freelocale(loc); assert(table); xkb_compose_table_unref(table); } #endif /* Bogus - not found. */ table = xkb_compose_table_new_from_locale(ctx, "blabla", XKB_COMPOSE_COMPILE_NO_FLAGS); assert(!table); unsetenv("XLOCALEDIR"); } static void test_modifier_syntax(struct xkb_context *ctx) { const char *table_string; /* We don't do anything with the modifiers, but make sure we can parse * them. */ assert(test_compose_seq_buffer(ctx, "None : X \n" "Shift : Y \n" "Ctrl : Y \n" "Alt : Y \n" "Caps : Y \n" "Lock : Y \n" "Shift Ctrl : Y \n" "~Shift : Y \n" "~Shift Ctrl : Y \n" "Shift ~Ctrl : Y \n" "Shift ~Ctrl ~Alt : Y \n" "! Shift : Y \n" "! Ctrl : Y \n" "! Alt : Y \n" "! Caps : Y \n" "! Lock : Y \n" "! Shift Ctrl : Y \n" "! ~Shift : Y \n" "! ~Shift Ctrl : Y \n" "! Shift ~Ctrl : Y \n" "! Shift ~Ctrl ~Alt : Y \n" " ! Shift : Y \n" "None ! Shift : Y \n" "None

! Shift : Y \n", XKB_KEY_NoSymbol)); fprintf(stderr, "\n"); table_string = "! None : X \n" "! Foo : X \n" "None ! Shift : X \n" "! ! : X \n" "! ~ : X \n" "! ! : X \n" "! Ctrl ! Ctrl : X \n" " ! : X \n" " None : X \n" "None None : X \n" " : !Shift X \n"; assert(!xkb_compose_table_new_from_buffer(ctx, table_string, strlen(table_string), "C", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS)); fprintf(stderr, "\n"); } static void test_include(struct xkb_context *ctx) { char *path, *table_string; path = test_get_path("locale/en_US.UTF-8/Compose"); assert(path); /* We don't have a mechanism to change the include paths like we * have for keymaps. So we must include the full path. */ table_string = asprintf_safe(" : \"foo\" X\n" "include \"%s\"\n" " : \"bar\" Y\n", path); assert(table_string); assert(test_compose_seq_buffer(ctx, table_string, /* No conflict. */ XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_dead_acute, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "´", XKB_KEY_acute, /* Comes before - doesn't override. */ XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_space, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "~", XKB_KEY_asciitilde, /* Comes after - does override. */ XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_dead_tilde, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_Y, XKB_KEY_NoSymbol)); free(path); free(table_string); } static void test_override(struct xkb_context *ctx) { const char *table_string = " : \"foo\" X\n" " : \"bar\" Y\n" " : \"baz\" Z\n"; assert(test_compose_seq_buffer(ctx, table_string, /* Comes after - does override. */ XKB_KEY_dead_circumflex, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_dead_circumflex, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_e, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "baz", XKB_KEY_Z, /* Override does not affect sibling nodes */ XKB_KEY_dead_circumflex, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_e, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "bar", XKB_KEY_Y, XKB_KEY_NoSymbol)); } static bool test_eq_entry_va(struct xkb_compose_table_entry *entry, xkb_keysym_t keysym_ref, const char *utf8_ref, va_list ap) { assert (entry != NULL); assert (xkb_compose_table_entry_keysym(entry) == keysym_ref); const char *utf8 = xkb_compose_table_entry_utf8(entry); assert (utf8 && utf8_ref && strcmp(utf8, utf8_ref) == 0); size_t nsyms; const xkb_keysym_t *sequence = xkb_compose_table_entry_sequence(entry, &nsyms); xkb_keysym_t keysym; for (unsigned int k = 0; ; k++) { keysym = va_arg(ap, xkb_keysym_t); if (keysym == XKB_KEY_NoSymbol) { return (k == nsyms - 1); } assert (k < nsyms); assert (keysym == sequence[k]); } } static bool test_eq_entry(struct xkb_compose_table_entry *entry, xkb_keysym_t keysym, const char *utf8, ...) { va_list ap; bool ok; va_start(ap, utf8); ok = test_eq_entry_va(entry, keysym, utf8, ap); va_end(ap); return ok; } static bool test_eq_entries(struct xkb_compose_table_entry *entry1, struct xkb_compose_table_entry *entry2) { if (!entry1 || !entry2) goto error; bool ok = true; if (entry1->keysym != entry2->keysym || !streq_null(entry1->utf8, entry2->utf8) || entry1->sequence_length != entry2->sequence_length) ok = false; for (size_t k = 0; k < entry1->sequence_length; k++) { if (entry1->sequence[k] != entry2->sequence[k]) ok = false; } if (ok) return true; error: #define print_entry(msg, entry) \ fprintf(stderr, msg); \ if (entry) \ print_compose_table_entry(stderr, entry); \ else \ fprintf(stderr, "\n"); print_entry("Expected: ", entry1); print_entry("Got: ", entry2); #undef print_entry return false; } static void compose_traverse_fn(struct xkb_compose_table_entry *entry_ref, void *data) { struct xkb_compose_table_iterator *iter = (struct xkb_compose_table_iterator *)data; struct xkb_compose_table_entry *entry = xkb_compose_table_iterator_next(iter); assert(test_eq_entries(entry_ref, entry)); } static void test_traverse(struct xkb_context *ctx, size_t quickcheck_loops) { struct xkb_compose_table *table; struct xkb_compose_table_iterator *iter; /* Empty table */ table = xkb_compose_table_new_from_buffer(ctx, "", 0, "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); iter = xkb_compose_table_iterator_new(table); assert (xkb_compose_table_iterator_next(iter) == NULL); xkb_compose_table_iterator_free(iter); xkb_compose_table_unref(table); /* Non-empty table */ const char *buffer = " : \"foo\" X\n" " : \"foobar\"\n" " : oe\n" " : \"bar\" Y\n" " : \"æ\" ae\n" " : \"baz\" Z\n" " : \"é\" eacute\n" " : \"aac\"\n" " : \"aab\"\n" " : \"aaa\"\n"; table = xkb_compose_table_new_from_buffer(ctx, buffer, strlen(buffer), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); iter = xkb_compose_table_iterator_new(table); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_eacute, "é", XKB_KEY_dead_acute, XKB_KEY_e, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_Z, "baz", XKB_KEY_dead_circumflex, XKB_KEY_a, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_Y, "bar", XKB_KEY_dead_circumflex, XKB_KEY_e, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_X, "foo", XKB_KEY_dead_circumflex, XKB_KEY_dead_circumflex, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_NoSymbol, "aaa", XKB_KEY_Multi_key, XKB_KEY_a, XKB_KEY_a, XKB_KEY_a, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_NoSymbol, "aab", XKB_KEY_Multi_key, XKB_KEY_a, XKB_KEY_a, XKB_KEY_b, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_NoSymbol, "aac", XKB_KEY_Multi_key, XKB_KEY_a, XKB_KEY_a, XKB_KEY_c, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_ae, "æ", XKB_KEY_Multi_key, XKB_KEY_a, XKB_KEY_e, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_oe, "", XKB_KEY_Multi_key, XKB_KEY_o, XKB_KEY_e, XKB_KEY_NoSymbol); test_eq_entry(xkb_compose_table_iterator_next(iter), XKB_KEY_NoSymbol, "foobar", XKB_KEY_Ahook, XKB_KEY_x, XKB_KEY_NoSymbol); assert (xkb_compose_table_iterator_next(iter) == NULL); xkb_compose_table_iterator_free(iter); xkb_compose_table_unref(table); /* QuickCheck: shuffle compose file lines and compare against * reference implementation */ char *input = test_read_file("locale/en_US.UTF-8/Compose"); assert(input); struct text_line lines[6000]; size_t input_length = strlen(input); size_t lines_count = split_lines(input, input_length, lines, ARRAY_SIZE(lines)); /* Note: we may add additional new line char */ char *shuffled = calloc(input_length + 1, sizeof(char)); assert(shuffled); for (size_t k = 0; k < quickcheck_loops; k++) { size_t shuffled_length = shuffle_lines(lines, lines_count, shuffled); table = xkb_compose_table_new_from_buffer(ctx, shuffled, shuffled_length, "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS); assert(table); iter = xkb_compose_table_iterator_new(table); assert(iter); xkb_compose_table_for_each(table, compose_traverse_fn, iter); assert(xkb_compose_table_iterator_next(iter) == NULL); xkb_compose_table_iterator_free(iter); xkb_compose_table_unref(table); } free(shuffled); free(input); } static void test_string_length(struct xkb_context *ctx) { // Invalid: empty string const char table_string_1[] = " : \"\" X\n"; assert(test_compose_seq_buffer(ctx, table_string_1, XKB_KEY_a, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_b, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "", XKB_KEY_X, XKB_KEY_NoSymbol)); char long_string[XKB_COMPOSE_MAX_STRING_SIZE] = { 0 }; memset(long_string, 0x61, XKB_COMPOSE_MAX_STRING_SIZE - 1); char table_string_2[XKB_COMPOSE_MAX_STRING_SIZE + sizeof(table_string_1) - 1]; assert(snprintf_safe(table_string_2, sizeof(table_string_2), " : \"%s\" X\n", long_string)); assert(test_compose_seq_buffer(ctx, table_string_2, XKB_KEY_a, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_b, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, long_string, XKB_KEY_X, XKB_KEY_NoSymbol)); } static void test_decode_escape_sequences(struct xkb_context *ctx) { /* The following escape sequences should be ignored: * • \401 overflows * • \0 and \x0 produce NULL */ const char table_string_1[] = " : \"\\401f\\x0o\\0o\" X\n"; assert(test_compose_seq_buffer(ctx, table_string_1, XKB_KEY_o, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSING, "", XKB_KEY_NoSymbol, XKB_KEY_e, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "foo", XKB_KEY_X, XKB_KEY_NoSymbol)); /* Test various cases */ const char table_string_2[] = " : \"\\x0abcg\\\"x\" A\n" /* hexadecimal sequence has max 2 chars */ " : \"éxyz\" B\n" /* non-ASCII (2 bytes) */ " : \"€xyz\" C\n" /* non-ASCII (3 bytes) */ " : \"✨xyz\" D\n" /* non-ASCII (4 bytes) */ " : \"✨\\x0aé\\x0a€x\\\"\" E\n" " : \"\" F\n"; assert(test_compose_seq_buffer(ctx, table_string_2, XKB_KEY_a, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "\x0a""bcg\"x", XKB_KEY_A, XKB_KEY_b, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "éxyz", XKB_KEY_B, XKB_KEY_c, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "€xyz", XKB_KEY_C, XKB_KEY_d, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "✨xyz", XKB_KEY_D, XKB_KEY_e, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "✨\x0aé\x0a€x\"", XKB_KEY_E, XKB_KEY_f, XKB_COMPOSE_FEED_ACCEPTED, XKB_COMPOSE_COMPOSED, "", XKB_KEY_F, XKB_KEY_NoSymbol)); } static uint32_t random_non_null_unicode_char(bool ascii) { if (ascii) return 0x01 + (rand() % 0x80); switch (rand() % 5) { case 0: /* U+0080..U+07FF: 2 bytes in UTF-8 */ return 0x80 + (rand() % 0x800); case 1: /* U+0800..U+FFFF: 3 bytes in UTF-8 */ return 0x800 + (rand() % 0x10000); case 2: /* U+10000..U+10FFFF: 4 bytes in UTF-8 */ return 0x10000 + (rand() % 0x110000); default: /* NOTE: Higher probability for ASCII */ /* U+0001..U+007F: 1 byte in UTF-8 */ return 0x01 + (rand() % 0x80); } } static void test_encode_escape_sequences(struct xkb_context *ctx) { char *escaped; /* Test empty string */ escaped = escape_utf8_string_literal(""); assert_streq_not_null("Empty string", "", escaped); free(escaped); /* Test specific ASCII characters: ", \ */ escaped = escape_utf8_string_literal("\"\\"); assert_streq_not_null("Quote and backslash", "\\\"\\\\", escaped); free(escaped); /* Test round-trip of random strings */ # define SAMPLE_SIZE 1000 # define MIN_CODE_POINT 0x0001 # define MAX_CODE_POINTS_COUNT 15 char buf[1 + MAX_CODE_POINTS_COUNT * 4]; for (int ascii = 1; ascii >= 0; ascii--) { for (size_t s = 0; s < SAMPLE_SIZE; s++) { memset(buf, 0xab, sizeof(buf)); /* Create the string */ size_t length = 1 + (rand() % MAX_CODE_POINTS_COUNT); size_t c = 0; for (size_t idx = 0; idx < length; idx++) { int nbytes; /* Get a random Unicode code point and encode it in UTF-8 */ do { const uint32_t cp = random_non_null_unicode_char(ascii); nbytes = utf32_to_utf8(cp, &buf[c]); } while (!nbytes); /* Handle invalid code point in UTF-8 */ c += nbytes - 1; assert(c <= sizeof(buf) - 1); } assert_printf(buf[c] == '\0', "NULL-terminated string\n"); assert_printf(strlen(buf) == c, "Contains no NULL char\n"); assert_printf(is_valid_utf8(buf, c), "Invalid input UTF-8 string: \"%s\"\n", buf); /* Escape the string */ escaped = escape_utf8_string_literal(buf); if (!escaped) break; assert_printf(is_valid_utf8(escaped, strlen(escaped)), "Invalid input UTF-8 string: %s\n", escaped); char *string_literal = asprintf_safe("\"%s\"", escaped); if (!string_literal) { free(escaped); break; } /* Unescape the string */ char *unescaped = parse_string_literal(ctx, string_literal); assert_streq_not_null("Escaped string", buf, unescaped); free(unescaped); free(string_literal); free(escaped); } } # undef SAMPLE_SIZE # undef MIN_CODE_POINT # undef MAX_CODE_POINTS_COUNT } /* Roundtrip check: check that a table parsed from a file and the table parsed * from the dump of the previous table are identical */ static void test_roundtrip(struct xkb_context *ctx) { /* TODO: add support for systems without open_memstream */ #if HAVE_OPEN_MEMSTREAM bool ok = false; /* Parse reference file */ char *input = test_read_file("locale/en_US.UTF-8/Compose"); assert(input); size_t input_length = strlen(input); struct xkb_compose_table *ref_table = xkb_compose_table_new_from_buffer( ctx, input, input_length, "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS ); free(input); assert(ref_table); /* Dump reference Compose table */ char *output; size_t output_length = 0; FILE *output_file = open_memstream(&output, &output_length); assert(output_file); ok = xkb_compose_table_dump(output_file, ref_table); fclose(output_file); assert(input); if (!ok) { free(output); xkb_compose_table_unref(ref_table); exit(TEST_SETUP_FAILURE); } /* Parse dumped table */ struct xkb_compose_table *table = xkb_compose_table_new_from_buffer( ctx, output, output_length, "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS ); free(output); assert(table); /* Check roundtrip by comparing table entries */ struct xkb_compose_table_iterator *iter = xkb_compose_table_iterator_new(table); xkb_compose_table_for_each(ref_table, compose_traverse_fn, iter); assert(xkb_compose_table_iterator_next(iter) == NULL); xkb_compose_table_iterator_free(iter); xkb_compose_table_unref(table); xkb_compose_table_unref(ref_table); #endif } /* CLI positional arguments: * 1. Seed for the pseudo-random generator: * - Leave it unset or set it to “-” to use current time. * - Use an integer to set it explicitly. * 2. Number of quickcheck loops: * - Leave it unset to use the default. It depends if the `RUNNING_VALGRIND` * environment variable is set. * - Use an integer to set it explicitly. */ int main(int argc, char *argv[]) { struct xkb_context *ctx; test_init(); ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); /* Initialize pseudo-random generator with program arg or current time */ unsigned int seed; if (argc >= 2 && !streq(argv[1], "-")) { seed = (unsigned int) atoi(argv[1]); } else { seed = (unsigned int) time(NULL); } fprintf(stderr, "Seed for the pseudo-random generator: %u\n", seed); srand(seed); /* Determine number of loops for quickchecks */ size_t quickcheck_loops = 50; /* Default */ if (argc > 2) { /* From command-line */ quickcheck_loops = (size_t)atoi(argv[2]); } else if (getenv("RUNNING_VALGRIND") != NULL) { /* Reduce if running Valgrind */ quickcheck_loops = quickcheck_loops / 20; } /* * Ensure no environment variables but “top_srcdir” is set. This ensures * that user Compose file paths are unset before the tests and set * explicitly when necessary. */ #ifdef __linux__ const char *srcdir = getenv("top_srcdir"); clearenv(); if (srcdir) setenv("top_srcdir", srcdir, 1); #else unsetenv("XCOMPOSEFILE"); unsetenv("XDG_CONFIG_HOME"); unsetenv("HOME"); unsetenv("XLOCALEDIR"); #endif test_compose_utf8_bom(ctx); test_invalid_encodings(ctx); test_seqs(ctx); test_conflicting(ctx); test_XCOMPOSEFILE(ctx); test_from_locale(ctx); test_state(ctx); test_modifier_syntax(ctx); test_include(ctx); test_override(ctx); test_traverse(ctx, quickcheck_loops); test_string_length(ctx); test_decode_escape_sequences(ctx); test_encode_escape_sequences(ctx); test_roundtrip(ctx); xkb_context_unref(ctx); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/context.c000066400000000000000000000210431510033435100214720ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #include "config.h" #include "test.h" #include "context.h" #include #include /* keeps a cache of all makedir/maketmpdir directories so we can free and * rmdir them in one go, see unmakedirs() */ char *dirnames[64]; int ndirs; /* keeps a cache of all buffered env vars so we can restore * them in one go, see restore_env() */ struct env { char *key; char *value; } environment[64]; int nenviron; static void buffer_env(const char *key) { char *v = getenv(key); environment[nenviron].key = strdup(key); environment[nenviron].value = v ? strdup(v) : NULL; nenviron++; } static void restore_env(void) { for (int i = 0; i < nenviron; i++) { char *key = environment[i].key, *value = environment[i].value; if (value) setenv(key, value, 1); else unsetenv(key); free(key); free(value); } nenviron = 0; memset(environment, 0, sizeof(environment)); } static const char *makedir(const char *parent, const char *path) { char *dirname = test_makedir(parent, path); dirnames[ndirs++] = dirname; return dirname; } static const char *maketmpdir(void) { char *tmpdir = test_maketempdir("xkbcommon-test.XXXXXX"); dirnames[ndirs++] = tmpdir; return tmpdir; } static void unmakedirs(void) { /* backwards order for rmdir to work */ for (int i = ndirs - 1; i >= 0; i--) { char *dir = dirnames[i]; if (!dir) break; rmdir(dir); free(dir); } ndirs = 0; memset(dirnames, 0, sizeof(dirnames)); } static void test_config_root_include_path(void) { struct xkb_context *ctx; const char *tmpdir; const char *context_path; buffer_env("XKB_CONFIG_ROOT"); buffer_env("HOME"); buffer_env("XDG_CONFIG_HOME"); tmpdir = maketmpdir(); setenv("XKB_CONFIG_ROOT", tmpdir, 1); unsetenv("HOME"); unsetenv("XDG_CONFIG_HOME"); /* Valid built-in path is last */ ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); const unsigned int nincludes = xkb_context_num_include_paths(ctx); assert(nincludes >= 1); context_path = xkb_context_include_path_get(ctx, nincludes - 1); assert(strcmp(context_path, tmpdir) == 0); xkb_context_unref(ctx); unmakedirs(); restore_env(); } static void test_config_root_include_path_fallback(void) { struct xkb_context *ctx; const char *xkbdir = DFLT_XKB_CONFIG_ROOT; const char *context_path; /* quick and dirty check that the default directory exists. * It may not on a vanilla test box if we just run the test * suite, so where it's not there just skip this test. */ struct stat stat_buf; int err = stat(xkbdir, &stat_buf); if (err != 0) return; if (!S_ISDIR(stat_buf.st_mode)) return; buffer_env("XKB_CONFIG_ROOT"); buffer_env("HOME"); buffer_env("XDG_CONFIG_HOME"); unsetenv("XKB_CONFIG_ROOT"); unsetenv("HOME"); unsetenv("XDG_CONFIG_HOME"); /* Valid built-in path is last */ ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); unsigned int nincludes = xkb_context_num_include_paths(ctx); assert(nincludes >= 1); context_path = xkb_context_include_path_get(ctx, nincludes - 1); assert(strcmp(context_path, xkbdir) == 0); xkb_context_unref(ctx); /* Invalid built-in path is replaced with legacy X11 path */ setenv("XKB_CONFIG_ROOT", "¡NONSENSE!", 1); ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); nincludes = xkb_context_num_include_paths(ctx); assert(nincludes >= 1); context_path = xkb_context_include_path_get(ctx, nincludes - 1); assert(strcmp(context_path, DFLT_XKB_LEGACY_ROOT) == 0); xkb_context_unref(ctx); /* Ensure some path is available */ const char *tmpdir = maketmpdir(); setenv("XKB_CONFIG_EXTRA_PATH", tmpdir, 1); /* Invalid built-in path and deliberately skipped legacy X11 path */ setenv("XKB_CONFIG_ROOT", "", 1); ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); nincludes = xkb_context_num_include_paths(ctx); assert(nincludes >= 1); context_path = xkb_context_include_path_get(ctx, nincludes - 1); assert(strcmp(context_path, tmpdir) == 0); xkb_context_unref(ctx); /* No valid path */ setenv("XKB_CONFIG_EXTRA_PATH", "", 1); ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(!ctx); unmakedirs(); restore_env(); } static void test_xkbdir_include_path(void) { struct xkb_context *ctx; const char *tmpdir; const char *xkb_path; const char *context_path; buffer_env("HOME"); buffer_env("XDG_CONFIG_HOME"); tmpdir = maketmpdir(); xkb_path = makedir(tmpdir, ".xkb"); setenv("HOME", tmpdir, 1); setenv("XDG_CONFIG_HOME", tmpdir, 1); /* No XDG directory in our tmpdir, so we expect * the $HOME/.xkb to be the first include path */ ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(xkb_context_num_include_paths(ctx) >= 1); context_path = xkb_context_include_path_get(ctx, 0); assert(strcmp(context_path, xkb_path) == 0); xkb_context_unref(ctx); unmakedirs(); restore_env(); } static void test_xdg_include_path(void) { struct xkb_context *ctx; const char *tmpdir; const char *xdg_path; const char *context_path; buffer_env("XDG_CONFIG_HOME"); tmpdir = maketmpdir(); xdg_path = makedir(tmpdir, "xkb"); setenv("XDG_CONFIG_HOME", tmpdir, 1); /* XDG path is always first */ ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(xkb_context_num_include_paths(ctx) >= 1); context_path = xkb_context_include_path_get(ctx, 0); assert(strcmp(context_path, xdg_path) == 0); xkb_context_unref(ctx); unmakedirs(); restore_env(); } static void test_xdg_include_path_fallback(void) { struct xkb_context *ctx; const char *tmpdir; const char *xdg_root, *xdg_path; const char *context_path; buffer_env("XDG_CONFIG_HOME"); buffer_env("HOME"); tmpdir = maketmpdir(); xdg_root = makedir(tmpdir, ".config"); xdg_path = makedir(xdg_root, "xkb"); setenv("HOME", tmpdir, 1); unsetenv("XDG_CONFIG_HOME"); /* XDG path is always first, even if fallback */ ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(xkb_context_num_include_paths(ctx) >= 1); context_path = xkb_context_include_path_get(ctx, 0); assert(strcmp(context_path, xdg_path) == 0); xkb_context_unref(ctx); unmakedirs(); restore_env(); } static void test_include_order(void) { struct xkb_context *ctx; const char *tmpdir; const char *xdg_path; const char *xkb_home_path; const char *xkb_root_path; const char *context_path; buffer_env("XKB_CONFIG_ROOT"); buffer_env("XDG_CONFIG_HOME"); buffer_env("HOME"); tmpdir = maketmpdir(); xdg_path = makedir(tmpdir, "xkb"); xkb_home_path = makedir(tmpdir, ".xkb"); xkb_root_path = makedir(tmpdir, "xkbroot"); setenv("HOME", tmpdir, 1); setenv("XDG_CONFIG_HOME", tmpdir, 1); setenv("XKB_CONFIG_ROOT", xkb_root_path, 1); ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); assert(xkb_context_num_include_paths(ctx) >= 3); /* XDG is first */ context_path = xkb_context_include_path_get(ctx, 0); assert(strcmp(context_path, xdg_path) == 0); /* $HOME/.xkb is second */ context_path = xkb_context_include_path_get(ctx, 1); assert(strcmp(context_path, xkb_home_path) == 0); /* CONFIG_ROOT is last */ context_path = xkb_context_include_path_get(ctx, 2); assert(strcmp(context_path, xkb_root_path) == 0); xkb_context_unref(ctx); unmakedirs(); restore_env(); } int main(void) { test_init(); struct xkb_context *context = test_get_context(0); xkb_atom_t atom; assert(context); assert(xkb_context_num_include_paths(context) == 1); assert(!xkb_context_include_path_append(context, "¡NONSENSE!")); assert(xkb_context_num_include_paths(context) == 1); atom = xkb_atom_intern(context, "HELLOjunkjunkjunk", 5); assert(atom != XKB_ATOM_NONE); assert(streq(xkb_atom_text(context, atom), "HELLO")); atom = xkb_atom_intern_literal(context, "HELLOjunkjunkjunk"); assert(atom != XKB_ATOM_NONE); assert(streq(xkb_atom_text(context, atom), "HELLOjunkjunkjunk")); xkb_context_unref(context); test_config_root_include_path(); test_config_root_include_path_fallback(); test_xkbdir_include_path(); test_xdg_include_path(); test_xdg_include_path_fallback(); test_include_order(); return 0; } xkbcommon-libxkbcommon-54ee7ac/test/data/000077500000000000000000000000001510033435100205535ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/.editorconfig000066400000000000000000000002311510033435100232240ustar00rootroot00000000000000[*] charset = utf-8 end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true indent_style = tab indent_size = 8 max_line_length = 80 xkbcommon-libxkbcommon-54ee7ac/test/data/.gitattributes000066400000000000000000000000111510033435100234360ustar00rootroot00000000000000* eol=lf xkbcommon-libxkbcommon-54ee7ac/test/data/compat/000077500000000000000000000000001510033435100220365ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/compat/accessx000066400000000000000000000021411510033435100234100ustar00rootroot00000000000000default partial xkb_compatibility "basic" { interpret AccessX_Enable { action= LockControls(controls=AccessXKeys); }; }; partial xkb_compatibility "full" { interpret AccessX_Enable { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable { action= LockControls(controls=Overlay1); }; interpret Overlay2_Enable { action= LockControls(controls=Overlay2); }; interpret AudibleBell_Enable { action= LockControls(controls=AudibleBell); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/basic000066400000000000000000000037121510033435100230450ustar00rootroot00000000000000// Minimal set of symbol interpretations to provide // reasonable default behavior (Num lock, Shift lock, // Caps lock, and Mode switch) and set up the // automatic updating of common keyboard LEDs. default xkb_compatibility "basic" { virtual_modifiers NumLock,AltGr; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Any+Lock { action= LockMods(modifiers=Lock); }; interpret Num_Lock+Any { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret Mode_switch { useModMapMods= level1; virtualModifier= AltGr; action= SetGroup(group=+1); }; interpret Any + Any { action= SetMods(modifiers=modMapMods); }; group 2 = AltGr; group 3 = AltGr; group 4 = AltGr; include "ledcaps" include "lednum" indicator "Shift Lock" { !allowExplicit; whichModState= Locked; modifiers= Shift; }; }; xkb_compatibility "pure-virtual-modifiers" { virtual_modifiers NumLock,AltGr,Alt; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; interpret Shift_Lock { action= LockMods(modifiers=Shift); }; interpret Num_Lock { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret Shift_L { action= SetMods(modifiers=Shift); }; interpret Shift_R { action= SetMods(modifiers=Shift); }; interpret Control_L { action= SetMods(modifiers=Control); }; interpret Control_R { action= SetMods(modifiers=Control); }; interpret Alt_L { action= SetMods(modifiers=Alt); }; interpret Alt_R { action= SetMods(modifiers=Alt); }; }; xkb_compatibility "invalid-pure-virtual-modifiers" { virtual_modifiers Alt; interpret Alt_R + Alt { action= SetMods(modifiers=Alt); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/caps000066400000000000000000000020521510033435100227060ustar00rootroot00000000000000partial xkb_compatibility "caps_lock" { // Keysym Caps_Lock locks the Lock modifier. // With this definition, the keysym Caps_Lock can be used without binding // the whole key to a real modifier. This is essential when you don't // want to use Caps_Lock on the first level. // This should not have any compatibility issues when used together with // other layouts which don't utilize this capability. interpret Caps_Lock { action = LockMods(modifiers = Lock); }; }; partial xkb_compatibility "unlock-on-release" { interpret Caps_Lock { action = LockMods(modifiers = Lock, unlockOnPress=false); }; interpret.repeat= False; interpret Caps_Lock + Lock { action = LockMods(modifiers = Lock, unlockOnPress=false); }; }; partial xkb_compatibility "unlock-on-press" { interpret Caps_Lock { action = LockMods(modifiers = Lock, unlockOnPress); }; interpret.repeat= False; interpret Caps_Lock + Lock { action = LockMods(modifiers = Lock, unlockOnPress); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/complete000066400000000000000000000003441510033435100235720ustar00rootroot00000000000000default xkb_compatibility "complete" { include "basic" augment "iso9995" augment "mousekeys" augment "accessx(full)" augment "misc" augment "xfree86" augment "level5" augment "caps(caps_lock)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/iso9995000066400000000000000000000031541510033435100231160ustar00rootroot00000000000000// Fairly complete set of symbol interpretations // to provide reasonable default behavior. default partial xkb_compatibility "default" { virtual_modifiers LevelThree,AltGr; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; interpret ISO_Level2_Latch+Shift { useModMapMods= level1; action= LatchMods(modifiers=Shift); }; interpret ISO_Level3_Shift+Any { useModMapMods= level1; virtualModifier= LevelThree; action= SetMods(modifiers=LevelThree); }; interpret ISO_Level3_Shift { action= SetMods(modifiers=LevelThree); }; interpret ISO_Level3_Latch+Any { useModMapMods= level1; virtualModifier= LevelThree; action= LatchMods(modifiers=LevelThree); }; interpret ISO_Level3_Latch { action= LatchMods(modifiers=LevelThree); }; interpret ISO_Level3_Lock+Any { useModMapMods= level1; virtualModifier= LevelThree; action= LockMods(modifiers=LevelThree); }; interpret ISO_Level3_Lock { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch { useModMapMods= level1; virtualModifier= AltGr; action= LatchGroup(group=2); }; interpret ISO_Next_Group { useModMapMods= level1; virtualModifier= AltGr; action= LockGroup(group=+1); }; interpret ISO_Prev_Group { useModMapMods= level1; virtualModifier= AltGr; action= LockGroup(group=-1); }; interpret ISO_First_Group { action= LockGroup(group=1); }; interpret ISO_Last_Group { action= LockGroup(group=2); }; indicator "Group 2" { !allowExplicit; groups= All-Group1; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/iso9995-v2000066400000000000000000000021271510033435100234420ustar00rootroot00000000000000default partial xkb_compatibility "lockOnPress" { virtual_modifiers AltGr; interpret.repeat= False; interpret ISO_Next_Group { useModMapMods= level1; virtualModifier= AltGr; action= LockGroup(group=+1, lockOnRelease=false); }; interpret ISO_Prev_Group { useModMapMods= level1; virtualModifier= AltGr; action= LockGroup(group=-1, lockOnRelease=false); }; interpret ISO_First_Group { action= LockGroup(group=1, lockOnRelease=false); }; interpret ISO_Last_Group { action= LockGroup(group=2, lockOnRelease=false); }; }; partial xkb_compatibility "lockOnRelease" { virtual_modifiers AltGr; interpret.repeat= False; interpret ISO_Next_Group { useModMapMods= level1; virtualModifier= AltGr; action= LockGroup(group=+1, lockOnRelease); }; interpret ISO_Prev_Group { useModMapMods= level1; virtualModifier= AltGr; action= LockGroup(group=-1, lockOnRelease); }; interpret ISO_First_Group { action= LockGroup(group=1, lockOnRelease); }; interpret ISO_Last_Group { action= LockGroup(group=2, lockOnRelease); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/ledcaps000066400000000000000000000007251510033435100234000ustar00rootroot00000000000000// Use the Caps Lock LED to show either // Caps Lock, Group, or Shift Lock state. default partial xkb_compatibility "caps_lock" { indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; }; partial xkb_compatibility "group_lock" { indicator "Caps Lock" { modifiers= None; groups=All-group1; }; }; partial xkb_compatibility "shift_lock" { indicator "Caps Lock" { whichModState= Locked; modifiers= Shift; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/lednum000066400000000000000000000007221510033435100232460ustar00rootroot00000000000000// Use the Num Lock LED to show either // Num Lock, Group, or Shift Lock state. default partial xkb_compatibility "num_lock" { indicator "Num Lock" { !allowExplicit; whichModState= Locked; modifiers= NumLock; }; }; partial xkb_compatibility "group_lock" { indicator "Num Lock" { modifiers= None; groups=All-group1; }; }; partial xkb_compatibility "shift_lock" { indicator "Num Lock" { whichModState= Locked; modifiers= Shift; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/leds000066400000000000000000000022311510033435100227060ustar00rootroot00000000000000default partial xkb_compatibility "groups" { indicator "Caps Lock" { modifiers= None; whichGroupState=Base; groups=0; }; indicator "Num Lock" { modifiers= None; whichGroupState=Base; groups=All; // Same as All-Group1 }; indicator "Scroll Lock" { modifiers= None; whichGroupState=Latched; groups=0; }; indicator "Compose" { modifiers= None; whichGroupState=Latched; groups=All; // Same as All-Group1 }; indicator "Kana" { modifiers= None; whichGroupState=Locked; groups=0; // Inactive }; indicator "Sleep" { modifiers= None; whichGroupState=Locked; groups=All-Group1; }; indicator "Suspend" { modifiers= None; whichGroupState=Effective; groups=0; // Inactive }; indicator "Mute" { modifiers= None; whichGroupState=Effective; groups=All-Group1; }; // Specific group + whichGroupState mask indicator "Misc" { modifiers= None; whichGroupState=Base+Latched; groups=Group2; }; indicator "Mail" { modifiers= None; whichGroupState=Locked; groups=Group2; }; indicator "Charging" { modifiers= None; whichGroupState=Latched+Locked+Effective; groups=Group3; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/ledscroll000066400000000000000000000007461510033435100237530ustar00rootroot00000000000000// Use the Scroll Lock LED to show either // Scroll Lock, Group, or Shift Lock state. default partial xkb_compatibility "scroll_lock" { indicator "Scroll Lock" { allowExplicit; whichModState= Locked; modifiers= ScrollLock; }; }; partial xkb_compatibility "group_lock" { indicator "Scroll Lock" { modifiers= None; groups=All-group1; }; }; partial xkb_compatibility "shift_lock" { indicator "Scroll Lock" { whichModState= Locked; modifiers= Shift; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/level3-v2000066400000000000000000000016451510033435100235060ustar00rootroot00000000000000partial xkb_compatibility "latchOnPress" { virtual_modifiers LevelThree; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; interpret ISO_Level3_Latch+Any { useModMapMods= level1; virtualModifier= LevelThree; action= LatchMods(modifiers=LevelThree, latchOnPress); }; interpret ISO_Level3_Latch { action= LatchMods(modifiers=LevelThree, latchOnPress); }; }; partial xkb_compatibility "latchOnRelease" { virtual_modifiers LevelThree; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; interpret ISO_Level3_Latch+Any { useModMapMods= level1; virtualModifier= LevelThree; action= LatchMods(modifiers=LevelThree, latchOnPress=false); }; interpret ISO_Level3_Latch { action= LatchMods(modifiers=LevelThree, latchOnPress=false); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/level5000066400000000000000000000025641510033435100231640ustar00rootroot00000000000000// Fairly complete set of symbol interpretations // to provide reasonable default behavior. default partial xkb_compatibility "default" { virtual_modifiers LevelFive; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; interpret ISO_Level5_Shift+Any { useModMapMods= level1; virtualModifier= LevelFive; action= SetMods(modifiers=LevelFive); }; interpret ISO_Level5_Shift { action= SetMods(modifiers=LevelFive); }; interpret ISO_Level5_Latch+Any { useModMapMods= level1; virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive); }; interpret ISO_Level5_Latch { action= LatchMods(modifiers=LevelFive); }; interpret ISO_Level5_Lock+Any { useModMapMods= level1; virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret ISO_Level5_Lock { action= LockMods(modifiers=LevelFive); }; }; partial xkb_compatibility "level5_lock" { // This defines a Level5-Lock using the NumLock real modifier // in order to create arbitrary level-behaviour, which would // not be possible with the virtual modifier. // See also: types/level5 : EIGHT_LEVEL_LEVEL_FIVE_LOCK // See also: symbols/level5(lock) virtual_modifiers NumLock; interpret ISO_Level5_Lock { action = LockMods(modifiers = NumLock); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/merge_modes000066400000000000000000000112441510033435100242510ustar00rootroot00000000000000// WARNING: This file was auto-generated by: scripts/update-merge-modes-tests.py xkb_compat "base-default" { virtual_modifiers NumLock; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; interpret Any + Any { action= SetMods(modifiers=modMapMods); }; interpret Caps_Lock { action = LockMods(modifiers = Lock); }; indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; indicator "Num Lock" { !allowExplicit; whichModState= Locked; modifiers= NumLock; }; }; xkb_compat "base-augment" { augment virtual_modifiers NumLock; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; augment interpret Any + Any { action= SetMods(modifiers=modMapMods); }; augment interpret Caps_Lock { action = LockMods(modifiers = Lock); }; augment indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; augment indicator "Num Lock" { !allowExplicit; whichModState= Locked; modifiers= NumLock; }; }; xkb_compat "base-override" { override virtual_modifiers NumLock; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; override interpret Any + Any { action= SetMods(modifiers=modMapMods); }; override interpret Caps_Lock { action = LockMods(modifiers = Lock); }; override indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; override indicator "Num Lock" { !allowExplicit; whichModState= Locked; modifiers= NumLock; }; }; xkb_compat "base-replace" { replace virtual_modifiers NumLock; interpret.repeat= False; setMods.clearLocks= True; latchMods.clearLocks= True; latchMods.latchToLock= True; replace interpret Any + Any { action= SetMods(modifiers=modMapMods); }; replace interpret Caps_Lock { action = LockMods(modifiers = Lock); }; replace indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; replace indicator "Num Lock" { !allowExplicit; whichModState= Locked; modifiers= NumLock; }; }; xkb_compat "update-default" { virtual_modifiers NumLock; interpret.repeat= False; setMods.clearLocks= False; // Changed // Unchanged interpret Any + Any { action= SetMods(modifiers=modMapMods); }; // Changed interpret Caps_Lock { action = LockMods(modifiers = NumLock); }; // Unchanged indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; // Changed indicator "Num Lock" { !allowExplicit; whichModState= Base; modifiers= Lock; }; // New indicator "Kana" { !allowExplicit; whichModState= Locked; modifiers= Control; }; }; xkb_compat "update-augment" { augment virtual_modifiers NumLock; augment interpret.repeat= False; augment setMods.clearLocks= False; // Changed // Unchanged augment interpret Any + Any { action= SetMods(modifiers=modMapMods); }; // Changed augment interpret Caps_Lock { action = LockMods(modifiers = NumLock); }; // Unchanged augment indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; // Changed augment indicator "Num Lock" { !allowExplicit; whichModState= Base; modifiers= Lock; }; // New augment indicator "Kana" { !allowExplicit; whichModState= Locked; modifiers= Control; }; }; xkb_compat "update-override" { override virtual_modifiers NumLock; override interpret.repeat= False; override setMods.clearLocks= False; // Changed // Unchanged override interpret Any + Any { action= SetMods(modifiers=modMapMods); }; // Changed override interpret Caps_Lock { action = LockMods(modifiers = NumLock); }; // Unchanged override indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; // Changed override indicator "Num Lock" { !allowExplicit; whichModState= Base; modifiers= Lock; }; // New override indicator "Kana" { !allowExplicit; whichModState= Locked; modifiers= Control; }; }; xkb_compat "update-replace" { replace virtual_modifiers NumLock; replace interpret.repeat= False; replace setMods.clearLocks= False; // Changed // Unchanged replace interpret Any + Any { action= SetMods(modifiers=modMapMods); }; // Changed replace interpret Caps_Lock { action = LockMods(modifiers = NumLock); }; // Unchanged replace indicator "Caps Lock" { !allowExplicit; whichModState= Locked; modifiers= Lock; }; // Changed replace indicator "Num Lock" { !allowExplicit; whichModState= Base; modifiers= Lock; }; // New replace indicator "Kana" { !allowExplicit; whichModState= Locked; modifiers= Control; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/merge_modes_defaults000066400000000000000000000035671510033435100261510ustar00rootroot00000000000000xkb_compat { virtual_modifiers M1=0x1000, M2=0x2000, M3=0x4000, M4=0x8000; interpret.repeat= False; // Effective: override interpret.repeat= True; interpret.virtualmod = M1; // Effective: override interpret.virtualmod = M2; // Ineffective: cannot augment previous value augment interpret.virtualmod = M3; SetGroup.group = 1; // Effective: override SetGroup.group = 2; // Ineffective: cannot augment previous value augment SetGroup.group = 3; // Effective: *override* every explicit field interpret a { virtualmod = M4; action=SetGroup(group=1); }; interpret A { repeat = False; virtualmod = M1; action=SetMods(mods=M1); }; // Effective: no previous interpret entry, // so *override* every explicit field augment interpret s { repeat = False; action=SetGroup(); }; // Only augment fields not set previously (explicit or implicit) augment interpret s { // Ineffective: cannot augment previous implicit value virtualmod = M4; // Ineffective: cannot augment previous explicit value action=SetGroup(group=4); // Effective: no previous value useModMapMods=level1; }; augment interpret S { action=SetGroup(group=4); }; indicator.modifiers = M1; indicator.modifiers = M2; augment indicator.modifiers = M3; indicator.groups = All - 1; indicator.controls = AudibleBell; indicator "A" { modifiers = M4; whichmodstate = base; }; indicator "A" { whichmodstate = locked; whichgroupstate = locked; controls = SlowKeys; }; augment indicator "B" { modifiers = M4; whichmodstate = base; }; augment indicator "B" { groups = 4; whichmodstate = locked; whichgroupstate = locked; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/merge_modes_vmods000066400000000000000000000006041510033435100254570ustar00rootroot00000000000000xkb_compat "new" { virtual_modifiers U7, Z7=0, M7=0x70000; augment virtual_modifiers U1, U2=none, U3=0x300000; override virtual_modifiers U4, U5=none, U6=0x600000; augment virtual_modifiers Z1, Z2=none, Z3=0x310000; override virtual_modifiers Z4, Z5=none, Z6=0x610000; augment virtual_modifiers M1, M2=none, M3=0x320000; override virtual_modifiers M4, M5=none, M6=0x620000; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/misc000066400000000000000000000052441510033435100227210ustar00rootroot00000000000000default partial xkb_compatibility "misc" { virtual_modifiers Alt,Meta,Super,Hyper,ScrollLock; // Interpretations for some other useful keys. interpret Terminate_Server { action = Terminate(); }; setMods.clearLocks= True; // Sets the "Alt" virtual modifier. interpret Alt_L+Any { //useModMapMods= level1; virtualModifier= Alt; action = SetMods(modifiers=modMapMods); }; interpret Alt_L { action = SetMods(modifiers=Alt); }; interpret Alt_R+Any { //useModMapMods= level1; virtualModifier= Alt; action = SetMods(modifiers=modMapMods); }; interpret Alt_R { action = SetMods(modifiers=Alt); }; // Sets the "Meta" virtual modifier. interpret Meta_L+Any { //useModMapMods= level1; virtualModifier= Meta; action = SetMods(modifiers=modMapMods); }; interpret Meta_L { action = SetMods(modifiers=Meta); }; interpret Meta_R+Any { //useModMapMods= level1; virtualModifier= Meta; action = SetMods(modifiers=modMapMods); }; interpret Meta_R { action = SetMods(modifiers=Meta); }; // Sets the "Super" virtual modifier. interpret Super_L+Any { //useModMapMods= level1; virtualModifier= Super; action = SetMods(modifiers=modMapMods); }; interpret Super_L { action = SetMods(modifiers=Super); }; interpret Super_R+Any { //useModMapMods= level1; virtualModifier= Super; action = SetMods(modifiers=modMapMods); }; interpret Super_R { action = SetMods(modifiers=Super); }; // Sets the "Hyper" virtual modifier. interpret Hyper_L+Any { //useModMapMods= level1; virtualModifier= Hyper; action = SetMods(modifiers=modMapMods); }; interpret Hyper_L { action = SetMods(modifiers=Hyper); }; interpret Hyper_R+Any { //useModMapMods= level1; virtualModifier= Hyper; action = SetMods(modifiers=modMapMods); }; interpret Hyper_R { action = SetMods(modifiers=Hyper); }; // Sets the "ScrollLock" virtual modifier and // makes it actually lock when pressed. Sets // up a map for the scroll lock indicator. interpret Scroll_Lock+Any { virtualModifier= ScrollLock; action = LockMods(modifiers=modMapMods); }; include "ledscroll" include "misc(assign_shift_left_action)" }; partial xkb_compatibility "assign_shift_left_action" { // Because of the irrevertable modifier mapping in symbols/pc, // is getting bound to the Lock modifier when using // symbols/shift(both_capslock), creating unwanted behaviour. // This is a quirk, to circumvent the problem. interpret Shift_L { action = SetMods(modifiers = Shift); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/mousekeys000066400000000000000000000107741510033435100240160ustar00rootroot00000000000000// Interpretations for arrow keys and a bunch of // other common keysyms which make it possible to // bind "mouse" keys using xmodmap and activate or // deactivate them from the keyboard. default partial xkb_compatibility "mousekeys" { // Keypad actions. interpret.repeat= True; interpret KP_1 { action = MovePtr(x=-1,y= +1); }; interpret KP_End { action = MovePtr(x=-1,y= +1); }; interpret KP_2 { action = MovePtr(x=+0,y= +1); }; interpret KP_Down { action = MovePtr(x=+0,y= +1); }; interpret KP_3 { action = MovePtr(x=+1,y=+1); }; interpret KP_Next { action = MovePtr(x=+1,y=+1); }; interpret KP_4 { action = MovePtr(x=-1,y=+0); }; interpret KP_Left { action = MovePtr(x=-1,y=+0); }; interpret KP_6 { action = MovePtr(x=+1,y=+0); }; interpret KP_Right { action = MovePtr(x=+1,y=+0); }; interpret KP_7 { action = MovePtr(x=-1,y=-1); }; interpret KP_Home { action = MovePtr(x=-1,y=-1); }; interpret KP_8 { action = MovePtr(x=+0,y=-1); }; interpret KP_Up { action = MovePtr(x=+0,y=-1); }; interpret KP_9 { action = MovePtr(x=+1,y=-1); }; interpret KP_Prior { action = MovePtr(x=+1,y=-1); }; interpret KP_5 { action = PointerButton(button=default); }; interpret KP_Begin { action = PointerButton(button=default); }; interpret KP_F2 { action = SetPtrDflt(affect=defaultButton,button=1); }; interpret KP_Divide { action = SetPtrDflt(affect=defaultButton,button=1); }; interpret KP_F3 { action = SetPtrDflt(affect=defaultButton,button=2); }; interpret KP_Multiply { action = SetPtrDflt(affect=defaultButton,button=2); }; interpret KP_F4 { action = SetPtrDflt(affect=defaultButton,button=3); }; interpret KP_Subtract { action = SetPtrDflt(affect=defaultButton,button=3); }; interpret KP_Separator { action = PointerButton(button=default,count=2); }; interpret KP_Add { action = PointerButton(button=default,count=2); }; interpret KP_0 { action = LockPointerButton(button=default,affect=lock); }; interpret KP_Insert { action = LockPointerButton(button=default,affect=lock); }; interpret KP_Decimal { action = LockPointerButton(button=default,affect=unlock); }; interpret KP_Delete { action = LockPointerButton(button=default,affect=unlock); }; // Additional mappings for Solaris keypad compatibility. interpret F25 { // aka KP_Divide action = SetPtrDflt(affect=defaultButton,button=1); }; interpret F26 { // aka KP_Multiply action = SetPtrDflt(affect=defaultButton,button=2); }; interpret F27 { // aka KP_Home action = MovePtr(x=-1,y=-1); }; interpret F29 { // aka KP_Prior action = MovePtr(x=+1,y=-1); }; interpret F31 { // aka KP_Begin action = PointerButton(button=default); }; interpret F33 { // aka KP_End action = MovePtr(x=-1,y= +1); }; interpret F35 { // aka KP_Next action = MovePtr(x=+1,y=+1); }; interpret.repeat= False; // New keysym actions. interpret Pointer_Button_Dflt { action= PointerButton(button=default); }; interpret Pointer_Button1 { action= PointerButton(button=1); }; interpret Pointer_Button2 { action= PointerButton(button=2); }; interpret Pointer_Button3 { action= PointerButton(button=3); }; interpret Pointer_DblClick_Dflt { action= PointerButton(button=default,count=2); }; interpret Pointer_DblClick1 { action= PointerButton(button=1,count=2); }; interpret Pointer_DblClick2 { action= PointerButton(button=2,count=2); }; interpret Pointer_DblClick3 { action= PointerButton(button=3,count=2); }; interpret Pointer_Drag_Dflt { action= LockPointerButton(button=default); }; interpret Pointer_Drag1 { action= LockPointerButton(button=1); }; interpret Pointer_Drag2 { action= LockPointerButton(button=2); }; interpret Pointer_Drag3 { action= LockPointerButton(button=3); }; interpret Pointer_EnableKeys { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext { action= SetPtrDflt(affect=defaultButton,button= +1); }; interpret Pointer_DfltBtnPrev { action= SetPtrDflt(affect=defaultButton,button= -1); }; // Allow an indicator for MouseKeys. indicator "Mouse Keys" { //!allowExplicit; indicatorDrivesKeyboard; controls= MouseKeys; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/pc000066400000000000000000000005241510033435100223640ustar00rootroot00000000000000default partial xkb_compatibility "pc" { // Sets the "Alt" virtual modifier. virtual_modifiers Alt; setMods.clearLocks= True; interpret Alt_L+Any { virtualModifier= Alt; action = SetMods(modifiers=modMapMods); }; interpret Alt_R+Any { virtualModifier= Alt; action = SetMods(modifiers=modMapMods); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/recursive000066400000000000000000000002631510033435100237710ustar00rootroot00000000000000default xkb_compatibility "foo" { include "recursive" }; xkb_compatibility "bar" { include "recursive(baz)" }; xkb_compatibility "baz" { include "recursive(bar)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/compat/xfree86000066400000000000000000000034621510033435100232550ustar00rootroot00000000000000// XFree86 special keysyms. default partial xkb_compatibility "basic" { interpret.repeat= True; interpret XF86_Switch_VT_1 { action = SwitchScreen(Screen=1, !SameServer); }; interpret XF86_Switch_VT_2 { action = SwitchScreen(Screen=2, !SameServer); }; interpret XF86_Switch_VT_3 { action = SwitchScreen(Screen=3, !SameServer); }; interpret XF86_Switch_VT_4 { action = SwitchScreen(Screen=4, !SameServer); }; interpret XF86_Switch_VT_5 { action = SwitchScreen(Screen=5, !SameServer); }; interpret XF86_Switch_VT_6 { action = SwitchScreen(Screen=6, !SameServer); }; interpret XF86_Switch_VT_7 { action = SwitchScreen(Screen=7, !SameServer); }; interpret XF86_Switch_VT_8 { action = SwitchScreen(Screen=8, !SameServer); }; interpret XF86_Switch_VT_9 { action = SwitchScreen(Screen=9, !SameServer); }; interpret XF86_Switch_VT_10 { action = SwitchScreen(Screen=10, !SameServer); }; interpret XF86_Switch_VT_11 { action = SwitchScreen(Screen=11, !SameServer); }; interpret XF86_Switch_VT_12 { action = SwitchScreen(Screen=12, !SameServer); }; interpret XF86LogGrabInfo { action = Private(type=0x86, data="PrGrbs"); }; interpret XF86LogWindowTree { action = Private(type=0x86, data="PrWins"); }; interpret XF86_Next_VMode { action = Private(type=0x86, data="+VMode"); }; interpret XF86_Prev_VMode { action = Private(type=0x86, data="-VMode"); }; }; partial xkb_compatibility "grab_break" { interpret XF86_Ungrab { action = Private(type=0x86, data="Ungrab"); }; interpret XF86_ClearGrab { action = Private(type=0x86, data="ClsGrb"); }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/extra/000077500000000000000000000000001510033435100216765ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/extra/symbols/000077500000000000000000000000001510033435100233665ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/extra/symbols/banana000066400000000000000000000001271510033435100245310ustar00rootroot00000000000000xkb_symbols "1" { key <> { ["🍉"] }; }; xkb_symbols "2" { key <> { ["🍍"] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/extra/symbols/capslock000066400000000000000000000000661510033435100251120ustar00rootroot00000000000000xkb_symbols "custom" { key { [ XF86Fn ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/extra/symbols/level3000066400000000000000000000002321510033435100245000ustar00rootroot00000000000000default partial modifier_keys xkb_symbols "ralt_switch" { key { [ ISO_Level3_Shift, ISO_Level3_Lock ] }; include "level3(modifier_mapping)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/000077500000000000000000000000001510033435100223615ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/aliases000066400000000000000000000042001510033435100237210ustar00rootroot00000000000000 // keycode aliases for phonetic keyboard maps default xkb_keycodes "qwerty" { alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_keycodes "azerty" { alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_keycodes "qwertz" { alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/aliases-xkbcommon000066400000000000000000000036361510033435100257300ustar00rootroot00000000000000 // keycode aliases for phonetic keyboard maps default xkb_keycodes "qwerty" { alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias =

; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_keycodes "azerty" { alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias =

; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_keycodes "qwertz" { alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias =

; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/empty000066400000000000000000000001041510033435100234350ustar00rootroot00000000000000default xkb_keycodes "empty" { minimum= 8; maximum= 255; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/evdev000066400000000000000000000213401510033435100234150ustar00rootroot00000000000000// translation from evdev scancodes to something resembling xfree86 keycodes. default xkb_keycodes "evdev" { minimum = 8; maximum = 255; # Added for pc105 compatibility = 94; = 49; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 51; alias = ; = 36; = 66; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 50; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 64; = 37; = 65; = 105; = 108; // Microsoft keyboard extra keys = 133; = 134; = 135; alias

= ; = 9; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 95; = 96; = 107; // = 107; = 78; = 127; // = 419; = 118; = 110; = 112; = 119; = 115; = 117; = 111; = 113; = 116; = 114; = 77; = 106; = 63; = 82; = 79; = 80; = 81; = 86; = 83; = 84; = 85; = 87; = 88; = 89; = 104; = 90; = 91; = 125; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; // Keys that are generated on Japanese keyboards // = 93; // Hankaku/Zenkakau toggle - not actually used alias = ; = 101; // Hiragana/Katakana toggle = 97; // backslash/underscore = 100; // Henkan = 102; // Muhenkan = 132; // Yen = 98; // Katakana = 99; // Hiragana = 103; // KPJPComma // = 97; // Romaji // Keys that are generated on Korean keyboards = 130; // Hangul Latin toggle = 131; // Hangul to Hanja conversion // Solaris compatibility alias = ; alias = ; = 121; = 122; = 123; = 124; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; // Extended keys that may be generated on "Internet" keyboards. // evdev has standardize names for these. = 109; // #define KEY_LINEFEED 101 = 120; // #define KEY_MACRO 112 = 126; // #define KEY_KPPLUSMINUS 118 = 128; // #define KEY_SCALE 120 = 129; // #define KEY_KPCOMMA 121 = 147; // #define KEY_MENU 139 = 148; // #define KEY_CALC 140 = 149; // #define KEY_SETUP 141 = 150; // #define KEY_SLEEP 142 = 151; // #define KEY_WAKEUP 143 = 152; // #define KEY_FILE 144 = 153; // #define KEY_SENDFILE 145 = 154; // #define KEY_DELETEFILE 146 = 155; // #define KEY_XFER 147 = 156; // #define KEY_PROG1 148 = 157; // #define KEY_PROG2 149 = 158; // #define KEY_WWW 150 = 159; // #define KEY_MSDOS 151 = 160; // #define KEY_COFFEE 152 = 161; // #define KEY_DIRECTION 153 = 162; // #define KEY_CYCLEWINDOWS 154 = 163; // #define KEY_MAIL 155 = 164; // #define KEY_BOOKMARKS 156 = 165; // #define KEY_COMPUTER 157 = 166; // #define KEY_BACK 158 = 167; // #define KEY_FORWARD 159 = 168; // #define KEY_CLOSECD 160 = 169; // #define KEY_EJECTCD 161 = 170; // #define KEY_EJECTCLOSECD 162 = 171; // #define KEY_NEXTSONG 163 = 172; // #define KEY_PLAYPAUSE 164 = 173; // #define KEY_PREVIOUSSONG 165 = 174; // #define KEY_STOPCD 166 = 175; // #define KEY_RECORD 167 = 176; // #define KEY_REWIND 168 = 177; // #define KEY_PHONE 169 = 178; // #define KEY_ISO 170 = 179; // #define KEY_CONFIG 171 = 180; // #define KEY_HOMEPAGE 172 = 181; // #define KEY_REFRESH 173 = 182; // #define KEY_EXIT 174 = 183; // #define KEY_MOVE 175 = 184; // #define KEY_EDIT 176 = 185; // #define KEY_SCROLLUP 177 = 186; // #define KEY_SCROLLDOWN 178 = 187; // #define KEY_KPLEFTPAREN 179 = 188; // #define KEY_KPRIGHTPAREN 180 = 189; // #define KEY_NEW 181 = 190; // #define KEY_REDO 182 = 208; // #define KEY_PLAYCD 200 = 209; // #define KEY_PAUSECD 201 = 210; // #define KEY_PROG3 202 = 211; // #define KEY_PROG4 203 conflicts with AB11 = 212; // #define KEY_DASHBOARD 204 = 213; // #define KEY_SUSPEND 205 = 214; // #define KEY_CLOSE 206 = 215; // #define KEY_PLAY 207 = 216; // #define KEY_FASTFORWARD 208 = 217; // #define KEY_BASSBOOST 209 = 218; // #define KEY_PRINT 210 = 219; // #define KEY_HP 211 = 220; // #define KEY_CAMERA 212 = 221; // #define KEY_SOUND 213 = 222; // #define KEY_QUESTION 214 = 223; // #define KEY_EMAIL 215 = 224; // #define KEY_CHAT 216 = 225; // #define KEY_SEARCH 217 = 226; // #define KEY_CONNECT 218 = 227; // #define KEY_FINANCE 219 = 228; // #define KEY_SPORT 220 = 229; // #define KEY_SHOP 221 = 230; // #define KEY_ALTERASE 222 = 231; // #define KEY_CANCEL 223 = 232; // #define KEY_BRIGHTNESSDOWN 224 = 233; // #define KEY_BRIGHTNESSUP 225 = 234; // #define KEY_MEDIA 226 = 235; // #define KEY_SWITCHVIDEOMODE 227 = 236; // #define KEY_KBDILLUMTOGGLE 228 = 237; // #define KEY_KBDILLUMDOWN 229 = 238; // #define KEY_KBDILLUMUP 230 = 239; // #define KEY_SEND 231 = 240; // #define KEY_REPLY 232 = 241; // #define KEY_FORWARDMAIL 233 = 242; // #define KEY_SAVE 234 = 243; // #define KEY_DOCUMENTS 235 = 244; // #define KEY_BATTERY 236 = 245; // #define KEY_BLUETOOTH 237 = 246; // #define KEY_WLAN 238 = 247; // #define KEY_UWB 239 = 248; // #define KEY_UNKNOWN 240 = 249; // #define KEY_VIDEO_NEXT 241 = 250; // #define KEY_VIDEO_PREV 242 = 251; // #define KEY_BRIGHTNESS_CYCLE 243 = 252; // #define KEY_BRIGHTNESS_ZERO 244 = 253; // #define KEY_DISPLAY_OFF 245 = 254; // #define KEY_WWAN 246 = 255; // #define KEY_RFKILL 247 = 372; // #define KEY_FAVORITES 364 = 382; // #define KEY_KEYBOARD 374 = 569; // #define KEY_ROTATE_LOCK_TOGGLE 561 = 380; // #define KEY_FULL_SCREEN 372 // Fake keycodes for virtual keys = 92; = 203; = 204; = 205; = 206; = 207; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; alias = ; // For Brazilian ABNT2 alias = ; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/evdev-xkbcommon000066400000000000000000000346341510033435100254220ustar00rootroot00000000000000default xkb_keycodes "evdev" { = 0; = 1; <1> = 2; <2> = 3; <3> = 4; <4> = 5; <5> = 6; <6> = 7; <7> = 8; <8> = 9; <9> = 10; <0> = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24;

= 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 85; <102ND> = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 93; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138;

= 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; // Fake keycodes for virtual keys = 84; = 195; = 196; = 197; = 198; = 199; indicator 0x01 = "Num Lock"; // NUML indicator 0x02 = "Caps Lock"; // CAPSL indicator 0x03 = "Scroll Lock"; // SCROLLL indicator 0x04 = "Compose"; // COMPOSE indicator 0x05 = "Kana"; // KANA indicator 0x06 = "Sleep"; // SLEEP indicator 0x07 = "Suspend"; // SUSPEND indicator 0x08 = "Mute"; // MUTE indicator 0x09 = "Misc"; // MISC indicator 0x0a = "Mail"; // MAIL indicator 0x0b = "Charging"; // CHARGING alias = ; alias = <1>; alias = <2>; alias = <3>; alias = <4>; alias = <5>; alias = <6>; alias = <7>; alias = <8>; alias = <9>; alias = <0>; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; // For Brazilian ABNT2 alias = ; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/high000066400000000000000000000000741510033435100232240ustar00rootroot00000000000000default xkb_keycodes { = 0xffff; = 0xfffffffe; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/merge_modes000066400000000000000000000372641510033435100246060ustar00rootroot00000000000000// WARNING: This file was auto-generated by: scripts/update-merge-modes-tests.py xkb_keycodes "base-default" { = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 93; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 158; = 161; = 164; = 167; = 170; = 173; = 176; = 179; = 182; = 185; = 188; = 191; = 194; = 197; = 200; = 212; = 215; = 218; <1> = 241; <2> = 242; alias = <1>; alias = <2>; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; }; xkb_keycodes "base-augment" { augment = 9; augment = 10; augment = 11; augment = 12; augment = 13; augment = 14; augment = 15; augment = 16; augment = 17; augment = 18; augment = 19; augment = 20; augment = 21; augment = 22; augment = 23; augment = 24; augment = 25; augment = 26; augment = 28; augment = 29; augment = 30; augment = 31; augment = 32; augment = 33; augment = 34; augment = 35; augment = 36; augment = 37; augment = 38; augment = 39; augment = 40; augment = 41; augment = 42; augment = 43; augment = 44; augment = 45; augment = 46; augment = 47; augment = 51; augment = 52; augment = 53; augment = 54; augment = 55; augment = 56; augment = 57; augment = 58; augment = 59; augment = 60; augment = 61; augment = 62; augment = 63; augment = 64; augment = 65; augment = 68; augment = 69; augment = 70; augment = 71; augment = 72; augment = 73; augment = 74; augment = 75; augment = 76; augment = 77; augment = 78; augment = 79; augment = 80; augment = 81; augment = 82; augment = 83; augment = 84; augment = 85; augment = 86; augment = 87; augment = 88; augment = 89; augment = 93; augment = 94; augment = 95; augment = 96; augment = 97; augment = 98; augment = 99; augment = 100; augment = 101; augment = 102; augment = 103; augment = 104; augment = 105; augment = 106; augment = 107; augment = 111; augment = 112; augment = 113; augment = 114; augment = 115; augment = 116; augment = 117; augment = 118; augment = 119; augment = 120; augment = 121; augment = 122; augment = 123; augment = 124; augment = 125; augment = 126; augment = 127; augment = 128; augment = 129; augment = 130; augment = 131; augment = 132; augment = 133; augment = 134; augment = 135; augment = 136; augment = 137; augment = 138; augment = 139; augment = 140; augment = 141; augment = 142; augment = 143; augment = 144; augment = 145; augment = 146; augment = 147; augment = 148; augment = 149; augment = 150; augment = 151; augment = 152; augment = 153; augment = 154; augment = 155; augment = 158; augment = 161; augment = 164; augment = 167; augment = 170; augment = 173; augment = 176; augment = 179; augment = 182; augment = 185; augment = 188; augment = 191; augment = 194; augment = 197; augment = 200; augment = 212; augment = 215; augment = 218; augment <1> = 241; augment <2> = 242; augment alias = <1>; augment alias = <2>; augment indicator 1 = "Caps Lock"; augment indicator 2 = "Num Lock"; augment indicator 3 = "Scroll Lock"; augment indicator 4 = "Compose"; augment indicator 5 = "Kana"; }; xkb_keycodes "base-override" { override = 9; override = 10; override = 11; override = 12; override = 13; override = 14; override = 15; override = 16; override = 17; override = 18; override = 19; override = 20; override = 21; override = 22; override = 23; override = 24; override = 25; override = 26; override = 28; override = 29; override = 30; override = 31; override = 32; override = 33; override = 34; override = 35; override = 36; override = 37; override = 38; override = 39; override = 40; override = 41; override = 42; override = 43; override = 44; override = 45; override = 46; override = 47; override = 51; override = 52; override = 53; override = 54; override = 55; override = 56; override = 57; override = 58; override = 59; override = 60; override = 61; override = 62; override = 63; override = 64; override = 65; override = 68; override = 69; override = 70; override = 71; override = 72; override = 73; override = 74; override = 75; override = 76; override = 77; override = 78; override = 79; override = 80; override = 81; override = 82; override = 83; override = 84; override = 85; override = 86; override = 87; override = 88; override = 89; override = 93; override = 94; override = 95; override = 96; override = 97; override = 98; override = 99; override = 100; override = 101; override = 102; override = 103; override = 104; override = 105; override = 106; override = 107; override = 111; override = 112; override = 113; override = 114; override = 115; override = 116; override = 117; override = 118; override = 119; override = 120; override = 121; override = 122; override = 123; override = 124; override = 125; override = 126; override = 127; override = 128; override = 129; override = 130; override = 131; override = 132; override = 133; override = 134; override = 135; override = 136; override = 137; override = 138; override = 139; override = 140; override = 141; override = 142; override = 143; override = 144; override = 145; override = 146; override = 147; override = 148; override = 149; override = 150; override = 151; override = 152; override = 153; override = 154; override = 155; override = 158; override = 161; override = 164; override = 167; override = 170; override = 173; override = 176; override = 179; override = 182; override = 185; override = 188; override = 191; override = 194; override = 197; override = 200; override = 212; override = 215; override = 218; override <1> = 241; override <2> = 242; override alias = <1>; override alias = <2>; override indicator 1 = "Caps Lock"; override indicator 2 = "Num Lock"; override indicator 3 = "Scroll Lock"; override indicator 4 = "Compose"; override indicator 5 = "Kana"; }; xkb_keycodes "base-replace" { replace = 9; replace = 10; replace = 11; replace = 12; replace = 13; replace = 14; replace = 15; replace = 16; replace = 17; replace = 18; replace = 19; replace = 20; replace = 21; replace = 22; replace = 23; replace = 24; replace = 25; replace = 26; replace = 28; replace = 29; replace = 30; replace = 31; replace = 32; replace = 33; replace = 34; replace = 35; replace = 36; replace = 37; replace = 38; replace = 39; replace = 40; replace = 41; replace = 42; replace = 43; replace = 44; replace = 45; replace = 46; replace = 47; replace = 51; replace = 52; replace = 53; replace = 54; replace = 55; replace = 56; replace = 57; replace = 58; replace = 59; replace = 60; replace = 61; replace = 62; replace = 63; replace = 64; replace = 65; replace = 68; replace = 69; replace = 70; replace = 71; replace = 72; replace = 73; replace = 74; replace = 75; replace = 76; replace = 77; replace = 78; replace = 79; replace = 80; replace = 81; replace = 82; replace = 83; replace = 84; replace = 85; replace = 86; replace = 87; replace = 88; replace = 89; replace = 93; replace = 94; replace = 95; replace = 96; replace = 97; replace = 98; replace = 99; replace = 100; replace = 101; replace = 102; replace = 103; replace = 104; replace = 105; replace = 106; replace = 107; replace = 111; replace = 112; replace = 113; replace = 114; replace = 115; replace = 116; replace = 117; replace = 118; replace = 119; replace = 120; replace = 121; replace = 122; replace = 123; replace = 124; replace = 125; replace = 126; replace = 127; replace = 128; replace = 129; replace = 130; replace = 131; replace = 132; replace = 133; replace = 134; replace = 135; replace = 136; replace = 137; replace = 138; replace = 139; replace = 140; replace = 141; replace = 142; replace = 143; replace = 144; replace = 145; replace = 146; replace = 147; replace = 148; replace = 149; replace = 150; replace = 151; replace = 152; replace = 153; replace = 154; replace = 155; replace = 158; replace = 161; replace = 164; replace = 167; replace = 170; replace = 173; replace = 176; replace = 179; replace = 182; replace = 185; replace = 188; replace = 191; replace = 194; replace = 197; replace = 200; replace = 212; replace = 215; replace = 218; replace <1> = 241; replace <2> = 242; replace alias = <1>; replace alias = <2>; replace indicator 1 = "Caps Lock"; replace indicator 2 = "Num Lock"; replace indicator 3 = "Scroll Lock"; replace indicator 4 = "Compose"; replace indicator 5 = "Kana"; }; xkb_keycodes "update-default" { <1> = 241; // Unchanged <2> = 244; // Changed <3> = 243; // New alias = <1>; // Unchanged alias = <3>; // Changed alias = <3>; // New indicator 1 = "Caps Lock"; // Unchanged indicator 6 = "Num Lock"; // Changed index (free) indicator 5 = "Scroll Lock"; // Changed index (not free) indicator 4 = "XXXX"; // Changed name indicator 7 = "Suspend"; // New }; xkb_keycodes "update-augment" { augment <1> = 241; // Unchanged augment <2> = 244; // Changed augment <3> = 243; // New augment alias = <1>; // Unchanged augment alias = <3>; // Changed augment alias = <3>; // New augment indicator 1 = "Caps Lock"; // Unchanged augment indicator 6 = "Num Lock"; // Changed index (free) augment indicator 5 = "Scroll Lock"; // Changed index (not free) augment indicator 4 = "XXXX"; // Changed name augment indicator 7 = "Suspend"; // New }; xkb_keycodes "update-override" { override <1> = 241; // Unchanged override <2> = 244; // Changed override <3> = 243; // New override alias = <1>; // Unchanged override alias = <3>; // Changed override alias = <3>; // New override indicator 1 = "Caps Lock"; // Unchanged override indicator 6 = "Num Lock"; // Changed index (free) override indicator 5 = "Scroll Lock"; // Changed index (not free) override indicator 4 = "XXXX"; // Changed name override indicator 7 = "Suspend"; // New }; xkb_keycodes "update-replace" { replace <1> = 241; // Unchanged replace <2> = 244; // Changed replace <3> = 243; // New replace alias = <1>; // Unchanged replace alias = <3>; // Changed replace alias = <3>; // New replace indicator 1 = "Caps Lock"; // Unchanged replace indicator 6 = "Num Lock"; // Changed index (free) replace indicator 5 = "Scroll Lock"; // Changed index (not free) replace indicator 4 = "XXXX"; // Changed name replace indicator 7 = "Suspend"; // New }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/recursive000066400000000000000000000003461510033435100243160ustar00rootroot00000000000000default xkb_keycodes "foo" { include "recursive" = 0x100000; }; xkb_keycodes "bar" { include "recursive(baz)" = 0x100001; }; xkb_keycodes "baz" { include "recursive(bar)" = 0x100002; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keycodes/xfree86000066400000000000000000000206671510033435100236060ustar00rootroot00000000000000// "standard" XFree86 codes // It seems that the "default" must be the first entry in the file. default xkb_keycodes "xfree86" { include "xfree86(basic)" = 51; alias = ; = 94; }; xkb_keycodes "basic" { minimum= 8; maximum= 255; = 49; alias = ; // Some geometries use AE00 = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 66; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 50; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 64; = 37; = 65; = 109; = 113; // Microsoft keyboard extra keys = 115; = 116; = 117; = 9; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 95; = 96; = 111; = 92; = 78; = 110; = 114; = 106; = 97; = 99; = 107; = 103; = 105; = 98; = 100; = 104; = 102; = 77; = 112; = 63; = 82; = 79; = 80; = 81; = 86; = 83; = 84; = 85; = 87; = 88; = 89; = 108; = 90; = 91; = 126; = 118; = 119; = 120; = 121; = 122; = 123; // Keys that are generated on Japanese keyboards alias = ; // Hankaku_Zenkaku toggle = 208; // Hiragana_Katakana toggle = 211; // backslash/underscore = 129; // Henkan = 131; // Muhenkan = 133; // Yen = 210; // Alphanumeric mode on macintosh = 209; // Kana mode on macintosh // Keys that are generated on Korean keyboards alias = ; // Hangul Latin toggle alias = ; // Hangul to Hanja conversion // Extended keys that may be generated on "Internet" keyboards. // These are not standardised, hence the meaningless names. // The entries commented out are never generated because the raw codes // in those positions are already used for well-defined keys. = 130; = 132; alias = ; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; // = 156; // = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; // = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; // = 181; // = 182; // = 183; // = 184; = 185; = 186; = 187; = 188; // = 189; // = 190; // = 191; // = 192; // = 193; = 194; = 195; = 196; = 197; // = 198; // = 199; // = 200; // = 201; = 202; // = 203; // = 204; // = 205; // = 206; // = 207; // = 208; // = 209; // = 210; // = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; // = 219; // = 220; // = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; alias = ; = 253; alias = ; = 254; = 255; // MacBooks generate 0x65 for the lower brightness key = 101; // Required for apple/logitech_g15 keyboard = 93; // Codes generated for scancodes 0x59-0x5f, 0x62-0x76 = 157; // = 170; // = 181; // alias = ; = 182; // = 183; // = 184; // = 189; // = 190; // = 191; // = 192; // = 193; // = 198; // = 199; // = 200; // = 201; // = 203; // = 204; // = 205; // = 206; // = 207; // alias = ; // alias = ; // alias = ; // alias = ; // = 219; // = 220; // = 221; // // Solaris compatibility alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; // Other codes never generated. The XFree86 ddx never generates // these codes. // Thus we can use them as fake keys = 8; = 124; // = 125; // = 156; // = 127; // = 128; // indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; alias = ; // For Brazilian ABNT2 alias = ; }; // What keyboard is this? xkb_keycodes "102" { include "xfree86(xfree86)" // There will be warnings from xkbcomp because of multiple definitions. = 122; = 123; = 121; = 118; = 131; = 135; = 119; = 129; = 130; = 134; = 128; = 132; = 120; = 133; = 125; = 124; }; // IBM ThinkPad Z60m/Z60t/Z61m/Z61t xkb_keycodes "thinkpadz60" { include "xfree86(xfree86)" = 227; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/000077500000000000000000000000001510033435100222245ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/basic.xkb000066400000000000000000000003021510033435100240060ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { include "evdev+aliases(qwerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+us" }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/bidi.xkb000066400000000000000000000004751510033435100236470ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <> = 1; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/compat-interpret.xkb000066400000000000000000000012441510033435100262300ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret 0x00000001+AnyOfOrNone(all) { action= NoAction(); }; interpret 0x0000000b+AnyOfOrNone(all) { action= NoAction(); }; interpret Shift_L+AnyOfOrNone(all) { action= NoAction(); }; interpret a+AnyOfOrNone(all) { action= NoAction(); }; interpret adiaeresis+AnyOfOrNone(all) { action= NoAction(); }; interpret U2728+AnyOfOrNone(all) { action= NoAction(); }; interpret U1F3BA+AnyOfOrNone(all) { action= NoAction(); }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/comprehensive-plus-geom.xkb000066400000000000000000001601411510033435100275120ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev+aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; virtual indicator 12 = "Shift Lock"; virtual indicator 13 = "Group 2"; virtual indicator 14 = "Mouse Keys"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= Level2; map[Lock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= Level2; map[NumLock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Number"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Control+Alt]= Level5; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift+Lock]= Level1; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Control]= Level5; map[Shift+Lock+Control]= Level5; map[Shift+Control]= Level6; map[Lock+Control]= Level6; map[Control+LevelThree]= Level7; map[Shift+Lock+Control+LevelThree]= Level7; map[Shift+Control+LevelThree]= Level8; map[Lock+Control+LevelThree]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; level_name[Level4]= "Shift Level3"; level_name[Level5]= "Ctrl"; level_name[Level6]= "Shift Ctrl"; level_name[Level7]= "Level3 Ctrl"; level_name[Level8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level8; map[Shift+Lock+LevelThree+LevelFive]= Level7; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; preserve[Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= Level8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelFive]= Level1; preserve[Shift+Lock+LevelFive]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift+NumLock]= Level1; map[NumLock]= Level2; map[Shift]= Level2; map[LevelThree]= Level3; map[NumLock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= Level2; map[Shift+LevelThree]= Level3; map[Control+Alt]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Alt Base"; level_name[Level3]= "Shift Alt"; level_name[Level4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level4; preserve[Lock]= Lock; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "AltGr Base"; level_name[Level4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock]= Level5; map[Shift+Lock]= Level2; map[Lock+LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Lock"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= Level2; map[NumLock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[NumLock+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Alt Number"; }; }; xkb_compatibility "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Lock+AnyOf(all) { action= ISOLock(modifiers=modMapMods,affect=all); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay1); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay2); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86LogGrabInfo+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret XF86LogWindowTree+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { !allowExplicit; whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { !allowExplicit; whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { !allowExplicit; whichModState= locked; modifiers= Shift; }; indicator "Group 2" { !allowExplicit; groups= 0xfe; }; indicator "Mouse Keys" { indicatorDrivesKeyboard; controls= mouseKeys; }; }; xkb_symbols "pc+us+inet(evdev)+ctrl(nocaps)+compose(rwin)+terminate(ctrl_alt_bksp)" { name[group1]="English (US)"; key { [ Escape ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ 5, percent ] }; key { [ 6, asciicircum ] }; key { [ 7, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { type= "CTRL+ALT", symbols[Group1]= [ BackSpace, BackSpace, NoSymbol, NoSymbol, Terminate_Server ] }; key { [ Tab, ISO_Left_Tab ] }; key { type= "ALPHABETIC", symbols[Group1]= [ q, Q ] }; key { type= "ALPHABETIC", symbols[Group1]= [ w, W ] }; key { type= "ALPHABETIC", symbols[Group1]= [ e, E ] }; key { type= "ALPHABETIC", symbols[Group1]= [ r, R ] }; key { type= "ALPHABETIC", symbols[Group1]= [ t, T ] }; key { type= "ALPHABETIC", symbols[Group1]= [ y, Y ] }; key { type= "ALPHABETIC", symbols[Group1]= [ u, U ] }; key { type= "ALPHABETIC", symbols[Group1]= [ i, I ] }; key { type= "ALPHABETIC", symbols[Group1]= [ o, O ] }; key { type= "ALPHABETIC", symbols[Group1]= [ p, P ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ Return ] }; key { [ Control_L ] }; key { type= "ALPHABETIC", symbols[Group1]= [ a, A ] }; key { type= "ALPHABETIC", symbols[Group1]= [ s, S ] }; key { type= "ALPHABETIC", symbols[Group1]= [ d, D ] }; key { type= "ALPHABETIC", symbols[Group1]= [ f, F ] }; key { type= "ALPHABETIC", symbols[Group1]= [ g, G ] }; key { type= "ALPHABETIC", symbols[Group1]= [ h, H ] }; key { type= "ALPHABETIC", symbols[Group1]= [ j, J ] }; key { type= "ALPHABETIC", symbols[Group1]= [ k, K ] }; key { type= "ALPHABETIC", symbols[Group1]= [ l, L ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ grave, asciitilde ] }; key { [ Shift_L ] }; key { [ backslash, bar ] }; key { type= "ALPHABETIC", symbols[Group1]= [ z, Z ] }; key { type= "ALPHABETIC", symbols[Group1]= [ x, X ] }; key { type= "ALPHABETIC", symbols[Group1]= [ c, C ] }; key { type= "ALPHABETIC", symbols[Group1]= [ v, V ] }; key { type= "ALPHABETIC", symbols[Group1]= [ b, B ] }; key { type= "ALPHABETIC", symbols[Group1]= [ n, N ] }; key { type= "ALPHABETIC", symbols[Group1]= [ m, M ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ slash, question ] }; key { [ Shift_R ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ] }; key { [ Alt_L, Meta_L ] }; key { [ space ] }; key { [ Control_L, Control_L ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ] }; key { [ Num_Lock ] }; key { [ Scroll_Lock ] }; key { [ KP_Home, KP_7 ] }; key { [ KP_Up, KP_8 ] }; key { [ KP_Prior, KP_9 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ] }; key { [ KP_Left, KP_4 ] }; key { [ KP_Begin, KP_5 ] }; key { [ KP_Right, KP_6 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ] }; key { [ KP_End, KP_1 ] }; key { [ KP_Down, KP_2 ] }; key { [ KP_Next, KP_3 ] }; key { [ KP_Insert, KP_0 ] }; key { [ KP_Delete, KP_Decimal ] }; key { [ ISO_Level3_Shift ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ less, greater, bar, brokenbar ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Henkan_Mode ] }; key { [ Hiragana_Katakana ] }; key { [ Muhenkan ] }; key { [ KP_Enter ] }; key { [ Control_R ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ] }; key { type= "PC_ALT_LEVEL2", symbols[Group1]= [ Print, Sys_Req ] }; key { type= "TWO_LEVEL", symbols[Group1]= [ Alt_R, Meta_R ] }; key { [ Linefeed ] }; key { [ Home ] }; key { [ Up ] }; key { [ Prior ] }; key { [ Left ] }; key { [ Right ] }; key { [ End ] }; key { [ Down ] }; key { [ Next ] }; key { [ Insert ] }; key { [ Delete ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { [ KP_Equal ] }; key { [ plusminus ] }; key { type= "PC_CONTROL_LEVEL2", symbols[Group1]= [ Pause, Break ] }; key { [ XF86LaunchA ] }; key { [ KP_Decimal, KP_Decimal ] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ Super_L ] }; key { type= "TWO_LEVEL", symbols[Group1]= [ Multi_key, Multi_key ] }; key { [ Menu ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ SunOpen ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Eject ] }; key { [ XF86Eject, XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ Mode_switch ] }; key { [ NoSymbol, Alt_L ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; key { [ NoSymbol, Hyper_L ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; key { [ Print ] }; key { [ XF86WebCam ] }; key { [ XF86Mail ] }; key { [ XF86Messenger ] }; key { [ XF86Search ] }; key { [ XF86Go ] }; key { [ XF86Finance ] }; key { [ XF86Game ] }; key { [ XF86Shop ] }; key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; modifier_map Control { }; modifier_map Shift { }; modifier_map Shift { }; modifier_map Mod1 { }; modifier_map Control { }; modifier_map Mod2 { }; modifier_map Mod5 { }; modifier_map Control { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod5 { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod4 { }; }; xkb_geometry "pc(pc105)" { width= 470; height= 180; alias = ; alias = ; baseColor= "white"; labelColor= "black"; xfont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; description= "Generic 105"; shape "NORM" { corner= 1, { [ 18, 18 ] }, { [ 2, 1 ], [ 16, 16 ] } }; shape "BKSP" { corner= 1, { [ 38, 18 ] }, { [ 2, 1 ], [ 36, 16 ] } }; shape "TABK" { corner= 1, { [ 28, 18 ] }, { [ 2, 1 ], [ 26, 16 ] } }; shape "BKSL" { corner= 1, { [ 28, 18 ] }, { [ 2, 1 ], [ 26, 16 ] } }; shape "RTRN" { corner= 1, { [ 0, 0 ], [ 28, 0 ], [ 28, 37 ], [ 5, 37 ], [ 5, 18 ], [ 0, 18 ] }, { [ 2, 1 ], [ 26, 1 ], [ 26, 35 ], [ 7, 35 ], [ 7, 16 ], [ 2, 16 ] }, approx= { [ 5, 0 ], [ 28, 37 ] } }; shape "CAPS" { corner= 1, { [ 33, 18 ] }, { [ 2, 1 ], [ 31, 16 ] } }; shape "LFSH" { corner= 1, { [ 25, 18 ] }, { [ 2, 1 ], [ 23, 16 ] } }; shape "RTSH" { corner= 1, { [ 50, 18 ] }, { [ 2, 1 ], [ 48, 16 ] } }; shape "MODK" { corner= 1, { [ 27, 18 ] }, { [ 2, 1 ], [ 25, 16 ] } }; shape "SMOD" { corner= 1, { [ 23, 18 ] }, { [ 2, 1 ], [ 21, 16 ] } }; shape "SPCE" { corner= 1, { [ 113, 18 ] }, { [ 2, 1 ], [ 111, 16 ] } }; shape "KP0" { corner= 1, { [ 37, 18 ] }, { [ 2, 1 ], [ 35, 16 ] } }; shape "KPAD" { corner= 1, { [ 18, 37 ] }, { [ 2, 1 ], [ 16, 35 ] } }; shape "LEDS" { { [ 75, 20 ] } }; shape "LED" { { [ 5, 1 ] } }; section "Function" { key.color= "grey20"; priority= 7; top= 22; left= 19; width= 351; height= 19; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 20, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 11, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 11, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 8, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" } }; }; }; // End of "Function" section section "Alpha" { key.color= "white"; priority= 8; top= 61; left= 19; width= 287; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "BKSP", 1, color="grey20" } }; }; row { top= 20; left= 1; keys { { , "TABK", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "RTRN", 1, color="grey20" } }; }; row { top= 39; left= 1; keys { { , "CAPS", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 58; left= 1; keys { { , "LFSH", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "RTSH", 1, color="grey20" } }; }; row { top= 77; left= 1; keys { { , "MODK", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SPCE", 1 }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" } }; }; }; // End of "Alpha" section section "Editing" { key.color= "grey20"; priority= 9; top= 61; left= 312; width= 58; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 20; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 58; left= 20; keys { { , "NORM", 1 } }; }; row { top= 77; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; }; // End of "Editing" section section "Keypad" { key.color= "grey20"; priority= 10; top= 61; left= 376; width= 77; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 20; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "KPAD", 1 } }; }; row { top= 39; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" } }; }; row { top= 58; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "KPAD", 1 } }; }; row { top= 77; left= 1; keys { { , "KP0", 1, color="white" }, { , "NORM", 1, color="white" } }; }; }; // End of "Keypad" section solid "LedPanel" { top= 22; left= 377; priority= 0; color= "grey10"; shape= "LEDS"; }; indicator "Num Lock" { top= 37; left= 382; priority= 1; onColor= "green"; offColor= "green30"; shape= "LED"; }; indicator "Caps Lock" { top= 37; left= 407; priority= 2; onColor= "green"; offColor= "green30"; shape= "LED"; }; indicator "Scroll Lock" { top= 37; left= 433; priority= 3; onColor= "green"; offColor= "green30"; shape= "LED"; }; text "NumLockLabel" { top= 25; left= 378; priority= 4; width= 19.8; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Num\nLock"; }; text "CapsLockLabel" { top= 25; left= 403; priority= 5; width= 26.4; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Caps\nLock"; }; text "ScrollLockLabel" { top= 25; left= 428; priority= 6; width= 39.6; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Scroll\nLock"; }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/digits.xkb000066400000000000000000000031051510033435100242140ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; <0> = 10; <1> = 11; <2> = 12; = 20; = 21; = 22; }; xkb_types { type "FOUR_LEVEL" { modifiers= Shift+Control; map[Shift]= 2; map[Control]= 3; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret 0+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret 1+AnyOfOrNone(all) { action= LockGroup(group=-1); }; interpret 0x00000001+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret 2+AnyOfOrNone(all) { action= LockGroup(group=-2); }; interpret 0x00000002+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret 3+AnyOfOrNone(all) { action= LockGroup(group=-3); }; interpret 0x00000003+AnyOfOrNone(all) { action= LockGroup(group=3); }; interpret Any+AnyOfOrNone(all) { action= LockGroup(group=4); }; }; xkb_symbols { key <0> { [ 0, NoSymbol, NoSymbol ] }; key <1> { [ 1, 0x00000001, 0x00000001 ] }; key <2> { [ 2, 0x00000002, 0x00000002 ] }; key { [ 3, NoSymbol, NoSymbol ] }; key { [ 0x00000004, NoSymbol, NoSymbol ] }; key { [ 0x00000005, NoSymbol, NoSymbol ] }; modifier_map Shift { <0>, }; modifier_map Lock { }; modifier_map Control { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/divide-by-zero.xkb000066400000000000000000000004771510033435100255730ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { = 1; }; xkb_types { virtual_modifiers NumLock; }; xkb_compatibility { virtual_modifiers NumLock; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=(1/0),y=+1); }; }; xkb_symbols { key { [ NoSymbol, Hyper_L ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/empty-compound-statements.xkb000066400000000000000000000051571510033435100301070ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32;

= 33; = 38; = 39; = 40; = 41; = 42; = 43; = 52; = 53; = 54; = 55; = 56; = 57; = 58; indicator 1 = "xxx"; indicator 2 = "yyy"; }; xkb_types { virtual_modifiers M1,M2; type "t1" { modifiers= none; }; type "t2" { modifiers= Shift; map[Shift]= 2; }; }; xkb_compatibility { virtual_modifiers M1,M2; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret q+AnyOfOrNone(all) { action= NoAction(); }; interpret w+AnyOfOrNone(all) { repeat= True; }; indicator "yyy" { modifiers= Shift; }; }; xkb_symbols { key { [ q ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=none) ] }; key { type= "t1", symbols[1]= [ e ] }; key { symbols[1]= [ NoSymbol ], symbols[2]= [ u ] }; key { [ i ] }; key { virtualMods= M1 }; key { repeat= No }; key { type= "t2", symbols[1]= [ NoSymbol, NoSymbol ] }; key { type= "t2", symbols[1]= [ NoSymbol, NoSymbol ] }; key { type[1]= "t1", type[2]= "t2", symbols[1]= [ NoSymbol ], symbols[2]= [ NoSymbol, NoSymbol ] }; key { virtualMods= M1 }; key { virtualMods= M2 }; key { virtualMods= none }; key { type= "t2", virtualMods= none, symbols[1]= [ NoSymbol, NoSymbol ] }; key { type= "t1", virtualMods= none, symbols[1]= [ NoSymbol ] }; key { type[1]= "t1", type[2]= "t2", virtualMods= none, symbols[1]= [ NoSymbol ], symbols[2]= [ NoSymbol, NoSymbol ] }; modifier_map Shift { }; modifier_map Lock { }; modifier_map Control { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/empty-symbol-decl.xkb000066400000000000000000000004751510033435100263060ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { include "evdev+aliases(qwerty)" }; xkb_types { include "complete" }; xkb_compat { include "complete" }; xkb_symbols "sym" { // This syntax caused the crash in parser before, and is not accepted // anymore. key { , [Space] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/escape-sequences.xkb000066400000000000000000000024001510033435100261570ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "La_paix_est_la_seule_bataille_qui_vaille_la_peine_d___tre_men_e__" { minimum = 1; maximum = 255; <> = 1; indicator 1 = "\n⌨️"; indicator 2 = "surrogates: � �"; indicator 3 = "noncharacters: ﷐ ﷯ ￾ ￿"; indicator 4 = "noncharacters: 🿾 🿿 􏿾 􏿿"; indicator 5 = "out of range: a "; indicator 6 = "invalid: a A b c e "; indicator 7 = "invalid: x\0042 y "; indicator 8 = "invalid: x y"; indicator 9 = " "; }; xkb_types "1__7___" { type "%1🎺✨🕊️\0014" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Où ils ont fait un \0042désert\0042, \0033ils disent qu’ils \nont fait la \0042paix\0042.\0010\n"; level_name[2]= "Science sans conscience n’est que rui\\ne\n de l’âme.\0015"; }; }; xkb_compatibility "Le_c_ur_a___ses_raisons_que_la_raison_ne_con_na_t_point" { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; indicator "\n⌨️" { modifiers= Shift; }; }; xkb_symbols "La_libert__commence_o__l__ignorance_finit_" { name[1]="\n"; name[2]="\00427"; key <> { type= "%1🎺✨🕊️\0014", symbols[1]= [ a, A ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/explicit-actions.xkb000066400000000000000000000263311510033435100262160ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "(unnamed)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 105; = 108; = 133; = 134; = 135; = 203; = 204; = 205; = 206; = 207; }; xkb_types "(unnamed)" { virtual_modifiers NumLock,Alt,LevelThree,ScrollLock,LevelFive,Super,AltGr,Meta,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr"; level_name[4]= "Shift AltGr"; }; type "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK" { modifiers= Shift+Lock+NumLock+LevelThree+LevelFive; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[LevelFive]= 5; map[Shift+LevelFive]= 6; preserve[Shift+LevelFive]= Shift; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[NumLock]= 5; map[Shift+NumLock]= 6; preserve[Shift+NumLock]= Shift; map[NumLock+LevelThree]= 7; map[Shift+NumLock+LevelThree]= 8; map[Shift+NumLock+LevelFive]= 2; map[NumLock+LevelThree+LevelFive]= 3; map[Shift+NumLock+LevelThree+LevelFive]= 4; map[Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; map[Lock+LevelFive]= 5; map[Shift+Lock+LevelFive]= 6; map[Lock+LevelThree+LevelFive]= 7; map[Shift+Lock+LevelThree+LevelFive]= 8; map[Lock+NumLock]= 5; map[Shift+Lock+NumLock]= 6; map[Lock+NumLock+LevelThree]= 7; map[Shift+Lock+NumLock+LevelThree]= 8; map[Lock+NumLock+LevelFive]= 2; map[Lock+NumLock+LevelThree+LevelFive]= 4; map[Shift+Lock+NumLock+LevelThree+LevelFive]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr"; level_name[4]= "Shift AltGr"; }; }; xkb_compatibility "(unnamed)" { virtual_modifiers NumLock,Alt,LevelThree,ScrollLock,LevelFive,Super,AltGr,Meta,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret Shift_R+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; }; xkb_symbols "(unnamed)" { name[1]="English (US)"; name[2]="Czech"; name[3]="German (Neo 2)"; key { //// repeat=Yes is set with the default *interpretation*, but //// using explicit actions makes the key keep the initial value, //// i.e. repeat=No. //repeat= Yes, symbols[1]= [ t, T ], //actions[1]= [ NoAction(), NoAction() ], symbols[2]= [ Cyrillic_ie, Cyrillic_IE ], actions[2]= [ NoAction(), NoAction() ], symbols[3]= [ w, W ]//, //actions[3]= [ NoAction(), NoAction() ] }; key { type[3]= "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK", symbols[1]= [ y, Y ], symbols[2]= [ z, Z, leftarrow, yen ], symbols[3]= [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] }; key { type[3]= "TWO_LEVEL", symbols[1]= [ Shift_L ], symbols[2]= [ Shift_L ], symbols[3]= [ Shift_L, Caps_Lock ] }; //// This should set the key’s EXPLICIT_INTERP explicit flag and //// the group 2 explicit_actions, but it should still allow to //// interpret the keysyms in groups 1 and 3. key { type[1]= "ONE_LEVEL", type[2]= "TWO_LEVEL", type[3]= "TWO_LEVEL", //repeat= No, symbols[1]= [ Shift_L ], //actions[1]= [ SetMods(modifiers=Shift,clearLocks) ], symbols[2]= [ ISO_Level3_Shift, Multi_key ], actions[2]= [ SetMods(modifiers=LevelThree), NoAction() ], symbols[3]= [ ISO_Level5_Shift, ISO_Level3_Shift ]//, //actions[3]= [ SetMods(modifiers=LevelFive,clearLocks), SetMods(modifiers=LevelThree,clearLocks) ] }; key { type= "ONE_LEVEL", //// The following fields are added, because they are set via //// compatibility interpretations, but using explicit actions //// disable them. //repeat= No, //virtualMods= LevelThree, symbols[1]= [ ISO_Level3_Shift ], //actions[1]= [ SetMods(modifiers=LevelThree,clearLocks) ], symbols[2]= [ ISO_Level3_Shift ], actions[2]= [ SetMods(modifiers=LevelThree) ], symbols[3]= [ ISO_Level3_Shift ]//, //actions[3]= [ SetMods(modifiers=LevelThree,clearLocks) ] }; key { symbols[1]= [ less, greater, bar, brokenbar ], symbols[2]= [ backslash, bar, slash, NoSymbol ], symbols[3]= [ ISO_Level5_Shift ] }; key { type[1]= "TWO_LEVEL", type[2]= "ONE_LEVEL", type[3]= "ONE_LEVEL", symbols[1]= [ Alt_R, Meta_R ], symbols[2]= [ ISO_Level3_Shift ], symbols[3]= [ ISO_Level5_Shift ] }; key { [ ISO_Next_Group, Menu ] }; key { type= "ONE_LEVEL", symbols[1]= [ ISO_Level5_Shift ], symbols[2]= [ ISO_Level5_Shift ], symbols[3]= [ ISO_Level5_Shift ] }; key { [ NoSymbol, Alt_L ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; modifier_map Shift { , }; modifier_map Mod1 { , , }; modifier_map Mod3 { }; modifier_map Mod5 { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/extended-layout-indices-v1.xkb000066400000000000000000000024251510033435100300100ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; = 1; = 2; = 3; indicator 1 = "a"; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret a+AnyOfOrNone(all) { action= LockControls(controls=none,affect=neither); }; indicator "a" { groups= 0xfffffffa; }; }; xkb_symbols { name[1]="G1"; key { symbols[1]= [ a ], symbols[2]= [ a ], symbols[3]= [ a ], symbols[4]= [ a ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ LockControls(controls=none,affect=neither) ], symbols[2]= [ NoSymbol ], actions[2]= [ NoAction() ], symbols[3]= [ NoSymbol ], actions[3]= [ LockControls(controls=none,affect=neither) ], symbols[4]= [ NoSymbol ], actions[4]= [ LockControls(controls=none,affect=neither) ] }; key { symbols[1]= [ 1 ], symbols[2]= [ 2 ], symbols[3]= [ 3 ], symbols[4]= [ 4 ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/extended-layout-indices-v2.xkb000066400000000000000000000030351510033435100300070ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; = 1; = 2; = 3; indicator 1 = "a"; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret a+AnyOfOrNone(all) { action= SetGroup(group=5); }; indicator "a" { groups= 0xfffffffa; }; }; xkb_symbols { name[1]="G1"; name[5]="G5"; key { symbols[1]= [ a ], symbols[2]= [ a ], symbols[3]= [ a ], symbols[4]= [ a ], symbols[5]= [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ LatchGroup(group=-5) ], symbols[2]= [ NoSymbol ], actions[2]= [ NoAction() ], symbols[3]= [ NoSymbol ], actions[3]= [ LatchGroup(group=-5) ], symbols[4]= [ NoSymbol ], actions[4]= [ LatchGroup(group=-5) ], symbols[5]= [ NoSymbol ], actions[5]= [ LockGroup(group=5) ] }; key { symbols[1]= [ 1 ], symbols[2]= [ 2 ], symbols[3]= [ 3 ], symbols[4]= [ 4 ], symbols[5]= [ 5 ], symbols[6]= [ 6 ], symbols[7]= [ 7 ], symbols[8]= [ 8 ], symbols[9]= [ 9 ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/group-index-names-1.xkb000066400000000000000000000014651510033435100264400ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <> = 1; indicator 1 = "1"; indicator 2 = "2"; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret a+AnyOfOrNone(all) { action= SetGroup(group=1); }; interpret b+AnyOfOrNone(all) { action= SetGroup(group=-2); }; interpret c+AnyOfOrNone(all) { action= SetGroup(group=+3); }; indicator "1" { groups= 0x08; }; indicator "2" { groups= 0xfffffffe; }; }; xkb_symbols { name[1]="1"; name[2]="2"; name[3]="3"; name[4]="4"; key <> { groupsRedirect= 4, symbols[1]= [ a ], symbols[2]= [ b ], symbols[3]= [ c ], symbols[4]= [ d ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/group-index-names-2.xkb000066400000000000000000000034721510033435100264410ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <> = 1; indicator 1 = "1"; indicator 2 = "2"; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret a+AnyOfOrNone(all) { action= SetGroup(group=32); }; interpret b+AnyOfOrNone(all) { action= SetGroup(group=-32); }; interpret c+AnyOfOrNone(all) { action= SetGroup(group=+32); }; indicator "1" { groups= 0x80000000; }; indicator "2" { groups= 0x7fffffff; }; }; xkb_symbols { name[1]="1"; name[4]="4"; name[5]="5"; name[8]="8"; name[32]="32"; key <> { groupsRedirect= 32, symbols[1]= [ a ], symbols[2]= [ a ], symbols[3]= [ a ], symbols[4]= [ b ], symbols[5]= [ c ], symbols[6]= [ a ], symbols[7]= [ a ], symbols[8]= [ d ], symbols[9]= [ a ], symbols[10]= [ a ], symbols[11]= [ a ], symbols[12]= [ a ], symbols[13]= [ a ], symbols[14]= [ a ], symbols[15]= [ a ], symbols[16]= [ a ], symbols[17]= [ a ], symbols[18]= [ a ], symbols[19]= [ a ], symbols[20]= [ a ], symbols[21]= [ a ], symbols[22]= [ a ], symbols[23]= [ a ], symbols[24]= [ a ], symbols[25]= [ a ], symbols[26]= [ a ], symbols[27]= [ a ], symbols[28]= [ a ], symbols[29]= [ a ], symbols[30]= [ a ], symbols[31]= [ a ], symbols[32]= [ e ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/high-keycodes-1.xkb000066400000000000000000000006001510033435100256070ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 4294967294; <> = 4294967294; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key <> { [ a ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/high-keycodes-2.xkb000066400000000000000000000005601510033435100256150ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; <> = 8; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key <> { [ a ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/high-keycodes-3.xkb000066400000000000000000000007271510033435100256230ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 4294967294; = 4294967293; = 4294967294; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key { [ a ] }; key { [ b ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/high-keycodes-4.xkb000066400000000000000000000013031510033435100256130ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 4294967294; = 15; = 4095; = 8192; = 16384; = 4294967294; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key { [ a ] }; key { [ b ] }; key { [ c ] }; key { [ d ] }; key { [ e ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/host-no-pretty.xkb000066400000000000000000001200151510033435100256450ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev_aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; indicator 12 = "Shift Lock"; indicator 13 = "Group 2"; indicator 14 = "Mouse Keys"; alias = ; alias

= ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 1; preserve[Lock]= Lock; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= 2; level_name[1]= "Base"; level_name[2]= "Shift+Alt"; }; type "PC_SUPER_LEVEL2" { modifiers= Mod4; map[Mod4]= 2; level_name[1]= "Base"; level_name[2]= "Super"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= 2; level_name[1]= "Base"; level_name[2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= 2; level_name[1]= "Base"; level_name[2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= 2; level_name[1]= "Base"; level_name[2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= 2; level_name[1]= "Base"; level_name[2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= 2; level_name[1]= "Base"; level_name[2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= 2; level_name[1]= "Base"; level_name[2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= 2; preserve[Shift]= Shift; map[LevelThree]= 3; map[Shift+LevelThree]= 4; preserve[Shift+LevelThree]= Shift; map[Control+Alt]= 5; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+Lock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Control]= 5; map[Shift+Lock+Control]= 5; map[Shift+Control]= 6; map[Lock+Control]= 6; map[Control+LevelThree]= 7; map[Shift+Lock+Control+LevelThree]= 7; map[Shift+Control+LevelThree]= 8; map[Lock+Control+LevelThree]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "3"; level_name[4]= "Shift 3"; level_name[5]= "Ctrl"; level_name[6]= "Shift Ctrl"; level_name[7]= "3 Ctrl"; level_name[8]= "Shift 3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 8; map[Shift+Lock+LevelThree+LevelFive]= 7; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; preserve[Lock+LevelFive]= Lock; map[Shift+Lock+LevelFive]= 6; preserve[Shift+Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= 8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= 2; map[Shift]= 2; map[LevelThree]= 3; map[NumLock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= 2; map[Shift+LevelThree]= 3; map[Control+Alt]= 4; level_name[1]= "Base"; level_name[2]= "Alt Base"; level_name[3]= "Shift Alt"; level_name[4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 4; preserve[Lock]= Lock; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr Base"; level_name[4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock]= 5; map[Shift+Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Lock"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= 2; map[NumLock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[NumLock+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Alt Number"; }; }; xkb_compatibility "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret 0xfe02+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret 0xffe6+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret 0xff7f+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret 0xfe03+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret 0xfe04+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret 0xfe05+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret 0xffe9+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffea+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffe7+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffe8+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffeb+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffec+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffed+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffee+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xff14+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret 0xfe11+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret 0xfe12+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret 0xfe13+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= LockMods(modifiers=LevelFive); }; interpret 0xff7e+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret 0xfe03+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret 0xfe04+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret 0xfe05+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret 0xfe06+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret 0xfe08+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret 0xfe0a+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret 0xfe0c+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret 0xfe0e+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret 0xffb1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret 0xff9c+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret 0xffb2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret 0xff99+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret 0xffb3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret 0xff9b+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret 0xffb4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret 0xff96+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret 0xffb6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret 0xff98+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret 0xffb7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret 0xff95+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret 0xffb8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret 0xff97+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret 0xffb9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret 0xff9a+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret 0xffb5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret 0xff9d+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret 0xff92+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret 0xffaf+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret 0xff93+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret 0xffaa+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret 0xff94+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret 0xffad+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret 0xffac+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret 0xffab+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret 0xffb0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret 0xff9e+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret 0xffae+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret 0xff9f+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret 0xffd6+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret 0xffd7+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret 0xffd8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret 0xffda+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret 0xffdc+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret 0xffde+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret 0xffe0+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret 0xfee8+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret 0xfee9+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret 0xfeea+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret 0xfeeb+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret 0xfeee+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret 0xfeef+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret 0xfef0+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret 0xfef1+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret 0xfef4+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret 0xfef5+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret 0xfef6+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret 0xfef7+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret 0xfef9+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret 0xfefa+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret 0xfefb+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret 0xfefc+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret 0xfe70+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret 0xfe71+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret 0xfe72+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret 0xfe73+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret 0xfe74+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret 0xfe75+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret 0xfe76+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret 0xfe77+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret 0xfe78+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret 0xfe79+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret 0xfe7a+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret 0xfed5+AnyOfOrNone(all) { action= Terminate(); }; interpret 0xffe9+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret 0xffea+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret 0xffe7+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret 0xffe8+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret 0xffeb+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret 0xffec+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret 0xffed+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret 0xffee+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret 0xffe1+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret 0x1008fe01+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret 0x1008fe02+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret 0x1008fe03+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret 0x1008fe04+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret 0x1008fe05+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret 0x1008fe06+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret 0x1008fe07+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret 0x1008fe08+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret 0x1008fe09+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret 0x1008fe0a+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret 0x1008fe0b+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret 0x1008fe0c+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret 0x1008fe25+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret 0x1008fe24+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret 0x1008fe22+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret 0x1008fe23+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret 0xfe11+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret 0xfe12+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret 0xfe13+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret 0xffe5+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; indicator "Group 2" { groups= 0xfe; }; indicator "Mouse Keys" { controls= MouseKeys; }; }; xkb_symbols "pc_us_pt_2_us_3_inet(evdev)_group(shift_caps_toggle)_compose(ralt)" { name[1]="English (US)"; name[2]="Portuguese"; name[3]="English (US)"; key { [ 0xff1b ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x31, 0x21 ], symbols[2]= [ 0x31, 0x21, 0xb9, 0xa1 ], symbols[3]= [ 0x31, 0x21 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x32, 0x40 ], symbols[2]= [ 0x32, 0x22, 0x40, 0xac3 ], symbols[3]= [ 0x32, 0x40 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x33, 0x23 ], symbols[2]= [ 0x33, 0x23, 0xa3, 0xa3 ], symbols[3]= [ 0x33, 0x23 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x34, 0x24 ], symbols[2]= [ 0x34, 0x24, 0xa7, 0x24 ], symbols[3]= [ 0x34, 0x24 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x35, 0x25 ], symbols[2]= [ 0x35, 0x25, 0xbd, 0xac4 ], symbols[3]= [ 0x35, 0x25 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x36, 0x5e ], symbols[2]= [ 0x36, 0x26, 0xac, 0xac5 ], symbols[3]= [ 0x36, 0x5e ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x37, 0x26 ], symbols[2]= [ 0x37, 0x2f, 0x7b, 0xac6 ], symbols[3]= [ 0x37, 0x26 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x38, 0x2a ], symbols[2]= [ 0x38, 0x28, 0x5b, 0xac9 ], symbols[3]= [ 0x38, 0x2a ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x39, 0x28 ], symbols[2]= [ 0x39, 0x29, 0x5d, 0xb1 ], symbols[3]= [ 0x39, 0x28 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x30, 0x29 ], symbols[2]= [ 0x30, 0x3d, 0x7d, 0xb0 ], symbols[3]= [ 0x30, 0x29 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x2d, 0x5f ], symbols[2]= [ 0x27, 0x3f, 0x5c, 0xbf ], symbols[3]= [ 0x2d, 0x5f ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x3d, 0x2b ], symbols[2]= [ 0xebf, 0xec4, 0xfe5b, 0xfe5c ], symbols[3]= [ 0x3d, 0x2b ] }; key { [ 0xff08, 0xff08 ] }; key { [ 0xff09, 0xfe20 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x71, 0x51 ], symbols[2]= [ 0x71, 0x51, 0x40, 0x7d9 ], symbols[3]= [ 0x71, 0x51 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x77, 0x57 ], symbols[2]= [ 0x77, 0x57, 0x1b3, 0x1a3 ], symbols[3]= [ 0x77, 0x57 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x65, 0x45 ], symbols[2]= [ 0x65, 0x45, 0x20ac, 0xa2 ], symbols[3]= [ 0x65, 0x45 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x72, 0x52 ], symbols[2]= [ 0x72, 0x52, 0xb6, 0xae ], symbols[3]= [ 0x72, 0x52 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x74, 0x54 ], symbols[2]= [ 0x74, 0x54, 0x3bc, 0x3ac ], symbols[3]= [ 0x74, 0x54 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x79, 0x59 ], symbols[2]= [ 0x79, 0x59, 0x8fb, 0xa5 ], symbols[3]= [ 0x79, 0x59 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x75, 0x55 ], symbols[2]= [ 0x75, 0x55, 0x8fe, 0x8fc ], symbols[3]= [ 0x75, 0x55 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x69, 0x49 ], symbols[2]= [ 0x69, 0x49, 0x8fd, 0x2b9 ], symbols[3]= [ 0x69, 0x49 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x6f, 0x4f ], symbols[2]= [ 0x6f, 0x4f, 0xf8, 0xd8 ], symbols[3]= [ 0x6f, 0x4f ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x70, 0x50 ], symbols[2]= [ 0x70, 0x50, 0xfe, 0xde ], symbols[3]= [ 0x70, 0x50 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x5b, 0x7b ], symbols[2]= [ 0x2b, 0x2a, 0xfe57, 0xfe58 ], symbols[3]= [ 0x5b, 0x7b ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x5d, 0x7d ], symbols[2]= [ 0xfe51, 0xfe50, 0xfe53, 0xfe54 ], symbols[3]= [ 0x5d, 0x7d ] }; key { [ 0xff0d ] }; key { [ 0xffe3 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x61, 0x41 ], symbols[2]= [ 0x61, 0x41, 0xe6, 0xc6 ], symbols[3]= [ 0x61, 0x41 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x73, 0x53 ], symbols[2]= [ 0x73, 0x53, 0xdf, 0xa7 ], symbols[3]= [ 0x73, 0x53 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x64, 0x44 ], symbols[2]= [ 0x64, 0x44, 0xf0, 0xd0 ], symbols[3]= [ 0x64, 0x44 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x66, 0x46 ], symbols[2]= [ 0x66, 0x46, 0x1f0, 0xaa ], symbols[3]= [ 0x66, 0x46 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x67, 0x47 ], symbols[2]= [ 0x67, 0x47, 0x3bf, 0x3bd ], symbols[3]= [ 0x67, 0x47 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x68, 0x48 ], symbols[2]= [ 0x68, 0x48, 0x2b1, 0x2a1 ], symbols[3]= [ 0x68, 0x48 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x6a, 0x4a ], symbols[2]= [ 0x6a, 0x4a, 0xfe61, 0xfe62 ], symbols[3]= [ 0x6a, 0x4a ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x6b, 0x4b ], symbols[2]= [ 0x6b, 0x4b, 0x3a2, 0x26 ], symbols[3]= [ 0x6b, 0x4b ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x6c, 0x4c ], symbols[2]= [ 0x6c, 0x4c, 0x1b3, 0x1a3 ], symbols[3]= [ 0x6c, 0x4c ] }; key { type[2]= "FOUR_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x3b, 0x3a ], symbols[2]= [ 0xe7, 0xc7, 0xfe51, 0xfe59 ], symbols[3]= [ 0x3b, 0x3a ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x27, 0x22 ], symbols[2]= [ 0xec7, 0xaa, 0xfe52, 0xfe5a ], symbols[3]= [ 0x27, 0x22 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x60, 0x7e ], symbols[2]= [ 0x5c, 0x7c, 0xac, 0xac ], symbols[3]= [ 0x60, 0x7e ] }; key { [ 0xffe1 ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x5c, 0x7c ], symbols[2]= [ 0xfe53, 0xfe52, 0xfe50, 0xfe55 ], symbols[3]= [ 0x5c, 0x7c ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x7a, 0x5a ], symbols[2]= [ 0x7a, 0x5a, 0xebf, 0x3c ], symbols[3]= [ 0x7a, 0x5a ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x78, 0x58 ], symbols[2]= [ 0x78, 0x58, 0xec4, 0x3e ], symbols[3]= [ 0x78, 0x58 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x63, 0x43 ], symbols[2]= [ 0x63, 0x43, 0xa2, 0xa9 ], symbols[3]= [ 0x63, 0x43 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x76, 0x56 ], symbols[2]= [ 0x76, 0x56, 0xad2, 0xad0 ], symbols[3]= [ 0x76, 0x56 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x62, 0x42 ], symbols[2]= [ 0x62, 0x42, 0xad3, 0xad1 ], symbols[3]= [ 0x62, 0x42 ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x6e, 0x4e ], symbols[2]= [ 0x6e, 0x4e, 0x6e, 0x4e ], symbols[3]= [ 0x6e, 0x4e ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ 0x6d, 0x4d ], symbols[2]= [ 0x6d, 0x4d, 0xb5, 0xec7 ], symbols[3]= [ 0x6d, 0x4d ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x2c, 0x3c ], symbols[2]= [ 0x2c, 0x3b, 0x8a3, 0xd7 ], symbols[3]= [ 0x2c, 0x3c ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x2e, 0x3e ], symbols[2]= [ 0x2e, 0x3a, 0xb7, 0xf7 ], symbols[3]= [ 0x2e, 0x3e ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0x2f, 0x3f ], symbols[2]= [ 0x2d, 0x5f, 0xfe60, 0xfe56 ], symbols[3]= [ 0x2f, 0x3f ] }; key { [ 0xffe2 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffaa, 0xffaa, 0xffaa, 0xffaa, 0x1008fe21 ] }; key { [ 0xffe9, 0xffe7 ] }; key { [ 0x20 ] }; key { [ 0xffe5, 0xfe08 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffbe, 0xffbe, 0xffbe, 0xffbe, 0x1008fe01 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffbf, 0xffbf, 0xffbf, 0xffbf, 0x1008fe02 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0x1008fe03 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc1, 0xffc1, 0xffc1, 0xffc1, 0x1008fe04 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc2, 0xffc2, 0xffc2, 0xffc2, 0x1008fe05 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc3, 0xffc3, 0xffc3, 0xffc3, 0x1008fe06 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc4, 0xffc4, 0xffc4, 0xffc4, 0x1008fe07 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc5, 0xffc5, 0xffc5, 0xffc5, 0x1008fe08 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc6, 0xffc6, 0xffc6, 0xffc6, 0x1008fe09 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc7, 0xffc7, 0xffc7, 0xffc7, 0x1008fe0a ] }; key { [ 0xff7f ] }; key { [ 0xff14 ] }; key { [ 0xff95, 0xffb7 ] }; key { [ 0xff97, 0xffb8 ] }; key { [ 0xff9a, 0xffb9 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffad, 0xffad, 0xffad, 0xffad, 0x1008fe23 ] }; key { [ 0xff96, 0xffb4 ] }; key { [ 0xff9d, 0xffb5 ] }; key { [ 0xff98, 0xffb6 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffab, 0xffab, 0xffab, 0xffab, 0x1008fe22 ] }; key { [ 0xff9c, 0xffb1 ] }; key { [ 0xff99, 0xffb2 ] }; key { [ 0xff9b, 0xffb3 ] }; key { [ 0xff9e, 0xffb0 ] }; key { [ 0xff9f, 0xffae ] }; key { type= "ONE_LEVEL", symbols[1]= [ 0xfe03 ] }; key { type= "FOUR_LEVEL", symbols[1]= [ 0x3c, 0x3e, 0x7c, 0xa6 ], symbols[2]= [ 0x3c, 0x3e, 0x5c, 0x5c ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc8, 0xffc8, 0xffc8, 0xffc8, 0x1008fe0b ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc9, 0xffc9, 0xffc9, 0xffc9, 0x1008fe0c ] }; key { [ 0xff26 ] }; key { [ 0xff25 ] }; key { [ 0xff23 ] }; key { [ 0xff27 ] }; key { [ 0xff22 ] }; key { [ 0xff8d ] }; key { [ 0xffe4 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffaf, 0xffaf, 0xffaf, 0xffaf, 0x1008fe20 ] }; key { type= "PC_ALT_LEVEL2", symbols[1]= [ 0xff61, 0xff15 ] }; key { type[1]= "TWO_LEVEL", type[2]= "ONE_LEVEL", symbols[1]= [ 0xff20, 0xff20 ], symbols[2]= [ 0xfe03 ] }; key { [ 0xff0a ] }; key { [ 0xff50 ] }; key { [ 0xff52 ] }; key { [ 0xff55 ] }; key { [ 0xff51 ] }; key { [ 0xff53 ] }; key { [ 0xff57 ] }; key { [ 0xff54 ] }; key { [ 0xff56 ] }; key { [ 0xff63 ] }; key { [ 0xffff ] }; key { [ 0x1008ff12 ] }; key { [ 0x1008ff11 ] }; key { [ 0x1008ff13 ] }; key { [ 0x1008ff2a ] }; key { [ 0xffbd ] }; key { [ 0xb1 ] }; key { type= "PC_CONTROL_LEVEL2", symbols[1]= [ 0xff13, 0xff6b ] }; key { [ 0x1008ff4a ] }; key { [ 0xffae, 0xffae ] }; key { [ 0xff31 ] }; key { [ 0xff34 ] }; key { [ 0xffeb ] }; key { [ 0xffec ] }; key { [ 0xff67 ] }; key { [ 0xff69 ] }; key { [ 0xff66 ] }; key { [ 0x1005ff70 ] }; key { [ 0xff65 ] }; key { [ 0x1005ff71 ] }; key { [ 0x1008ff57 ] }; key { [ 0x1008ff6b ] }; key { [ 0x1008ff6d ] }; key { [ 0xff68 ] }; key { [ 0x1008ff58 ] }; key { [ 0xff6a ] }; key { [ 0x1008ff65 ] }; key { [ 0x1008ff1d ] }; key { [ 0x1008ff2f ] }; key { [ 0x1008ff2b ] }; key { [ 0x1008ff5d ] }; key { [ 0x1008ff7b ] }; key { [ 0x1008ff8a ] }; key { [ 0x1008ff41 ] }; key { [ 0x1008ff42 ] }; key { [ 0x1008ff2e ] }; key { [ 0x1008ff5a ] }; key { [ 0x1008ff2d ] }; key { [ 0x1008ff74 ] }; key { [ 0x1008ff7f ] }; key { [ 0x1008ff19 ] }; key { [ 0x1008ff30 ] }; key { [ 0x1008ff33 ] }; key { [ 0x1008ff26 ] }; key { [ 0x1008ff27 ] }; key { [ 0x1008ff2c ] }; key { [ 0x1008ff2c, 0x1008ff2c ] }; key { [ 0x1008ff17 ] }; key { [ 0x1008ff14, 0x1008ff31 ] }; key { [ 0x1008ff16 ] }; key { [ 0x1008ff15, 0x1008ff2c ] }; key { [ 0x1008ff1c ] }; key { [ 0x1008ff3e ] }; key { [ 0x1008ff6e ] }; key { [ 0x1008ff81 ] }; key { [ 0x1008ff18 ] }; key { [ 0x1008ff73 ] }; key { [ 0x1008ff56 ] }; key { [ 0x1008ff78 ] }; key { [ 0x1008ff79 ] }; key { [ 0x28 ] }; key { [ 0x29 ] }; key { [ 0x1008ff68 ] }; key { [ 0xff66 ] }; key { [ 0x1008ff81 ] }; key { [ 0x1008ff45 ] }; key { [ 0x1008ff46 ] }; key { [ 0x1008ff47 ] }; key { [ 0x1008ff48 ] }; key { [ 0x1008ff49 ] }; key { [ 0x1008ffb2 ] }; key { [ 0x1008ffa9 ] }; key { [ 0x1008ffb0 ] }; key { [ 0x1008ffb1 ] }; key { [ 0xff7e ] }; key { [ NoSymbol, 0xffe9 ] }; key { [ NoSymbol, 0xffe7 ] }; key { [ NoSymbol, 0xffeb ] }; key { [ NoSymbol, 0xffed ] }; key { [ 0x1008ff14 ] }; key { [ 0x1008ff31 ] }; key { [ 0x1008ff43 ] }; key { [ 0x1008ff44 ] }; key { [ 0x1008ff4b ] }; key { [ 0x1008ffa7 ] }; key { [ 0x1008ff56 ] }; key { [ 0x1008ff14 ] }; key { [ 0x1008ff97 ] }; key { [ 0xff61 ] }; key { [ 0x1008ff8f ] }; key { [ 0x1008ff19 ] }; key { [ 0x1008ff8e ] }; key { [ 0x1008ff1b ] }; key { [ 0x1008ff5f ] }; key { [ 0x1008ff3c ] }; key { [ 0x1008ff5e ] }; key { [ 0x1008ff36 ] }; key { [ 0xff69 ] }; key { [ 0x1008ff03 ] }; key { [ 0x1008ff02 ] }; key { [ 0x1008ff32 ] }; key { [ 0x1008ff59 ] }; key { [ 0x1008ff04 ] }; key { [ 0x1008ff06 ] }; key { [ 0x1008ff05 ] }; key { [ 0x1008ff7b ] }; key { [ 0x1008ff72 ] }; key { [ 0x1008ff90 ] }; key { [ 0x1008ff77 ] }; key { [ 0x1008ff5b ] }; key { [ 0x1008ff93 ] }; key { [ 0x1008ff94 ] }; key { [ 0x1008ff95 ] }; key { repeat= Yes, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=Shift) ] }; modifier_map Shift { , }; modifier_map Lock { }; modifier_map Control { , }; modifier_map Mod1 { , }; modifier_map Mod2 { }; modifier_map Mod4 { , , , }; modifier_map Mod5 { , }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/host.xkb000066400000000000000000001524011510033435100237120ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev_aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; indicator 12 = "Shift Lock"; indicator 13 = "Group 2"; indicator 14 = "Mouse Keys"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 1; preserve[Lock]= Lock; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= 2; level_name[1]= "Base"; level_name[2]= "Shift+Alt"; }; type "PC_SUPER_LEVEL2" { modifiers= Mod4; map[Mod4]= 2; level_name[1]= "Base"; level_name[2]= "Super"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= 2; level_name[1]= "Base"; level_name[2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= 2; level_name[1]= "Base"; level_name[2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= 2; level_name[1]= "Base"; level_name[2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= 2; level_name[1]= "Base"; level_name[2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= 2; level_name[1]= "Base"; level_name[2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= 2; level_name[1]= "Base"; level_name[2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= 2; preserve[Shift]= Shift; map[LevelThree]= 3; map[Shift+LevelThree]= 4; preserve[Shift+LevelThree]= Shift; map[Control+Alt]= 5; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+Lock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Control]= 5; map[Shift+Lock+Control]= 5; map[Shift+Control]= 6; map[Lock+Control]= 6; map[Control+LevelThree]= 7; map[Shift+Lock+Control+LevelThree]= 7; map[Shift+Control+LevelThree]= 8; map[Lock+Control+LevelThree]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "3"; level_name[4]= "Shift 3"; level_name[5]= "Ctrl"; level_name[6]= "Shift Ctrl"; level_name[7]= "3 Ctrl"; level_name[8]= "Shift 3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 8; map[Shift+Lock+LevelThree+LevelFive]= 7; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; preserve[Lock+LevelFive]= Lock; map[Shift+Lock+LevelFive]= 6; preserve[Shift+Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= 8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= 2; map[Shift]= 2; map[LevelThree]= 3; map[NumLock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= 2; map[Shift+LevelThree]= 3; map[Control+Alt]= 4; level_name[1]= "Base"; level_name[2]= "Alt Base"; level_name[3]= "Shift Alt"; level_name[4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 4; preserve[Lock]= Lock; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr Base"; level_name[4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock]= 5; map[Shift+Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Lock"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= 2; map[NumLock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[NumLock+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Alt Number"; }; }; xkb_compatibility "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86LogGrabInfo+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret XF86LogWindowTree+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; indicator "Group 2" { groups= 0xfe; }; indicator "Mouse Keys" { controls= MouseKeys; }; }; xkb_symbols "pc_us_pt_2_us_3_inet(evdev)_group(shift_caps_toggle)_compose(ralt)" { name[1]="English (US)"; name[2]="Portuguese"; name[3]="English (US)"; key { [ Escape ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 1, exclam ], symbols[2]= [ 1, exclam, onesuperior, exclamdown ], symbols[3]= [ 1, exclam ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 2, at ], symbols[2]= [ 2, quotedbl, at, oneeighth ], symbols[3]= [ 2, at ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 3, numbersign ], symbols[2]= [ 3, numbersign, sterling, sterling ], symbols[3]= [ 3, numbersign ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 4, dollar ], symbols[2]= [ 4, dollar, section, dollar ], symbols[3]= [ 4, dollar ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 5, percent ], symbols[2]= [ 5, percent, onehalf, threeeighths ], symbols[3]= [ 5, percent ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 6, asciicircum ], symbols[2]= [ 6, ampersand, notsign, fiveeighths ], symbols[3]= [ 6, asciicircum ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 7, ampersand ], symbols[2]= [ 7, slash, braceleft, seveneighths ], symbols[3]= [ 7, ampersand ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 8, asterisk ], symbols[2]= [ 8, parenleft, bracketleft, trademark ], symbols[3]= [ 8, asterisk ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 9, parenleft ], symbols[2]= [ 9, parenright, bracketright, plusminus ], symbols[3]= [ 9, parenleft ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ 0, parenright ], symbols[2]= [ 0, equal, braceright, degree ], symbols[3]= [ 0, parenright ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ minus, underscore ], symbols[2]= [ apostrophe, question, backslash, questiondown ], symbols[3]= [ minus, underscore ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ equal, plus ], symbols[2]= [ Hangul_A, Hangul_E, dead_cedilla, dead_ogonek ], symbols[3]= [ equal, plus ] }; key { [ BackSpace, BackSpace ] }; key { [ Tab, ISO_Left_Tab ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ q, Q ], symbols[2]= [ q, Q, at, Greek_OMEGA ], symbols[3]= [ q, Q ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ w, W ], symbols[2]= [ w, W, lstroke, Lstroke ], symbols[3]= [ w, W ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ e, E ], symbols[2]= [ e, E, EuroSign, cent ], symbols[3]= [ e, E ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ r, R ], symbols[2]= [ r, R, paragraph, registered ], symbols[3]= [ r, R ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ t, T ], symbols[2]= [ t, T, tslash, Tslash ], symbols[3]= [ t, T ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ y, Y ], symbols[2]= [ y, Y, leftarrow, yen ], symbols[3]= [ y, Y ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ u, U ], symbols[2]= [ u, U, downarrow, uparrow ], symbols[3]= [ u, U ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ i, I ], symbols[2]= [ i, I, rightarrow, idotless ], symbols[3]= [ i, I ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ o, O ], symbols[2]= [ o, O, oslash, Oslash ], symbols[3]= [ o, O ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ p, P ], symbols[2]= [ p, P, thorn, THORN ], symbols[3]= [ p, P ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ bracketleft, braceleft ], symbols[2]= [ plus, asterisk, dead_diaeresis, dead_abovering ], symbols[3]= [ bracketleft, braceleft ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ bracketright, braceright ], symbols[2]= [ dead_acute, dead_grave, dead_tilde, dead_macron ], symbols[3]= [ bracketright, braceright ] }; key { [ Return ] }; key { [ Control_L ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ a, A ], symbols[2]= [ a, A, ae, AE ], symbols[3]= [ a, A ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ s, S ], symbols[2]= [ s, S, ssharp, section ], symbols[3]= [ s, S ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ d, D ], symbols[2]= [ d, D, eth, ETH ], symbols[3]= [ d, D ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ f, F ], symbols[2]= [ f, F, dstroke, ordfeminine ], symbols[3]= [ f, F ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ g, G ], symbols[2]= [ g, G, eng, ENG ], symbols[3]= [ g, G ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ h, H ], symbols[2]= [ h, H, hstroke, Hstroke ], symbols[3]= [ h, H ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ j, J ], symbols[2]= [ j, J, dead_hook, dead_horn ], symbols[3]= [ j, J ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ k, K ], symbols[2]= [ k, K, kra, ampersand ], symbols[3]= [ k, K ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ l, L ], symbols[2]= [ l, L, lstroke, Lstroke ], symbols[3]= [ l, L ] }; key { type[2]= "FOUR_LEVEL_SEMIALPHABETIC", symbols[1]= [ semicolon, colon ], symbols[2]= [ ccedilla, Ccedilla, dead_acute, dead_doubleacute ], symbols[3]= [ semicolon, colon ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ apostrophe, quotedbl ], symbols[2]= [ Hangul_O, ordfeminine, dead_circumflex, dead_caron ], symbols[3]= [ apostrophe, quotedbl ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ grave, asciitilde ], symbols[2]= [ backslash, bar, notsign, notsign ], symbols[3]= [ grave, asciitilde ] }; key { [ Shift_L ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ backslash, bar ], symbols[2]= [ dead_tilde, dead_circumflex, dead_grave, dead_breve ], symbols[3]= [ backslash, bar ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ z, Z ], symbols[2]= [ z, Z, Hangul_A, less ], symbols[3]= [ z, Z ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ x, X ], symbols[2]= [ x, X, Hangul_E, greater ], symbols[3]= [ x, X ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ c, C ], symbols[2]= [ c, C, cent, copyright ], symbols[3]= [ c, C ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ v, V ], symbols[2]= [ v, V, leftdoublequotemark, leftsinglequotemark ], symbols[3]= [ v, V ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ b, B ], symbols[2]= [ b, B, rightdoublequotemark, rightsinglequotemark ], symbols[3]= [ b, B ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_ALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ n, N ], symbols[2]= [ n, N, n, N ], symbols[3]= [ n, N ] }; key { type[1]= "ALPHABETIC", type[2]= "FOUR_LEVEL_SEMIALPHABETIC", type[3]= "ALPHABETIC", symbols[1]= [ m, M ], symbols[2]= [ m, M, mu, Hangul_O ], symbols[3]= [ m, M ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ comma, less ], symbols[2]= [ comma, semicolon, horizconnector, multiply ], symbols[3]= [ comma, less ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ period, greater ], symbols[2]= [ period, colon, periodcentered, division ], symbols[3]= [ period, greater ] }; key { type[2]= "FOUR_LEVEL", symbols[1]= [ slash, question ], symbols[2]= [ minus, underscore, dead_belowdot, dead_abovedot ], symbols[3]= [ slash, question ] }; key { [ Shift_R ] }; key { type= "CTRL+ALT", symbols[1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ] }; key { [ Alt_L, Meta_L ] }; key { [ space ] }; key { [ Caps_Lock, ISO_Next_Group ] }; key { type= "CTRL+ALT", symbols[1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ] }; key { type= "CTRL+ALT", symbols[1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ] }; key { type= "CTRL+ALT", symbols[1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ] }; key { type= "CTRL+ALT", symbols[1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ] }; key { type= "CTRL+ALT", symbols[1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ] }; key { type= "CTRL+ALT", symbols[1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ] }; key { type= "CTRL+ALT", symbols[1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ] }; key { type= "CTRL+ALT", symbols[1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ] }; key { type= "CTRL+ALT", symbols[1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ] }; key { type= "CTRL+ALT", symbols[1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ] }; key { [ Num_Lock ] }; key { [ Scroll_Lock ] }; key { [ KP_Home, KP_7 ] }; key { [ KP_Up, KP_8 ] }; key { [ KP_Prior, KP_9 ] }; key { type= "CTRL+ALT", symbols[1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ] }; key { [ KP_Left, KP_4 ] }; key { [ KP_Begin, KP_5 ] }; key { [ KP_Right, KP_6 ] }; key { type= "CTRL+ALT", symbols[1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ] }; key { [ KP_End, KP_1 ] }; key { [ KP_Down, KP_2 ] }; key { [ KP_Next, KP_3 ] }; key { [ KP_Insert, KP_0 ] }; key { [ KP_Delete, KP_Decimal ] }; key { type= "ONE_LEVEL", symbols[1]= [ ISO_Level3_Shift ] }; key { type= "FOUR_LEVEL", symbols[1]= [ less, greater, bar, brokenbar ], symbols[2]= [ less, greater, backslash, backslash ] }; key { type= "CTRL+ALT", symbols[1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ] }; key { type= "CTRL+ALT", symbols[1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Henkan_Mode ] }; key { [ Hiragana_Katakana ] }; key { [ Muhenkan ] }; key { [ KP_Enter ] }; key { [ Control_R ] }; key { type= "CTRL+ALT", symbols[1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ] }; key { type= "PC_ALT_LEVEL2", symbols[1]= [ Print, Sys_Req ] }; key { type[1]= "TWO_LEVEL", type[2]= "ONE_LEVEL", symbols[1]= [ Multi_key, Multi_key ], symbols[2]= [ ISO_Level3_Shift ] }; key { [ Linefeed ] }; key { [ Home ] }; key { [ Up ] }; key { [ Prior ] }; key { [ Left ] }; key { [ Right ] }; key { [ End ] }; key { [ Down ] }; key { [ Next ] }; key { [ Insert ] }; key { [ Delete ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { [ KP_Equal ] }; key { [ plusminus ] }; key { type= "PC_CONTROL_LEVEL2", symbols[1]= [ Pause, Break ] }; key { [ XF86LaunchA ] }; key { [ KP_Decimal, KP_Decimal ] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ Super_L ] }; key { [ Super_R ] }; key { [ Menu ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ XF86Open ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86TaskPane ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Eject ] }; key { [ XF86Eject, XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; key { [ XF86AudioMicMute ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ Mode_switch ] }; key { [ NoSymbol, Alt_L ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; key { [ NoSymbol, Hyper_L ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; key { [ Print ] }; key { [ XF86WebCam ] }; key { [ XF86Mail ] }; key { [ XF86Messenger ] }; key { [ XF86Search ] }; key { [ XF86Go ] }; key { [ XF86Finance ] }; key { [ XF86Game ] }; key { [ XF86Shop ] }; key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; key { repeat= Yes, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=Shift) ] }; modifier_map Shift { , }; modifier_map Lock { }; modifier_map Control { , }; modifier_map Mod1 { , }; modifier_map Mod2 { }; modifier_map Mod4 { , , , }; modifier_map Mod5 { , }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/include-banana-implicit-default.xkb000066400000000000000000000005711510033435100310300ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <> = 1; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols "banana" { key <> { [ U1F349 ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/include-capslock-custom.xkb000066400000000000000000000006041510033435100274620ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; = 66; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols "capslock(custom)" { key { [ XF86Fn ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/include-capslock-system.xkb000066400000000000000000000006331510033435100274760ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; = 66; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols "capslock" { key { [ Caps_Lock ] }; modifier_map Lock { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/include-level3-explicit-default.xkb000066400000000000000000000015571510033435100310160ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; = 92; = 108; }; xkb_types "basic" { virtual_modifiers NumLock; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; }; xkb_compatibility { virtual_modifiers NumLock; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols "level3" { key { type= "ONE_LEVEL", symbols[1]= [ ISO_Level3_Shift ] }; key { [ ISO_Level3_Shift, ISO_Level3_Lock ] }; modifier_map Mod5 { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/integers-overflow.xkb000066400000000000000000000004731510033435100264170ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <> = 1; }; xkb_types { type "default" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/integers.xkb000066400000000000000000000011111510033435100245440ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <> = 1; indicator 32 = "xxx"; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key <> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ MovePtr(x=0,y=+0) ], symbols[2]= [ NoSymbol ], actions[2]= [ MovePtr(x=2,y=32766) ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/invalid-escape-sequence.xkb000066400000000000000000000010531510033435100274230ustar00rootroot00000000000000xkb_keymap { // The following include statement has an octal escape sequence that // must be ignored. Else it would insert a NULL character and thus // truncates the string to "evde", while we expect "evdev+aliases(qwerty)". xkb_keycodes { include "evde\0v+aliases(qwerty)" }; // The following include statement has two octal escape sequences that // should be ignored, else they would overflow. xkb_types { include "com\401ple\777te" }; xkb_compat { include "complete" }; xkb_symbols { include "pc+us" }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/invalid-qualified-symbols-field.xkb000066400000000000000000000003011510033435100310620ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { include "evdev" }; xkb_types { include "basic" }; xkb_compat { }; xkb_symbols { key { garbage.symbols = [q, Q] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/invalid-qualified-type-field.xkb000066400000000000000000000007261510033435100303660ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { include "evdev" }; xkb_types { type "ONE_LEVEL" { garbage.modifiers = None; garbage.map[None] = Level1; garbage.level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; }; xkb_compat { }; xkb_symbols { include "pc" }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/keycodes-aliases-1.xkb000066400000000000000000000005651510033435100263230ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; = 1; = 2; alias = ; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/keycodes-aliases-2.xkb000066400000000000000000000014151510033435100263170ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; = 1; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types { }; xkb_compatibility { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= false; interpret.locking= false; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Lock+AnyOf(all) { action= NoAction(); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= true; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= true; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= true; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= true; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= true; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= true; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= true; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= true; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= true; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= true; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= true; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= true; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= true; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= true; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= true; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= true; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= true; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= true; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=mouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=mouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=accessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=accessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=repeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=slowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=bounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=stickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=mouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=mouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=audibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= true; action= SwitchScreen(screen=12,!same); }; interpret XF86LogGrabInfo+AnyOfOrNone(all) { repeat= true; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret XF86LogWindowTree+AnyOfOrNone(all) { repeat= true; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= true; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= true; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; group 2 = AltGr; group 3 = AltGr; group 4 = AltGr; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; indicator "Group 2" { groups= 0xfe; }; indicator "Mouse Keys" { controls= mouseKeys; }; }; xkb_symbols { name[group1]="English (US)"; key { [ Escape ] }; key { [ 1 ] }; key { [ 2 ] }; key { [ 3 ] }; key { [ 4 ] }; key { [ 5 ] }; key { [ 6 ] }; key { [ 7 ] }; key { [ 8 ] }; key { [ 9 ] }; key { [ 0 ] }; key { [ minus ] }; key { [ equal ] }; key { [ BackSpace ] }; key { [ Tab ] }; key { [ q ] }; key { [ w ] }; key { [ e ] }; key { [ r ] }; key { [ t ] }; key { [ y ] }; key { [ u ] }; key { [ i ] }; key { [ o ] }; key { [ p ] }; key { [ bracketleft ] }; key { [ bracketright ] }; key { [ Return ] }; key { [ Control_L ] }; key { [ a ] }; key { [ s ] }; key { [ d ] }; key { [ f ] }; key { [ g ] }; key { [ h ] }; key { [ j ] }; key { [ k ] }; key { [ l ] }; key { [ semicolon ] }; key { [ apostrophe ] }; key { [ grave ] }; key { [ Shift_L ] }; key { [ NoSymbol ] }; key { [ z ] }; key { [ x ] }; key { [ c ] }; key { [ v ] }; key { [ b ] }; key { [ n ] }; key { [ m ] }; key { [ comma ] }; key { [ period ] }; key { [ slash ] }; key { [ Shift_R ] }; key { [ KP_Multiply ] }; key { [ Alt_L ] }; key { [ space ] }; key { [ Caps_Lock ] }; key { [ F1 ] }; key { [ F2 ] }; key { [ F3 ] }; key { [ F4 ] }; key { [ F5 ] }; key { [ F6 ] }; key { [ F7 ] }; key { [ F8 ] }; key { [ F9 ] }; key { [ F10 ] }; key { [ Num_Lock ] }; key { [ Scroll_Lock ] }; key { [ KP_Home ] }; key { [ KP_Up ] }; key { [ KP_Prior ] }; key { [ KP_Subtract ] }; key { [ KP_Left ] }; key { [ KP_Begin ] }; key { [ KP_Right ] }; key { [ KP_Add ] }; key { [ KP_End ] }; key { [ KP_Down ] }; key { [ KP_Next ] }; key { [ KP_Insert ] }; key { [ KP_Delete ] }; key { [ ISO_Level3_Shift ] }; key { [ less ] }; key { [ F11 ] }; key { [ F12 ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Henkan_Mode ] }; key { [ Hiragana_Katakana ] }; key { [ Muhenkan ] }; key { [ KP_Enter ] }; key { [ Control_R ] }; key { [ KP_Divide ] }; key { [ Print ] }; key { [ Alt_R ] }; key { [ Linefeed ] }; key { [ Home ] }; key { [ Up ] }; key { [ Prior ] }; key { [ Left ] }; key { [ Right ] }; key { [ End ] }; key { [ Down ] }; key { [ Next ] }; key { [ Insert ] }; key { [ Delete ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { [ KP_Equal ] }; key { [ plusminus ] }; key { [ Pause ] }; key { [ XF86LaunchA ] }; key { [ KP_Decimal] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ Super_L ] }; key { [ Super_R ] }; key { [ Menu ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ SunOpen ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Eject ] }; key { [ XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ Mode_switch ] }; key { [ NoSymbol ] }; key { [ NoSymbol ] }; key { [ NoSymbol ] }; key { [ NoSymbol ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; key { [ Print ] }; key { [ XF86WebCam ] }; key { [ XF86Mail ] }; key { [ XF86Messenger ] }; key { [ XF86Search ] }; key { [ XF86Go ] }; key { [ XF86Finance ] }; key { [ XF86Game ] }; key { [ XF86Shop ] }; key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; modifier_map Control { }; modifier_map Shift { }; modifier_map Shift { }; modifier_map Mod1 { }; modifier_map Lock { }; modifier_map Mod2 { }; modifier_map Mod5 { }; modifier_map Control { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod4 { }; modifier_map Mod5 { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod4 { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/no_void_action-v1.xkb000066400000000000000000000014621510033435100262530ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <1> = 1; <2> = 2; <3> = 3; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key <1> { repeat= No, symbols[1]= [ x ], actions[1]= [ NoAction() ] }; key <2> { repeat= No, symbols[1]= [ y ], actions[1]= [ NoAction() ] }; key <3> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ LockControls(controls=none,affect=neither) ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/no_void_action-v2.xkb000066400000000000000000000014461510033435100262560ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <1> = 1; <2> = 2; <3> = 3; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key <1> { repeat= No, symbols[1]= [ x ], actions[1]= [ NoAction() ] }; key <2> { repeat= No, symbols[1]= [ y ], actions[1]= [ NoAction() ] }; key <3> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ VoidAction() ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/optional-components-basic.xkb000066400000000000000000000006241510033435100300230ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <> = 1; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key <> { type= "ONE_LEVEL", symbols[1]= [ a ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/optional-components-no-real-led.xkb000066400000000000000000000005421510033435100310400ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; indicator 1 = "XXX"; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; indicator "XXX" { modifiers= Lock; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/optional-components-none.xkb000066400000000000000000000004421510033435100276770ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/pure-virtual-mods-explicit.xkb000066400000000000000000000137461510033435100301630ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "test" { minimum = 8; maximum = 255; = 49; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 51; = 36; = 66; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; alias = ; = 50; = 94; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 92; = 108; }; xkb_types "complete" { // Define >20 virtual modifiers. This lead to overcome the X11 limit of // 16 virtual modifiers. virtual_modifiers LevelThree = 0x00000100, ModA = 0x00000200, ModB = 0x00000400, ModC = 0x00000800, ModD = 0x00001000, ModE = 0x00002000, ModF = 0x00004000, ModG = 0x00008000, ModH = 0x00010000, ModI = 0x00020000, ModJ = 0x00040000, ModK = 0x00080000, ModL = 0x00100000, ModM = 0x00200000, ModN = 0x00400000, ModO = 0x00800000, ModP = 0x01000000, ModQ = 0x02000000, ModR = 0x04000000, ModS = 0x08000000, ModT = 0x10000000, ModU = 0x20000000, ModV = 0x40000000; type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "TEST" { modifiers= Shift + LevelThree + ModA + ModB + ModC + ModD + ModE + ModF + ModG + ModH + ModI + ModJ + ModK + ModL + ModM + ModN + ModO + ModP + ModQ + ModR + ModS + ModT + ModU + ModV; map[ModA]= 2; map[ModB]= 3; map[ModC]= 4; map[ModD]= 5; map[ModE]= 6; map[ModF]= 7; map[ModG]= 8; map[ModH]= 9; map[ModI]= 10; map[ModJ]= 11; map[ModK]= 12; map[ModL]= 13; map[ModM]= 14; map[ModN]= 15; map[ModO]= 16; map[ModP]= 17; map[ModQ]= 18; map[ModR]= 19; map[ModS]= 20; map[ModT]= 21; map[ModU]= 22; map[ModV]= 23; map[ModV+Shift]= 24; map[ModA+ModS]= 25; map[ModA+ModQ]= 26; map[LevelThree+ModA]= 27; map[LevelThree+ModA+ModS]= 28; map[ModA+ModB+ModC]= 29; level_name[1]= "1"; level_name[2]= "2"; level_name[3]= "3"; level_name[4]= "4"; level_name[5]= "5"; level_name[6]= "6"; level_name[7]= "7"; level_name[8]= "8"; level_name[9]= "9"; level_name[10]= "10"; level_name[11]= "11"; level_name[12]= "12"; level_name[13]= "13"; level_name[14]= "14"; level_name[15]= "15"; level_name[16]= "16"; level_name[17]= "17"; level_name[18]= "18"; level_name[19]= "19"; level_name[20]= "20"; level_name[21]= "21"; level_name[22]= "22"; level_name[23]= "23"; level_name[24]= "24"; level_name[25]= "25"; level_name[26]= "26"; level_name[27]= "27"; level_name[28]= "28"; level_name[29]= "29"; }; }; xkb_compatibility "complete" { virtual_modifiers LevelThree, ModA, ModB, ModC, ModD; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret a { action= SetMods(modifiers=ModA,clearLocks); }; interpret b { action= SetMods(modifiers=ModB,clearLocks); }; interpret c { action= SetMods(modifiers=ModC,clearLocks); }; interpret d { action= SetMods(modifiers=ModD,clearLocks); }; interpret e { action= SetMods(modifiers=ModE,clearLocks); }; interpret f { action= SetMods(modifiers=ModF,clearLocks); }; interpret g { action= SetMods(modifiers=ModG,clearLocks); }; interpret h { action= SetMods(modifiers=ModH,clearLocks); }; interpret i { action= SetMods(modifiers=ModI,clearLocks); }; interpret j { action= SetMods(modifiers=ModJ,clearLocks); }; interpret k { action= SetMods(modifiers=ModK,clearLocks); }; interpret l { action= SetMods(modifiers=ModL,clearLocks); }; interpret m { action= SetMods(modifiers=ModM,clearLocks); }; interpret n { action= SetMods(modifiers=ModN,clearLocks); }; interpret o { action= SetMods(modifiers=ModO,clearLocks); }; interpret p { action= SetMods(modifiers=ModP,clearLocks); }; interpret q { action= SetMods(modifiers=ModQ,clearLocks); }; interpret r { action= SetMods(modifiers=ModR,clearLocks); }; interpret s { action= SetMods(modifiers=ModS,clearLocks); }; interpret t { action= SetMods(modifiers=ModT,clearLocks); }; interpret u { action= SetMods(modifiers=ModU,clearLocks); }; interpret v { action= SetMods(modifiers=ModV,clearLocks); }; }; xkb_symbols { name[group1]="Test"; key { [Shift_L] }; key { [ISO_Level3_Shift] }; key { [ISO_Level3_Shift] }; modmap Shift { }; modmap Mod5 { , }; key {[ q, Q ]}; key {[ w, W ]}; key {[ e, E ]}; key {[ r, R ]}; key {[ t, T ]}; key {[ y, Y ]}; key {[ u, U ]}; key {[ i, I ]}; key {[ o, O ]}; key {[ p, P ]}; key {[ a, A ]}; key {[ s, S ]}; key {[ d, D ]}; key {[ f, F ]}; key {[ g, G ]}; key {[ h, H ]}; key {[ j, J ]}; key {[ k, K ]}; key {[ l, L ]}; key {[ z, Z ]}; key {[ x, X ]}; key {[ c, C ]}; key {[ v, V ]}; key {[ b, B ]}; key {[ n, N ]}; key {[ m, M ]}; key.type[1] = "TEST"; key { [ w, a, b, c, d, e, f, g, h, i, j, k, l, m, n , o, p, q, r, s, t, u, v, V, 1, 2, 3, 4, 5 ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/pure-virtual-mods-implicit.xkb000066400000000000000000000130671510033435100301500ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "test" { minimum = 8; maximum = 255; = 49; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 51; = 36; = 66; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; alias = ; = 50; = 94; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 92; = 108; }; xkb_types "complete" { // Define >20 virtual modifiers. This lead to overcome the X11 limit of // 16 virtual modifiers. virtual_modifiers LevelThree, ModA, ModB, ModC, ModD, ModE, ModF, ModG, ModH, ModI, ModJ, ModK, ModL, ModM, ModN, ModO, ModP, ModQ, ModR, ModS, ModT, ModU, ModV; type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "TEST" { modifiers= Shift + LevelThree + ModA + ModB + ModC + ModD + ModE + ModF + ModG + ModH + ModI + ModJ + ModK + ModL + ModM + ModN + ModO + ModP + ModQ + ModR + ModS + ModT + ModU + ModV; map[ModA]= 2; map[ModB]= 3; map[ModC]= 4; map[ModD]= 5; map[ModE]= 6; map[ModF]= 7; map[ModG]= 8; map[ModH]= 9; map[ModI]= 10; map[ModJ]= 11; map[ModK]= 12; map[ModL]= 13; map[ModM]= 14; map[ModN]= 15; map[ModO]= 16; map[ModP]= 17; map[ModQ]= 18; map[ModR]= 19; map[ModS]= 20; map[ModT]= 21; map[ModU]= 22; map[ModV]= 23; map[ModV+Shift]= 24; map[ModA+ModS]= 25; map[ModA+ModQ]= 26; map[LevelThree+ModA]= 27; map[LevelThree+ModA+ModS]= 28; map[ModA+ModB+ModC]= 29; level_name[1]= "1"; level_name[2]= "2"; level_name[3]= "3"; level_name[4]= "4"; level_name[5]= "5"; level_name[6]= "6"; level_name[7]= "7"; level_name[8]= "8"; level_name[9]= "9"; level_name[10]= "10"; level_name[11]= "11"; level_name[12]= "12"; level_name[13]= "13"; level_name[14]= "14"; level_name[15]= "15"; level_name[16]= "16"; level_name[17]= "17"; level_name[18]= "18"; level_name[19]= "19"; level_name[20]= "20"; level_name[21]= "21"; level_name[22]= "22"; level_name[23]= "23"; level_name[24]= "24"; level_name[25]= "25"; level_name[26]= "26"; level_name[27]= "27"; level_name[28]= "28"; level_name[29]= "29"; }; }; xkb_compatibility "complete" { virtual_modifiers LevelThree, ModA, ModB, ModC, ModD; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret a { action= SetMods(modifiers=ModA,clearLocks); }; interpret b { action= SetMods(modifiers=ModB,clearLocks); }; interpret c { action= SetMods(modifiers=ModC,clearLocks); }; interpret d { action= SetMods(modifiers=ModD,clearLocks); }; interpret e { action= SetMods(modifiers=ModE,clearLocks); }; interpret f { action= SetMods(modifiers=ModF,clearLocks); }; interpret g { action= SetMods(modifiers=ModG,clearLocks); }; interpret h { action= SetMods(modifiers=ModH,clearLocks); }; interpret i { action= SetMods(modifiers=ModI,clearLocks); }; interpret j { action= SetMods(modifiers=ModJ,clearLocks); }; interpret k { action= SetMods(modifiers=ModK,clearLocks); }; interpret l { action= SetMods(modifiers=ModL,clearLocks); }; interpret m { action= SetMods(modifiers=ModM,clearLocks); }; interpret n { action= SetMods(modifiers=ModN,clearLocks); }; interpret o { action= SetMods(modifiers=ModO,clearLocks); }; interpret p { action= SetMods(modifiers=ModP,clearLocks); }; interpret q { action= SetMods(modifiers=ModQ,clearLocks); }; interpret r { action= SetMods(modifiers=ModR,clearLocks); }; interpret s { action= SetMods(modifiers=ModS,clearLocks); }; interpret t { action= SetMods(modifiers=ModT,clearLocks); }; interpret u { action= SetMods(modifiers=ModU,clearLocks); }; interpret v { action= SetMods(modifiers=ModV,clearLocks); }; }; xkb_symbols { name[group1]="Test"; key { [Shift_L] }; key { [ISO_Level3_Shift] }; key { [ISO_Level3_Shift] }; modmap Shift { }; modmap Mod5 { , }; key {[ q, Q ]}; key {[ w, W ]}; key {[ e, E ]}; key {[ r, R ]}; key {[ t, T ]}; key {[ y, Y ]}; key {[ u, U ]}; key {[ i, I ]}; key {[ o, O ]}; key {[ p, P ]}; key {[ a, A ]}; key {[ s, S ]}; key {[ d, D ]}; key {[ f, F ]}; key {[ g, G ]}; key {[ h, H ]}; key {[ j, J ]}; key {[ k, K ]}; key {[ l, L ]}; key {[ z, Z ]}; key {[ x, X ]}; key {[ c, C ]}; key {[ v, V ]}; key {[ b, B ]}; key {[ n, N ]}; key {[ m, M ]}; key.type[1] = "TEST"; key { [ w, a, b, c, d, e, f, g, h, i, j, k, l, m, n , o, p, q, r, s, t, u, v, V, 1, 2, 3, 4, 5 ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/quartz.xkb000066400000000000000000001055311510033435100242650ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "empty_aliases(qwerty)" { minimum = 8; maximum = 255; virtual indicator 1 = "Caps Lock"; virtual indicator 2 = "Num Lock"; virtual indicator 3 = "Shift Lock"; virtual indicator 4 = "Group 2"; virtual indicator 5 = "Mouse Keys"; virtual indicator 6 = "Scroll Lock"; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= Level2; map[Lock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= Level2; map[NumLock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Number"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Control+Alt; map[Control+Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Control]= Level5; map[Shift+Lock+Control]= Level5; map[Shift+Control]= Level6; map[Lock+Control]= Level6; map[Control+LevelThree]= Level7; map[Shift+Lock+Control+LevelThree]= Level7; map[Shift+Control+LevelThree]= Level8; map[Lock+Control+LevelThree]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; level_name[Level4]= "Shift Level3"; level_name[Level5]= "Ctrl"; level_name[Level6]= "Shift Ctrl"; level_name[Level7]= "Level3 Ctrl"; level_name[Level8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level8; map[Shift+Lock+LevelThree+LevelFive]= Level7; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; preserve[Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= Level8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelFive]= Level1; preserve[Shift+Lock+LevelFive]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= Level2; map[Shift]= Level2; map[LevelThree]= Level3; map[NumLock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= Level2; map[Shift+LevelThree]= Level3; map[Control+Alt]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Alt Base"; level_name[Level3]= "Shift Alt"; level_name[Level4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level4; preserve[Lock]= Lock; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "AltGr Base"; level_name[Level4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock]= Level5; map[Shift+Lock]= Level2; map[Lock+LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Lock"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= Level2; map[NumLock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[NumLock+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Alt Number"; }; }; xkb_compatibility "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Lock+AnyOf(all) { action= ISOLock(modifiers=modMapMods,affect=all); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay1); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay2); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86Ungrab+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x55,data[1]=0x6e,data[2]=0x67,data[3]=0x72,data[4]=0x61,data[5]=0x62,data[6]=0x00); }; interpret XF86ClearGrab+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x43,data[1]=0x6c,data[2]=0x73,data[3]=0x47,data[4]=0x72,data[5]=0x62,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; group 2 = AltGr; group 3 = AltGr; group 4 = AltGr; indicator "Caps Lock" { !allowExplicit; whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { !allowExplicit; whichModState= locked; modifiers= NumLock; }; indicator "Shift Lock" { !allowExplicit; whichModState= locked; modifiers= Shift; }; indicator "Group 2" { !allowExplicit; groups= 0xfe; }; indicator "Mouse Keys" { indicatorDrivesKeyboard; controls= mouseKeys; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; }; xkb_symbols "unknown" { key <> { type= "ALPHABETIC", symbols[Group1]= [ a, A ], symbols[Group2]= [ aring, Aring ] }; modifier_map Mod2 { <> }; }; xkb_geometry "pc(pc104)" { width= 470; height= 180; baseColor= "white"; labelColor= "black"; xfont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; description= "Generic 104"; shape "NORM" { corner= 1, { [ 18, 18 ] }, { [ 2, 1 ], [ 16, 16 ] } }; shape "BKSP" { corner= 1, { [ 38, 18 ] }, { [ 2, 1 ], [ 36, 16 ] } }; shape "TABK" { corner= 1, { [ 28, 18 ] }, { [ 2, 1 ], [ 26, 16 ] } }; shape "BKSL" { corner= 1, { [ 28, 18 ] }, { [ 2, 1 ], [ 26, 16 ] } }; shape "RTRN" { corner= 1, { [ 42, 18 ] }, { [ 2, 1 ], [ 40, 16 ] } }; shape "CAPS" { corner= 1, { [ 33, 18 ] }, { [ 2, 1 ], [ 31, 16 ] } }; shape "LFSH" { corner= 1, { [ 42, 18 ] }, { [ 2, 1 ], [ 40, 16 ] } }; shape "RTSH" { corner= 1, { [ 52, 18 ] }, { [ 2, 1 ], [ 50, 16 ] } }; shape "MODK" { corner= 1, { [ 27, 18 ] }, { [ 2, 1 ], [ 25, 16 ] } }; shape "SMOD" { corner= 1, { [ 23, 18 ] }, { [ 2, 1 ], [ 21, 16 ] } }; shape "SPCE" { corner= 1, { [ 113, 18 ] }, { [ 2, 1 ], [ 111, 16 ] } }; shape "KP0" { corner= 1, { [ 37, 18 ] }, { [ 2, 1 ], [ 35, 16 ] } }; shape "KPAD" { corner= 1, { [ 18, 37 ] }, { [ 2, 1 ], [ 16, 35 ] } }; shape "LEDS" { { [ 75, 20 ] } }; shape "LED" { { [ 5, 1 ] } }; section "Function" { key.color= "grey20"; priority= 7; top= 22; left= 19; width= 351; height= 19; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 20, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 11, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 11, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 8, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" } }; }; }; // End of "Function" section section "Alpha" { key.color= "white"; priority= 8; top= 61; left= 19; width= 287; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "BKSP", 1, color="grey20" } }; }; row { top= 20; left= 1; keys { { , "TABK", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "BKSL", 1 } }; }; row { top= 39; left= 1; keys { { , "CAPS", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "RTRN", 1, color="grey20" } }; }; row { top= 58; left= 1; keys { { , "LFSH", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "RTSH", 1, color="grey20" } }; }; row { top= 77; left= 1; keys { { , "MODK", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SPCE", 1 }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" } }; }; }; // End of "Alpha" section section "Editing" { key.color= "grey20"; priority= 9; top= 61; left= 312; width= 58; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 20; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 58; left= 20; keys { { , "NORM", 1 } }; }; row { top= 77; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; }; // End of "Editing" section section "Keypad" { key.color= "grey20"; priority= 10; top= 61; left= 376; width= 77; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 20; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "KPAD", 1 } }; }; row { top= 39; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" } }; }; row { top= 58; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "KPAD", 1 } }; }; row { top= 77; left= 1; keys { { , "KP0", 1, color="white" }, { , "NORM", 1, color="white" } }; }; }; // End of "Keypad" section solid "LedPanel" { top= 22; left= 377; priority= 0; color= "grey10"; shape= "LEDS"; }; indicator "Num Lock" { top= 37; left= 382; priority= 1; onColor= "green"; offColor= "green30"; shape= "LED"; }; indicator "Caps Lock" { top= 37; left= 407; priority= 2; onColor= "green"; offColor= "green30"; shape= "LED"; }; indicator "Scroll Lock" { top= 37; left= 433; priority= 3; onColor= "green"; offColor= "green30"; shape= "LED"; }; text "NumLockLabel" { top= 25; left= 378; priority= 4; width= 19.8; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Num\nLock"; }; text "CapsLockLabel" { top= 25; left= 403; priority= 5; width= 26.4; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Caps\nLock"; }; text "ScrollLockLabel" { top= 25; left= 428; priority= 6; width= 39.6; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Scroll\nLock"; }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/string-as-keysyms.xkb000066400000000000000000000145261510033435100263530ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; <10> = 10; <11> = 11; <12> = 12; <20> = 20; <21> = 21; <22> = 22; <23> = 23; <24> = 24; <25> = 25; <30> = 30; <31> = 31; <32> = 32; <33> = 33; <34> = 34; <35> = 35; <40> = 40; <41> = 41; <42> = 42; <50> = 50; <51> = 51; <52> = 52; <60> = 60; <61> = 61; <62> = 62; <63> = 63; <64> = 64; <65> = 65; <66> = 66; <67> = 67; <68> = 68; <69> = 69; <70> = 70; <71> = 71; <72> = 72; <73> = 73; <74> = 74; = 80; = 81; = 82; = 83; }; xkb_types "basic" { virtual_modifiers NumLock; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; }; xkb_compatibility { virtual_modifiers NumLock; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret adiaeresis+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret U2728+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret U1F3BA+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret U1F54A+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret 0x01000001+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret Linefeed+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret 0x0100001f+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret space+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret asciitilde+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret Delete+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret 0x01000080+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret 0x0100009f+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret nobreakspace+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret ydiaeresis+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret UFDD0+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret UFDEF+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret UFFFE+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret UFFFF+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret U10000+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret U1FFFF+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret U10FFFF+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; }; xkb_symbols { key <10> { [ NoSymbol, { b, c } ] }; key <11> { [ a, b ] }; key <20> { [ a, { b, c } ] }; key <23> { [ U2728, U1F3BA ] }; key <24> { [ { u, U0308 } ] }; key <25> { [ { U2200, partialderivative, elementof, U211D, logicaland, union, identical, infinity, space, uparrow, U2197, U21A8, U21BB, U21E3, space, uprightcorner, crossinglines, U2554, U2558, U2591, U25BA, U263A, femalesymbol, space, UFB01, UFFFD, U2440, twosubscript, U1F20, Babovedot, U04E5, Wdiaeresis, U0250, U02D0, U234E, hebrew_aleph, Armenian_AYB, Georgian_an } ] }; key <30> { [ a, { b, c } ] }; key <31> { [ a, { b, c } ] }; key <32> { [ a, { b, c } ] }; key <33> { [ U1F54A, { U1F3F3, UFE0F } ] }; key <34> { [ { u, U0308 } ] }; key <35> { [ { U2200, partialderivative, elementof, U211D, logicaland, union, identical, infinity, space, uparrow, U2197, U21A8, U21BB, U21E3, space, uprightcorner, crossinglines, U2554, U2558, U2591, U25BA, U263A, femalesymbol, space, UFB01, UFFFD, U2440, twosubscript, U1F20, Babovedot, U04E5, Wdiaeresis, U0250, U02D0, U234E, hebrew_aleph, Armenian_AYB, Georgian_an } ] }; key <40> { [ { a, b }, { c, d, e, f } ] }; key <41> { [ { a, b }, { c, d, e, f } ] }; key <42> { [ { a, b }, { c, d, e, f } ] }; key <50> { [ { a, b }, { c, d, e, f } ] }; key <51> { [ { a, b }, { c, d, e, f } ] }; key <52> { [ { a, b }, { c, d, e, f } ] }; key <60> { [ { a, b }, { c, d, e, f } ] }; key <61> { [ { a, b }, { c, d, e, f } ] }; key <63> { [ { a, b, c, d }, { e, f, g, h } ] }; key <64> { [ { a, b, c, d }, { e, f, g, h } ] }; key <65> { [ NoSymbol, U10FFFF ] }; key <66> { [ 0x01000001, Linefeed ] }; key <67> { [ 0x0100001f, space ] }; key <68> { [ asciitilde, Delete ] }; key <69> { [ 0x01000080, 0x0100009f ] }; key <70> { [ nobreakspace, ydiaeresis ] }; key <71> { [ UFFFD, UFFFD ] }; key <72> { [ UFDD0, UFDEF ] }; key <73> { [ UFFFE, UFFFF ] }; key <74> { [ U10000, U1FFFF ] }; key { [ { i, j }, U0132 ] }; key { [ { g, combining_tilde }, { G, combining_tilde } ] }; key { [ { Arabic_lam, Arabic_alef }, { Arabic_lam, Arabic_maddaonalef } ] }; key { [ { c, rightsinglequotemark, h }, { C, rightsinglequotemark, h } ] }; modifier_map Mod1 { <23>, <33> }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/stringcomp-v1-no-flags.xkb000066400000000000000000001246061510033435100271600ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev_aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; indicator 12 = "Shift Lock"; indicator 13 = "Group 2"; indicator 14 = "Mouse Keys"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt=Mod1,RAlt=0x100,RControl=0x210001,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= 2; level_name[1]= "Base"; level_name[2]= "Control"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= 2; level_name[1]= "Base"; level_name[2]= "Alt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Control+Alt]= 5; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Ctrl+Alt"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; preserve[Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= 8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelFive]= 1; preserve[Shift+Lock+LevelFive]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; }; xkb_compatibility "complete_caps(caps_lock)_4_misc(assign_shift_left_action)_4_level5(level5_lock)_4" { virtual_modifiers NumLock,Alt,LevelThree,LAlt=Mod1,RAlt=0x100,RControl=0x210001,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret 0xff7f+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret 0xfe03+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret 0xffe9+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffea+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffe7+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffe8+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffeb+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffec+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffed+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xfe11+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret 0xff7e+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret 0xfe03+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret 0xffb1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret 0xff9c+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret 0xffb2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret 0xff99+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret 0xffb3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret 0xff9b+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret 0xffb4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret 0xff96+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret 0xffb6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret 0xff98+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret 0xffb7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret 0xff95+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret 0xffb8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret 0xff97+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret 0xffb9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret 0xff9a+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret 0xffb5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret 0xff9d+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret 0xffaf+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret 0xffaa+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret 0xffad+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret 0xffac+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret 0xffab+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret 0xffb0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret 0xff9e+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret 0xffae+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret 0xff9f+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret 0xfef9+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret 0xffe9+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret 0xffe1+AnyOfOrNone(all) { action= SetMods(modifiers=Shift); }; interpret 0x1008fe01+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret 0x1008fe02+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret 0x1008fe03+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret 0x1008fe04+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret 0x1008fe05+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret 0x1008fe06+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret 0x1008fe07+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret 0x1008fe08+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret 0x1008fe09+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret 0x1008fe0a+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret 0x1008fe0b+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret 0x1008fe0c+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret 0x1008fe22+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret 0x1008fe23+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret 0xfe11+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret 0xfe13+AnyOfOrNone(all) { action= LockMods(modifiers=NumLock); }; interpret 0xffe5+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; indicator "Group 2" { groups= 0xfe; }; indicator "Mouse Keys" { controls= MouseKeys; }; }; xkb_symbols "pc_us_ru_2_ca(multix)_3_de(neo)_4_inet(evdev)" { name[1]="English (US)"; name[2]="Russian"; name[3]="Canadian Multilingual"; name[4]="German (Neo 2)"; key { [ 0xff1b ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x31, 0x21 ], symbols[2]= [ 0x31, 0x21 ], symbols[3]= [ 0x31, 0x21, 0xb1, NoSymbol, 0xb9, 0xa1, NoSymbol, NoSymbol ], symbols[4]= [ 0x31, 0xb0, 0xb9, 0x1002081, 0xaa, NoSymbol, 0xac, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x32, 0x40 ], symbols[2]= [ 0x32, 0x22 ], symbols[3]= [ 0x32, 0x40, 0x40, NoSymbol, 0xb2, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 0x32, 0xa7, 0xb2, 0x1002082, 0xba, NoSymbol, 0x8df, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x33, 0x23 ], symbols[2]= [ 0x33, 0x6b0 ], symbols[3]= [ 0x33, 0x23, 0xa3, NoSymbol, 0xb3, 0xa3, NoSymbol, NoSymbol ], symbols[4]= [ 0x33, 0x1002113, 0xb3, 0x1002083, 0x6b0, NoSymbol, 0x8de, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x34, 0x24 ], symbols[2]= [ 0x34, 0x3b ], symbols[3]= [ 0x34, 0x24, 0xa2, NoSymbol, 0xbc, 0xa4, NoSymbol, NoSymbol ], symbols[4]= [ 0x34, 0xbb, 0x100203a, 0xaf8, NoSymbol, NoSymbol, 0x10022a5, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x35, 0x25 ], symbols[2]= [ 0x35, 0x25 ], symbols[3]= [ 0x35, 0x25, 0xa4, NoSymbol, 0xbd, 0xac4, NoSymbol, NoSymbol ], symbols[4]= [ 0x35, 0xab, 0x1002039, 0xaf7, 0xb7, NoSymbol, 0x1002221, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ {0x48,0x45,0x4c,0x4c,0x4f}, 0x5e ], symbols[2]= [ 0x36, 0x3a ], symbols[3]= [ 0x36, 0x3f, 0xac, NoSymbol, 0xbe, 0xac5, NoSymbol, NoSymbol ], symbols[4]= [ 0x36, 0x24, 0xa2, 0x10026a5, 0xa3, NoSymbol, 0x1002225, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ {0x59,0x45,0x53,0x20,0x54,0x48,0x49,0x53,0x20,0x49,0x53,0x20,0x44,0x4f,0x47}, 0x26 ], symbols[2]= [ 0x37, 0x3f ], symbols[3]= [ 0x37, 0x26, 0x7b, NoSymbol, NoSymbol, 0xac6, NoSymbol, NoSymbol ], symbols[4]= [ 0x37, 0x20ac, 0xa5, 0x10003f0, 0xa4, NoSymbol, 0x8fd, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x38, 0x2a ], symbols[2]= [ 0x38, 0x2a ], symbols[3]= [ 0x38, 0x2a, 0x7d, NoSymbol, NoSymbol, 0xac9, NoSymbol, NoSymbol ], symbols[4]= [ 0x38, 0xafe, 0xafd, 0x10027e8, 0xff09, 0xfe20, 0x100221e, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x39, 0x28 ], symbols[2]= [ 0x39, 0x28 ], symbols[3]= [ 0x39, 0x28, 0x5b, NoSymbol, NoSymbol, 0xb1, NoSymbol, NoSymbol ], symbols[4]= [ 0x39, 0xad2, 0xad0, 0x10027e9, 0xffaf, 0xffaf, 0x8c1, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x30, 0x29 ], symbols[2]= [ 0x30, 0x29 ], symbols[3]= [ 0x30, 0x29, 0x5d, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 0x30, 0xad3, 0xad1, 0x1002080, 0xffaa, 0xffaa, 0x1002205, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x2d, 0x5f ], symbols[2]= [ 0x2d, 0x5f ], symbols[3]= [ 0x2d, 0x5f, 0xbd, NoSymbol, NoSymbol, 0xbf, NoSymbol, NoSymbol ], symbols[4]= [ 0x2d, 0xaa9, NoSymbol, 0x1002011, 0xffad, 0xffad, 0xad, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x3d, 0x2b ], symbols[2]= [ 0x3d, 0x2b ], symbols[3]= [ 0x3d, 0x2b, 0xac, NoSymbol, 0xfe5b, 0xfe5c, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe50, 0xfe5b, 0xfe58, 0xfe65, 0xfe57, NoSymbol, 0xfe54, NoSymbol ] }; key { [ 0xff08, 0xff08 ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff09, 0xfe20 ], symbols[2]= [ 0xff09, 0xfe20 ], symbols[3]= [ 0xff09, 0xfe20 ], symbols[4]= [ 0xff09, 0xfe20, 0xff20, 0xfe13, NoSymbol, NoSymbol, NoSymbol, 0xfe13 ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x71, 0x51 ], symbols[2]= [ 0x6ca, 0x6ea ], symbols[3]= [ 0x71, 0x51, NoSymbol, NoSymbol, NoSymbol, 0x7d9, NoSymbol, NoSymbol ], symbols[4]= [ 0x78, 0x58, 0xaae, 0x7ee, 0xff55, 0xff55, 0x7ce, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x77, 0x57 ], symbols[2]= [ 0x6c3, 0x6e3 ], symbols[3]= [ 0x77, 0x57, NoSymbol, NoSymbol, 0x1b3, 0x1a3, NoSymbol, NoSymbol ], symbols[4]= [ 0x76, 0x56, 0x5f, NoSymbol, 0xff08, 0xff08, 0x8d6, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x65, 0x45 ], symbols[2]= [ 0x6d5, 0x6f5 ], symbols[3]= [ 0x65, 0x45, NoSymbol, NoSymbol, 0x13bd, 0x13bc, NoSymbol, NoSymbol ], symbols[4]= [ 0x6c, 0x4c, 0x5b, 0x7eb, 0xff52, 0xff52, 0x7cb, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x72, 0x52 ], symbols[2]= [ 0x6cb, 0x6eb ], symbols[3]= [ 0x72, 0x52, NoSymbol, NoSymbol, 0xb6, 0xae, NoSymbol, NoSymbol ], symbols[4]= [ 0x63, 0x43, 0x5d, 0x7f7, 0xffff, 0xffff, 0x1002102, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x74, 0x54 ], symbols[2]= [ 0x6c5, 0x6e5 ], symbols[3]= [ 0x74, 0x54, NoSymbol, NoSymbol, 0x3bc, 0x3ac, NoSymbol, NoSymbol ], symbols[4]= [ 0x77, 0x57, 0x5e, 0x7f9, 0xff56, 0xff56, 0x7d9, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x79, 0x59 ], symbols[2]= [ 0x6ce, 0x6ee ], symbols[3]= [ 0x79, 0x59, NoSymbol, NoSymbol, 0x8fb, 0xa5, NoSymbol, NoSymbol ], symbols[4]= [ 0x6b, 0x4b, 0x21, 0x7ea, 0xa1, NoSymbol, 0xd7, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x75, 0x55 ], symbols[2]= [ 0x6c7, 0x6e7 ], symbols[3]= [ 0x75, 0x55, NoSymbol, NoSymbol, 0x8fe, 0x8fc, NoSymbol, NoSymbol ], symbols[4]= [ 0x68, 0x48, 0x3c, 0x7f8, 0xffb7, 0xffb7, 0x7d8, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x69, 0x49 ], symbols[2]= [ 0x6db, 0x6fb ], symbols[3]= [ 0x69, 0x49, NoSymbol, NoSymbol, 0x8fd, 0x2b9, NoSymbol, NoSymbol ], symbols[4]= [ 0x67, 0x47, 0x3e, 0x7e3, 0xffb8, 0xffb8, 0x7c3, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6f, 0x4f ], symbols[2]= [ 0x6dd, 0x6fd ], symbols[3]= [ 0x6f, 0x4f, 0xa7, NoSymbol, 0xf8, 0xd8, NoSymbol, NoSymbol ], symbols[4]= [ 0x66, 0x46, 0x3d, 0x7f6, 0xffb9, 0xffb9, 0x7d6, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x70, 0x50 ], symbols[2]= [ 0x6da, 0x6fa ], symbols[3]= [ 0x70, 0x50, 0xb6, NoSymbol, 0xfe, 0xde, NoSymbol, NoSymbol ], symbols[4]= [ 0x71, 0x51, 0x26, 0x10003d5, 0xffab, 0xffab, 0x100211a, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x5b, 0x7b ], symbols[2]= [ 0x6c8, 0x6e8 ], symbols[3]= [ 0xfe52, 0xfe57, 0xfe50, NoSymbol, NoSymbol, 0xfe58, NoSymbol, NoSymbol ], symbols[4]= [ 0xdf, 0x1001e9e, 0x100017f, 0x7f3, 0x1002212, NoSymbol, 0xbca, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x5d, 0x7d ], symbols[2]= [ 0x6df, 0x6ff ], symbols[3]= [ 0xe7, 0xc7, 0x7e, NoSymbol, 0xfe53, 0xfe54, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe51, 0xfe53, 0xfe63, 0xfe64, 0xfe59, NoSymbol, 0xfe55, NoSymbol ] }; key { [ 0xff0d ] }; key { [ 0xffe3 ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x61, 0x41 ], symbols[2]= [ 0x6c6, 0x6e6 ], symbols[3]= [ 0x61, 0x41, NoSymbol, NoSymbol, 0xe6, 0xc6, NoSymbol, NoSymbol ], symbols[4]= [ 0x75, 0x55, 0x5c, NoSymbol, 0xff50, 0xff50, 0x8da, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x73, 0x53 ], symbols[2]= [ 0x6d9, 0x6f9 ], symbols[3]= [ 0x73, 0x53, NoSymbol, NoSymbol, 0xdf, 0xa7, NoSymbol, NoSymbol ], symbols[4]= [ 0x69, 0x49, 0x2f, 0x7e9, 0xff51, 0xff51, 0x8bf, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x64, 0x44 ], symbols[2]= [ 0x6d7, 0x6f7 ], symbols[3]= [ 0x64, 0x44, NoSymbol, NoSymbol, 0xf0, 0xd0, NoSymbol, NoSymbol ], symbols[4]= [ 0x61, 0x41, 0x7b, 0x7e1, 0xff54, 0xff54, 0x1002200, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x66, 0x46 ], symbols[2]= [ 0x6c1, 0x6e1 ], symbols[3]= [ 0x66, 0x46, NoSymbol, NoSymbol, NoSymbol, 0xaa, NoSymbol, NoSymbol ], symbols[4]= [ 0x65, 0x45, 0x7d, 0x7e5, 0xff53, 0xff53, 0x1002203, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x67, 0x47 ], symbols[2]= [ 0x6d0, 0x6f0 ], symbols[3]= [ 0x67, 0x47, NoSymbol, NoSymbol, 0x3bf, 0x3bd, NoSymbol, NoSymbol ], symbols[4]= [ 0x6f, 0x4f, 0x2a, 0x7ef, 0xff57, 0xff57, 0x1002208, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x68, 0x48 ], symbols[2]= [ 0x6d2, 0x6f2 ], symbols[3]= [ 0x68, 0x48, NoSymbol, NoSymbol, 0x2b1, 0x2a1, NoSymbol, NoSymbol ], symbols[4]= [ 0x73, 0x53, 0x3f, 0x7f2, 0xbf, NoSymbol, 0x7d2, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6a, 0x4a ], symbols[2]= [ 0x6cf, 0x6ef ], symbols[3]= [ 0x6a, 0x4a, NoSymbol, NoSymbol, 0x1000133, 0x1000132, NoSymbol, NoSymbol ], symbols[4]= [ 0x6e, 0x4e, 0x28, 0x7ed, 0xffb4, 0xffb4, 0x1002115, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6b, 0x4b ], symbols[2]= [ 0x6cc, 0x6ec ], symbols[3]= [ 0x6b, 0x4b, NoSymbol, NoSymbol, 0x3a2, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 0x72, 0x52, 0x29, 0x7f1, 0xffb5, 0xffb5, 0x100211d, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6c, 0x4c ], symbols[2]= [ 0x6c4, 0x6e4 ], symbols[3]= [ 0x6c, 0x4c, NoSymbol, NoSymbol, 0x1000140, 0x100013f, NoSymbol, NoSymbol ], symbols[4]= [ 0x74, 0x54, 0x2d, 0x7f4, 0xffb6, 0xffb6, 0x8ef, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x3b, 0x3a ], symbols[2]= [ 0x6d6, 0x6f6 ], symbols[3]= [ 0x3b, 0x3a, 0xb0, NoSymbol, 0xfe51, 0xfe59, NoSymbol, NoSymbol ], symbols[4]= [ 0x64, 0x44, 0x3a, 0x7e4, 0xffac, 0x2c, 0x7c4, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x27, 0x22 ], symbols[2]= [ 0x6dc, 0x6fc ], symbols[3]= [ 0xe8, 0xc8, 0x7b, NoSymbol, NoSymbol, 0xfe5a, NoSymbol, NoSymbol ], symbols[4]= [ 0x79, 0x59, 0x40, 0x7f5, 0x2e, 0xffae, 0x8c5, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x60, 0x7e ], symbols[2]= [ 0x6a3, 0x6b3 ], symbols[3]= [ 0x2f, 0x5c, 0x7c, NoSymbol, NoSymbol, 0xad, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe52, 0xfe5a, 0x10021bb, 0x10002de, 0xfe56, 0xfef9, 0xfe60, NoSymbol ] }; key { type[4]= "TWO_LEVEL", symbols[1]= [ 0xffe1 ], symbols[2]= [ 0xffe1 ], symbols[3]= [ 0xffe1 ], symbols[4]= [ 0xffe1, 0xffe5 ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "ONE_LEVEL", symbols[1]= [ 0x5c, 0x7c ], symbols[2]= [ 0x5c, 0x2f ], symbols[3]= [ 0xe0, 0xc0, 0x7d, NoSymbol, NoSymbol, 0xfe55, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe03 ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "FOUR_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x7a, 0x5a ], symbols[2]= [ 0x6d1, 0x6f1 ], symbols[3]= [ 0x7a, 0x5a, 0xab, NoSymbol ], symbols[4]= [ 0xfc, 0xdc, 0x23, NoSymbol, 0xff1b, 0xff1b, 0x8dd, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "FOUR_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x78, 0x58 ], symbols[2]= [ 0x6de, 0x6fe ], symbols[3]= [ 0x78, 0x58, 0xbb, NoSymbol ], symbols[4]= [ 0xf6, 0xd6, 0x24, 0x10003f5, 0xff09, 0xff09, 0x8dc, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x63, 0x43 ], symbols[2]= [ 0x6d3, 0x6f3 ], symbols[3]= [ 0x63, 0x43, NoSymbol, NoSymbol, 0xa2, 0xa9, NoSymbol, NoSymbol ], symbols[4]= [ 0xe4, 0xc4, 0x7c, 0x7e7, 0xff63, 0xff63, 0x1002135, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x76, 0x56 ], symbols[2]= [ 0x6cd, 0x6ed ], symbols[3]= [ 0x76, 0x56, NoSymbol, NoSymbol, 0xad2, 0xad0, NoSymbol, NoSymbol ], symbols[4]= [ 0x70, 0x50, 0x7e, 0x7f0, 0xff0d, 0xff0d, 0x7d0, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x62, 0x42 ], symbols[2]= [ 0x6c9, 0x6e9 ], symbols[3]= [ 0x62, 0x42, NoSymbol, NoSymbol, 0xad3, 0xad1, NoSymbol, NoSymbol ], symbols[4]= [ 0x7a, 0x5a, 0x60, 0x7e6, 0xff65, 0xff65, 0x1002124, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6e, 0x4e ], symbols[2]= [ 0x6d4, 0x6f4 ], symbols[3]= [ 0x6e, 0x4e, NoSymbol, NoSymbol, 0x1000149, 0x100266a, NoSymbol, NoSymbol ], symbols[4]= [ 0x62, 0x42, 0x2b, 0x7e2, 0x3a, NoSymbol, 0x10021d0, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6d, 0x4d ], symbols[2]= [ 0x6d8, 0x6f8 ], symbols[3]= [ 0x6d, 0x4d, 0xb5, NoSymbol, 0xb5, 0xba, NoSymbol, NoSymbol ], symbols[4]= [ 0x6d, 0x4d, 0x25, 0x7ec, 0xffb1, 0xffb1, 0x8cd, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x2c, 0x3c ], symbols[2]= [ 0x6c2, 0x6e2 ], symbols[3]= [ 0x2c, 0x27, 0x3c, NoSymbol, 0x7af, 0xd7, NoSymbol, NoSymbol ], symbols[4]= [ 0x2c, 0xaaa, 0x22, 0x10003f1, 0xffb2, 0xffb2, 0x10021d2, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x2e, 0x3e ], symbols[2]= [ 0x6c0, 0x6e0 ], symbols[3]= [ 0x2e, 0x22, 0x3e, NoSymbol, 0xb7, 0xf7, NoSymbol, NoSymbol ], symbols[4]= [ 0x2e, 0xae6, 0x27, 0x10003d1, 0xffb3, 0xffb3, 0x10021a6, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x2f, 0x3f ], symbols[2]= [ 0x2e, 0x2c ], symbols[3]= [ 0xe9, 0xc9, 0xfe51, NoSymbol, NoSymbol, 0xfe56, NoSymbol, NoSymbol ], symbols[4]= [ 0x6a, 0x4a, 0x3b, 0x7e8, 0x3b, NoSymbol, 0x7c8, NoSymbol ] }; key { type[4]= "TWO_LEVEL", symbols[1]= [ 0xffe2 ], symbols[2]= [ 0xffe2 ], symbols[3]= [ 0xffe2 ], symbols[4]= [ 0xffe2, 0xffe5 ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffaa, 0xffaa, 0xffaa, 0xffaa, 0x1008fe21 ], symbols[2]= [ 0xffaa, 0xffaa, 0xffaa, 0xffaa, 0x1008fe21 ], symbols[3]= [ 0xffaa, 0xffaa, 0xffaa, 0xffaa, 0x1008fe21 ], symbols[4]= [ 0xffaa, 0xffaa, 0x1002219, 0x1002299, 0xd7, NoSymbol, 0x1002297, NoSymbol ] }; key { [ 0xffe9, 0xffe7 ] }; key { type[3]= "FOUR_LEVEL", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x20 ], symbols[2]= [ 0x20 ], symbols[3]= [ 0x20, 0x20, 0xa0, NoSymbol ], symbols[4]= [ 0x20, 0x20, 0x20, 0xa0, 0xffb0, 0xffb0, 0x100202f, NoSymbol ] }; key { type= "ONE_LEVEL", symbols[1]= [ 0xffe5 ], symbols[2]= [ 0xffe5 ], symbols[3]= [ 0xffe5 ], symbols[4]= [ 0xfe03 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffbe, 0xffbe, 0xffbe, 0xffbe, 0x1008fe01 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffbf, 0xffbf, 0xffbf, 0xffbf, 0x1008fe02 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0x1008fe03 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc1, 0xffc1, 0xffc1, 0xffc1, 0x1008fe04 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc2, 0xffc2, 0xffc2, 0xffc2, 0x1008fe05 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc3, 0xffc3, 0xffc3, 0xffc3, 0x1008fe06 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc4, 0xffc4, 0xffc4, 0xffc4, 0x1008fe07 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc5, 0xffc5, 0xffc5, 0xffc5, 0x1008fe08 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc6, 0xffc6, 0xffc6, 0xffc6, 0x1008fe09 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc7, 0xffc7, 0xffc7, 0xffc7, 0x1008fe0a ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff7f ], symbols[2]= [ 0xff7f ], symbols[3]= [ 0xff7f ], symbols[4]= [ 0xff09, 0xfe20, 0x3d, 0x1002248, 0x8bd, 0xfef9, 0x8cf, NoSymbol ] }; key { [ 0xff14 ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff95, 0xffb7 ], symbols[2]= [ 0xff95, 0xffb7 ], symbols[3]= [ 0xff95, 0xffb7 ], symbols[4]= [ 0xffb7, 0x1002714, 0x1002195, 0x100226a, 0xff95, 0xff95, 0xbd3, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff97, 0xffb8 ], symbols[2]= [ 0xff97, 0xffb8 ], symbols[3]= [ 0xff97, 0xffb8 ], symbols[4]= [ 0xffb8, 0x1002718, 0x8fc, 0x8dc, 0xff97, 0xff97, 0x10022c2, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9a, 0xffb9 ], symbols[2]= [ 0xff9a, 0xffb9 ], symbols[3]= [ 0xff9a, 0xffb9 ], symbols[4]= [ 0xffb9, 0xaf1, 0x10020d7, 0x100226b, 0xff9a, 0xff9a, 0x1002309, NoSymbol ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffad, 0xffad, 0xffad, 0xffad, 0x1008fe23 ], symbols[2]= [ 0xffad, 0xffad, 0xffad, 0xffad, 0x1008fe23 ], symbols[3]= [ 0xffad, 0xffad, 0xffad, 0xffad, 0x1008fe23 ], symbols[4]= [ 0xffad, 0xffad, 0x1002212, 0x1002296, 0x1002216, NoSymbol, 0x1002238, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff96, 0xffb4 ], symbols[2]= [ 0xff96, 0xffb4 ], symbols[3]= [ 0xff96, 0xffb4 ], symbols[4]= [ 0xffb4, 0xaec, 0x8fb, 0x8da, 0xff96, 0xff96, 0x1002286, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9d, 0xffb5 ], symbols[2]= [ 0xff9d, 0xffb5 ], symbols[3]= [ 0xff9d, 0xffb5 ], symbols[4]= [ 0xffb5, 0x20ac, 0x3a, 0x10022b6, 0xff9d, 0xff9d, 0x10022b7, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff98, 0xffb6 ], symbols[2]= [ 0xff98, 0xffb6 ], symbols[3]= [ 0xff98, 0xffb6 ], symbols[4]= [ 0xffb6, 0x1002023, 0x8fd, 0x8db, 0xff98, 0xff98, 0x1002287, NoSymbol ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffab, 0xffab, 0xffab, 0xffab, 0x1008fe22 ], symbols[2]= [ 0xffab, 0xffab, 0xffab, 0xffab, 0x1008fe22 ], symbols[3]= [ 0xffab, 0xffab, 0xffab, 0xffab, 0x1008fe22 ], symbols[4]= [ 0xffab, 0xffab, 0xb1, 0x1002295, 0x1002213, NoSymbol, 0x1002214, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9c, 0xffb1 ], symbols[2]= [ 0xff9c, 0xffb1 ], symbols[3]= [ 0xff9c, 0xffb1 ], symbols[4]= [ 0xffb1, 0xaed, 0x1002194, 0x8bc, 0xff9c, 0xff9c, 0xbc4, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff99, 0xffb2 ], symbols[2]= [ 0xff99, 0xffb2 ], symbols[3]= [ 0xff99, 0xffb2 ], symbols[4]= [ 0xffb2, 0xaee, 0x8fe, 0x8dd, 0xff99, 0xff99, 0x10022c3, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9b, 0xffb3 ], symbols[2]= [ 0xff9b, 0xffb3 ], symbols[3]= [ 0xff9b, 0xffb3 ], symbols[4]= [ 0xffb3, 0x1002660, 0x10021cc, 0x8be, 0xff9b, 0xff9b, 0x100230b, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9e, 0xffb0 ], symbols[2]= [ 0xff9e, 0xffb0 ], symbols[3]= [ 0xff9e, 0xffb0 ], symbols[4]= [ 0xffb0, 0x1002423, 0x25, 0x1002030, 0xff9e, 0xff9e, 0x10025a1, NoSymbol ] }; key { type[2]= "KEYPAD", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9f, 0xffae ], symbols[2]= [ 0xff9f, 0xffac ], symbols[3]= [ 0xff9f, 0xffae ], symbols[4]= [ 0xffac, 0x2e, 0x2c, 0xad6, 0xff9f, 0xff9f, 0xad7, NoSymbol ] }; key { [ 0xfe03 ] }; key { type[1]= "FOUR_LEVEL", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "ONE_LEVEL", symbols[1]= [ 0x3c, 0x3e, 0x7c, 0xa6 ], symbols[2]= [ 0x2f, 0x7c ], symbols[3]= [ 0xf9, 0xd9, 0xb0, NoSymbol, NoSymbol, 0xa6, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe11 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc8, 0xffc8, 0xffc8, 0xffc8, 0x1008fe0b ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc9, 0xffc9, 0xffc9, 0xffc9, 0x1008fe0c ] }; key { [ 0xff26 ] }; key { [ 0xff25 ] }; key { [ 0xff23 ] }; key { [ 0xff27 ] }; key { [ 0xff22 ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff8d ], symbols[2]= [ 0xff8d ], symbols[3]= [ 0xff8d ], symbols[4]= [ 0xff8d, 0xff8d, 0xff8d, 0xff8d, 0xff8d, 0xff8d, 0xff8d, NoSymbol ] }; key { type= "ONE_LEVEL", symbols[1]= [ 0xffe4 ], symbols[2]= [ 0xffe4 ], symbols[3]= [ 0xfe11 ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffaf, 0xffaf, 0xffaf, 0xffaf, 0x1008fe20 ], symbols[2]= [ 0xffaf, 0xffaf, 0xffaf, 0xffaf, 0x1008fe20 ], symbols[3]= [ 0xffaf, 0xffaf, 0xffaf, 0xffaf, 0x1008fe20 ], symbols[4]= [ 0xffaf, 0xffaf, 0xf7, 0x1002300, 0x1002215, NoSymbol, 0x1002223, NoSymbol ] }; key { type= "PC_ALT_LEVEL2", symbols[1]= [ 0xff61, 0xff15 ] }; key { type[1]= "TWO_LEVEL", type[2]= "TWO_LEVEL", type[3]= "ONE_LEVEL", type[4]= "ONE_LEVEL", symbols[1]= [ 0xffea, 0xffe8 ], symbols[2]= [ 0xffea, 0xffe8 ], symbols[3]= [ 0xfe03 ], symbols[4]= [ 0xfe11 ] }; key { [ 0xff0a ] }; key { [ 0xff50 ] }; key { [ 0xff52 ] }; key { [ 0xff55 ] }; key { [ 0xff51 ] }; key { [ 0xff53 ] }; key { [ 0xff57 ] }; key { [ 0xff54 ] }; key { [ 0xff56 ] }; key { [ 0xff63 ] }; key { [ 0xffff ] }; key { [ 0x1008ff12 ] }; key { [ 0x1008ff11 ] }; key { [ 0x1008ff13 ] }; key { [ 0x1008ff2a ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffbd ], symbols[2]= [ 0xffbd ], symbols[3]= [ 0xffbd ], symbols[4]= [ 0xffbd, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; key { [ 0xb1 ] }; key { type= "PC_CONTROL_LEVEL2", symbols[1]= [ 0xff13, 0xff6b ] }; key { [ 0x1008ff4a ] }; key { [ 0xffae, 0xffae ] }; key { [ 0xff31 ] }; key { [ 0xff34 ] }; key { [ 0xffeb ] }; key { [ 0xffec ] }; key { [ 0xff67 ] }; key { [ 0xff69 ] }; key { [ 0xff66 ] }; key { [ 0x1005ff70 ] }; key { [ 0xff65 ] }; key { [ 0x1005ff71 ] }; key { [ 0x1008ff57 ] }; key { [ 0x1005ff73 ] }; key { [ 0x1008ff6d ] }; key { [ 0xff68 ] }; key { [ 0x1008ff58 ] }; key { [ 0xff6a ] }; key { [ 0x1008ff65 ] }; key { [ 0x1008ff1d ] }; key { [ 0x1008ff2f ] }; key { [ 0x1008ff2b ] }; key { [ 0x1008ff5d ] }; key { [ 0x1008ff7b ] }; key { [ 0x1008ff8a ] }; key { [ 0x1008ff41 ] }; key { [ 0x1008ff42 ] }; key { [ 0x1008ff2e ] }; key { [ 0x1008ff5a ] }; key { [ 0x1008ff2d ] }; key { [ 0x1008ff74 ] }; key { [ 0x1008ff19 ] }; key { [ 0x1008ff30 ] }; key { [ 0x1008ff33 ] }; key { [ 0x1008ff26 ] }; key { [ 0x1008ff27 ] }; key { [ 0x1008ff2c ] }; key { [ 0x1008ff2c, 0x1008ff2c ] }; key { [ 0x1008ff17 ] }; key { [ 0x1008ff14, 0x1008ff31 ] }; key { [ 0x1008ff16 ] }; key { [ 0x1008ff15, 0x1008ff2c ] }; key { [ 0x1008ff1c ] }; key { [ 0x1008ff3e ] }; key { [ 0x1008ff6e ] }; key { [ 0x1008ff81 ] }; key { [ 0x1008ff18 ] }; key { [ 0x1008ff73 ] }; key { [ 0x1008ff56 ] }; key { [ 0x1008ff78 ] }; key { [ 0x1008ff79 ] }; key { [ 0x28 ] }; key { [ 0x29 ] }; key { [ 0x1008ff68 ] }; key { [ 0xff66 ] }; key { [ 0x1008ff81 ] }; key { [ 0x1008ff45 ] }; key { [ 0x1008ff46 ] }; key { [ 0x1008ff47 ] }; key { [ 0x1008ff48 ] }; key { [ 0x1008ff49 ] }; key { [ 0x1008ffa9 ] }; key { [ 0x1008ffb0 ] }; key { [ 0x1008ffb1 ] }; key { [ 0xff7e ] }; key { [ NoSymbol, 0xffe9 ] }; key { [ NoSymbol, 0xffe7 ] }; key { [ NoSymbol, 0xffeb ] }; key { [ NoSymbol, 0xffed ] }; key { [ 0x1008ff14 ] }; key { [ 0x1008ff31 ] }; key { [ 0x1008ff43 ] }; key { [ 0x1008ff44 ] }; key { [ 0x1008ff4b ] }; key { [ 0x1008ffa7 ] }; key { [ 0x1008ff56 ] }; key { [ 0x1008ff14 ] }; key { [ 0x1008ff97 ] }; key { [ 0xff61 ] }; key { [ 0x1008ff8f ] }; key { [ 0x1008ff19 ] }; key { [ 0x1008ff8e ] }; key { [ 0x1008ff1b ] }; key { [ 0x1008ff5f ] }; key { [ 0x1008ff3c ] }; key { [ 0x1008ff5e ] }; key { [ 0x1008ff36 ] }; key { [ 0xff69 ] }; key { [ 0x1008ff03 ] }; key { [ 0x1008ff02 ] }; key { [ 0x1008ff32 ] }; key { [ 0x1008ff59 ] }; key { [ 0x1008ff04 ] }; key { [ 0x1008ff06 ] }; key { [ 0x1008ff05 ] }; key { [ 0x1008ff7b ] }; key { [ 0x1008ff72 ] }; key { [ 0x1008ff90 ] }; key { [ 0x1008ff77 ] }; key { [ 0x1008ff5b ] }; key { [ 0x1008ff93 ] }; key { [ 0x1008ff94 ] }; key { [ 0x1008ff95 ] }; modifier_map Shift { , }; modifier_map Lock { }; modifier_map Control { }; modifier_map Mod1 { , , }; modifier_map Mod2 { }; modifier_map Mod3 { }; modifier_map Mod4 { , , , }; modifier_map Mod5 { , }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/stringcomp-v1-no-prettyfied.xkb000066400000000000000000001506011510033435100302350ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev_aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; indicator 12 = "Shift Lock"; indicator 13 = "Group 2"; indicator 14 = "Mouse Keys"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt=Mod1,RAlt=0x100,RControl=0x210001,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= 2; level_name[1]= "Base"; level_name[2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= 2; level_name[1]= "Base"; level_name[2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= 2; level_name[1]= "Base"; level_name[2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= 2; level_name[1]= "Base"; level_name[2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= 2; level_name[1]= "Base"; level_name[2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= 2; level_name[1]= "Base"; level_name[2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= 2; level_name[1]= "Base"; level_name[2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Control+Alt]= 5; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+Lock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Control]= 5; map[Shift+Lock+Control]= 5; map[Shift+Control]= 6; map[Lock+Control]= 6; map[Control+LevelThree]= 7; map[Shift+Lock+Control+LevelThree]= 7; map[Shift+Control+LevelThree]= 8; map[Lock+Control+LevelThree]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Level3"; level_name[4]= "Shift Level3"; level_name[5]= "Ctrl"; level_name[6]= "Shift Ctrl"; level_name[7]= "Level3 Ctrl"; level_name[8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 8; map[Shift+Lock+LevelThree+LevelFive]= 7; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; preserve[Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= 8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelFive]= 1; preserve[Shift+Lock+LevelFive]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= 2; map[Shift]= 2; map[LevelThree]= 3; map[NumLock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= 2; map[Shift+LevelThree]= 3; map[Control+Alt]= 4; level_name[1]= "Base"; level_name[2]= "Alt Base"; level_name[3]= "Shift Alt"; level_name[4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 4; preserve[Lock]= Lock; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr Base"; level_name[4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock]= 5; map[Shift+Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Lock"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= 2; map[NumLock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[NumLock+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Alt Number"; }; }; xkb_compatibility "complete_caps(caps_lock)_4_misc(assign_shift_left_action)_4_level5(level5_lock)_4" { virtual_modifiers NumLock,Alt,LevelThree,LAlt=Mod1,RAlt=0x100,RControl=0x210001,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret 0xfe02+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret 0xffe6+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret 0xff7f+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret 0xfe01+AnyOf(all) { action= NoAction(); }; interpret 0xfe03+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret 0xfe04+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret 0xfe05+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret 0xffe9+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffea+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffe7+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffe8+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffeb+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffec+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffed+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xffee+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret 0xff14+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret 0xfe11+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret 0xfe12+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret 0xfe13+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret 0xff7e+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret 0xfe03+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret 0xfe04+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret 0xfe05+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret 0xfe06+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret 0xfe08+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret 0xfe0a+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret 0xfe0c+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret 0xfe0e+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret 0xffb1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret 0xff9c+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret 0xffb2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret 0xff99+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret 0xffb3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret 0xff9b+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret 0xffb4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret 0xff96+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret 0xffb6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret 0xff98+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret 0xffb7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret 0xff95+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret 0xffb8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret 0xff97+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret 0xffb9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret 0xff9a+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret 0xffb5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret 0xff9d+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret 0xff92+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret 0xffaf+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret 0xff93+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret 0xffaa+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret 0xff94+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret 0xffad+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret 0xffac+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret 0xffab+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret 0xffb0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret 0xff9e+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret 0xffae+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret 0xff9f+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret 0xffd6+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret 0xffd7+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret 0xffd8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret 0xffda+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret 0xffdc+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret 0xffde+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret 0xffe0+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret 0xfee8+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret 0xfee9+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret 0xfeea+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret 0xfeeb+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret 0xfeee+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret 0xfeef+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret 0xfef0+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret 0xfef1+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret 0xfef4+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret 0xfef5+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret 0xfef6+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret 0xfef7+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret 0xfef9+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret 0xfefa+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret 0xfefb+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret 0xfefc+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret 0xfe70+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret 0xfe71+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret 0xfe72+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret 0xfe73+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret 0xfe74+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret 0xfe75+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret 0xfe76+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret 0xfe77+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret 0xfe78+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret 0xfe79+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret 0xfe7a+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret 0xfed5+AnyOfOrNone(all) { action= Terminate(); }; interpret 0xffe9+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret 0xffea+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret 0xffe7+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret 0xffe8+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret 0xffeb+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret 0xffec+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret 0xffed+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret 0xffee+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret 0xffe1+AnyOfOrNone(all) { action= SetMods(modifiers=Shift); }; interpret 0x1008fe01+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret 0x1008fe02+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret 0x1008fe03+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret 0x1008fe04+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret 0x1008fe05+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret 0x1008fe06+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret 0x1008fe07+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret 0x1008fe08+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret 0x1008fe09+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret 0x1008fe0a+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret 0x1008fe0b+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret 0x1008fe0c+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret 0x1008fe25+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret 0x1008fe24+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret 0x1008fe22+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret 0x1008fe23+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret 0xfe11+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret 0xfe12+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret 0xfe13+AnyOfOrNone(all) { action= LockMods(modifiers=NumLock); }; interpret 0xffe5+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; indicator "Group 2" { groups= 0xfe; }; indicator "Mouse Keys" { controls= MouseKeys; }; }; xkb_symbols "pc_us_ru_2_ca(multix)_3_de(neo)_4_inet(evdev)" { name[1]="English (US)"; name[2]="Russian"; name[3]="Canadian Multilingual"; name[4]="German (Neo 2)"; key { [ 0xff1b ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x31, 0x21 ], symbols[2]= [ 0x31, 0x21 ], symbols[3]= [ 0x31, 0x21, 0xb1, NoSymbol, 0xb9, 0xa1, NoSymbol, NoSymbol ], symbols[4]= [ 0x31, 0xb0, 0xb9, 0x1002081, 0xaa, NoSymbol, 0xac, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x32, 0x40 ], symbols[2]= [ 0x32, 0x22 ], symbols[3]= [ 0x32, 0x40, 0x40, NoSymbol, 0xb2, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 0x32, 0xa7, 0xb2, 0x1002082, 0xba, NoSymbol, 0x8df, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x33, 0x23 ], symbols[2]= [ 0x33, 0x6b0 ], symbols[3]= [ 0x33, 0x23, 0xa3, NoSymbol, 0xb3, 0xa3, NoSymbol, NoSymbol ], symbols[4]= [ 0x33, 0x1002113, 0xb3, 0x1002083, 0x6b0, NoSymbol, 0x8de, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x34, 0x24 ], symbols[2]= [ 0x34, 0x3b ], symbols[3]= [ 0x34, 0x24, 0xa2, NoSymbol, 0xbc, 0xa4, NoSymbol, NoSymbol ], symbols[4]= [ 0x34, 0xbb, 0x100203a, 0xaf8, NoSymbol, NoSymbol, 0x10022a5, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x35, 0x25 ], symbols[2]= [ 0x35, 0x25 ], symbols[3]= [ 0x35, 0x25, 0xa4, NoSymbol, 0xbd, 0xac4, NoSymbol, NoSymbol ], symbols[4]= [ 0x35, 0xab, 0x1002039, 0xaf7, 0xb7, NoSymbol, 0x1002221, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ {0x48,0x45,0x4c,0x4c,0x4f}, 0x5e ], symbols[2]= [ 0x36, 0x3a ], symbols[3]= [ 0x36, 0x3f, 0xac, NoSymbol, 0xbe, 0xac5, NoSymbol, NoSymbol ], symbols[4]= [ 0x36, 0x24, 0xa2, 0x10026a5, 0xa3, NoSymbol, 0x1002225, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ {0x59,0x45,0x53,0x20,0x54,0x48,0x49,0x53,0x20,0x49,0x53,0x20,0x44,0x4f,0x47}, 0x26 ], symbols[2]= [ 0x37, 0x3f ], symbols[3]= [ 0x37, 0x26, 0x7b, NoSymbol, NoSymbol, 0xac6, NoSymbol, NoSymbol ], symbols[4]= [ 0x37, 0x20ac, 0xa5, 0x10003f0, 0xa4, NoSymbol, 0x8fd, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x38, 0x2a ], symbols[2]= [ 0x38, 0x2a ], symbols[3]= [ 0x38, 0x2a, 0x7d, NoSymbol, NoSymbol, 0xac9, NoSymbol, NoSymbol ], symbols[4]= [ 0x38, 0xafe, 0xafd, 0x10027e8, 0xff09, 0xfe20, 0x100221e, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x39, 0x28 ], symbols[2]= [ 0x39, 0x28 ], symbols[3]= [ 0x39, 0x28, 0x5b, NoSymbol, NoSymbol, 0xb1, NoSymbol, NoSymbol ], symbols[4]= [ 0x39, 0xad2, 0xad0, 0x10027e9, 0xffaf, 0xffaf, 0x8c1, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x30, 0x29 ], symbols[2]= [ 0x30, 0x29 ], symbols[3]= [ 0x30, 0x29, 0x5d, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 0x30, 0xad3, 0xad1, 0x1002080, 0xffaa, 0xffaa, 0x1002205, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x2d, 0x5f ], symbols[2]= [ 0x2d, 0x5f ], symbols[3]= [ 0x2d, 0x5f, 0xbd, NoSymbol, NoSymbol, 0xbf, NoSymbol, NoSymbol ], symbols[4]= [ 0x2d, 0xaa9, NoSymbol, 0x1002011, 0xffad, 0xffad, 0xad, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x3d, 0x2b ], symbols[2]= [ 0x3d, 0x2b ], symbols[3]= [ 0x3d, 0x2b, 0xac, NoSymbol, 0xfe5b, 0xfe5c, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe50, 0xfe5b, 0xfe58, 0xfe65, 0xfe57, NoSymbol, 0xfe54, NoSymbol ] }; key { [ 0xff08, 0xff08 ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff09, 0xfe20 ], symbols[2]= [ 0xff09, 0xfe20 ], symbols[3]= [ 0xff09, 0xfe20 ], symbols[4]= [ 0xff09, 0xfe20, 0xff20, 0xfe13, NoSymbol, NoSymbol, NoSymbol, 0xfe13 ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x71, 0x51 ], symbols[2]= [ 0x6ca, 0x6ea ], symbols[3]= [ 0x71, 0x51, NoSymbol, NoSymbol, NoSymbol, 0x7d9, NoSymbol, NoSymbol ], symbols[4]= [ 0x78, 0x58, 0xaae, 0x7ee, 0xff55, 0xff55, 0x7ce, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x77, 0x57 ], symbols[2]= [ 0x6c3, 0x6e3 ], symbols[3]= [ 0x77, 0x57, NoSymbol, NoSymbol, 0x1b3, 0x1a3, NoSymbol, NoSymbol ], symbols[4]= [ 0x76, 0x56, 0x5f, NoSymbol, 0xff08, 0xff08, 0x8d6, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x65, 0x45 ], symbols[2]= [ 0x6d5, 0x6f5 ], symbols[3]= [ 0x65, 0x45, NoSymbol, NoSymbol, 0x13bd, 0x13bc, NoSymbol, NoSymbol ], symbols[4]= [ 0x6c, 0x4c, 0x5b, 0x7eb, 0xff52, 0xff52, 0x7cb, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x72, 0x52 ], symbols[2]= [ 0x6cb, 0x6eb ], symbols[3]= [ 0x72, 0x52, NoSymbol, NoSymbol, 0xb6, 0xae, NoSymbol, NoSymbol ], symbols[4]= [ 0x63, 0x43, 0x5d, 0x7f7, 0xffff, 0xffff, 0x1002102, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x74, 0x54 ], symbols[2]= [ 0x6c5, 0x6e5 ], symbols[3]= [ 0x74, 0x54, NoSymbol, NoSymbol, 0x3bc, 0x3ac, NoSymbol, NoSymbol ], symbols[4]= [ 0x77, 0x57, 0x5e, 0x7f9, 0xff56, 0xff56, 0x7d9, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x79, 0x59 ], symbols[2]= [ 0x6ce, 0x6ee ], symbols[3]= [ 0x79, 0x59, NoSymbol, NoSymbol, 0x8fb, 0xa5, NoSymbol, NoSymbol ], symbols[4]= [ 0x6b, 0x4b, 0x21, 0x7ea, 0xa1, NoSymbol, 0xd7, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x75, 0x55 ], symbols[2]= [ 0x6c7, 0x6e7 ], symbols[3]= [ 0x75, 0x55, NoSymbol, NoSymbol, 0x8fe, 0x8fc, NoSymbol, NoSymbol ], symbols[4]= [ 0x68, 0x48, 0x3c, 0x7f8, 0xffb7, 0xffb7, 0x7d8, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x69, 0x49 ], symbols[2]= [ 0x6db, 0x6fb ], symbols[3]= [ 0x69, 0x49, NoSymbol, NoSymbol, 0x8fd, 0x2b9, NoSymbol, NoSymbol ], symbols[4]= [ 0x67, 0x47, 0x3e, 0x7e3, 0xffb8, 0xffb8, 0x7c3, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6f, 0x4f ], symbols[2]= [ 0x6dd, 0x6fd ], symbols[3]= [ 0x6f, 0x4f, 0xa7, NoSymbol, 0xf8, 0xd8, NoSymbol, NoSymbol ], symbols[4]= [ 0x66, 0x46, 0x3d, 0x7f6, 0xffb9, 0xffb9, 0x7d6, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x70, 0x50 ], symbols[2]= [ 0x6da, 0x6fa ], symbols[3]= [ 0x70, 0x50, 0xb6, NoSymbol, 0xfe, 0xde, NoSymbol, NoSymbol ], symbols[4]= [ 0x71, 0x51, 0x26, 0x10003d5, 0xffab, 0xffab, 0x100211a, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x5b, 0x7b ], symbols[2]= [ 0x6c8, 0x6e8 ], symbols[3]= [ 0xfe52, 0xfe57, 0xfe50, NoSymbol, NoSymbol, 0xfe58, NoSymbol, NoSymbol ], symbols[4]= [ 0xdf, 0x1001e9e, 0x100017f, 0x7f3, 0x1002212, NoSymbol, 0xbca, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x5d, 0x7d ], symbols[2]= [ 0x6df, 0x6ff ], symbols[3]= [ 0xe7, 0xc7, 0x7e, NoSymbol, 0xfe53, 0xfe54, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe51, 0xfe53, 0xfe63, 0xfe64, 0xfe59, NoSymbol, 0xfe55, NoSymbol ] }; key { [ 0xff0d ] }; key { [ 0xffe3 ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x61, 0x41 ], symbols[2]= [ 0x6c6, 0x6e6 ], symbols[3]= [ 0x61, 0x41, NoSymbol, NoSymbol, 0xe6, 0xc6, NoSymbol, NoSymbol ], symbols[4]= [ 0x75, 0x55, 0x5c, NoSymbol, 0xff50, 0xff50, 0x8da, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x73, 0x53 ], symbols[2]= [ 0x6d9, 0x6f9 ], symbols[3]= [ 0x73, 0x53, NoSymbol, NoSymbol, 0xdf, 0xa7, NoSymbol, NoSymbol ], symbols[4]= [ 0x69, 0x49, 0x2f, 0x7e9, 0xff51, 0xff51, 0x8bf, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x64, 0x44 ], symbols[2]= [ 0x6d7, 0x6f7 ], symbols[3]= [ 0x64, 0x44, NoSymbol, NoSymbol, 0xf0, 0xd0, NoSymbol, NoSymbol ], symbols[4]= [ 0x61, 0x41, 0x7b, 0x7e1, 0xff54, 0xff54, 0x1002200, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x66, 0x46 ], symbols[2]= [ 0x6c1, 0x6e1 ], symbols[3]= [ 0x66, 0x46, NoSymbol, NoSymbol, NoSymbol, 0xaa, NoSymbol, NoSymbol ], symbols[4]= [ 0x65, 0x45, 0x7d, 0x7e5, 0xff53, 0xff53, 0x1002203, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x67, 0x47 ], symbols[2]= [ 0x6d0, 0x6f0 ], symbols[3]= [ 0x67, 0x47, NoSymbol, NoSymbol, 0x3bf, 0x3bd, NoSymbol, NoSymbol ], symbols[4]= [ 0x6f, 0x4f, 0x2a, 0x7ef, 0xff57, 0xff57, 0x1002208, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x68, 0x48 ], symbols[2]= [ 0x6d2, 0x6f2 ], symbols[3]= [ 0x68, 0x48, NoSymbol, NoSymbol, 0x2b1, 0x2a1, NoSymbol, NoSymbol ], symbols[4]= [ 0x73, 0x53, 0x3f, 0x7f2, 0xbf, NoSymbol, 0x7d2, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6a, 0x4a ], symbols[2]= [ 0x6cf, 0x6ef ], symbols[3]= [ 0x6a, 0x4a, NoSymbol, NoSymbol, 0x1000133, 0x1000132, NoSymbol, NoSymbol ], symbols[4]= [ 0x6e, 0x4e, 0x28, 0x7ed, 0xffb4, 0xffb4, 0x1002115, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6b, 0x4b ], symbols[2]= [ 0x6cc, 0x6ec ], symbols[3]= [ 0x6b, 0x4b, NoSymbol, NoSymbol, 0x3a2, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 0x72, 0x52, 0x29, 0x7f1, 0xffb5, 0xffb5, 0x100211d, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6c, 0x4c ], symbols[2]= [ 0x6c4, 0x6e4 ], symbols[3]= [ 0x6c, 0x4c, NoSymbol, NoSymbol, 0x1000140, 0x100013f, NoSymbol, NoSymbol ], symbols[4]= [ 0x74, 0x54, 0x2d, 0x7f4, 0xffb6, 0xffb6, 0x8ef, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x3b, 0x3a ], symbols[2]= [ 0x6d6, 0x6f6 ], symbols[3]= [ 0x3b, 0x3a, 0xb0, NoSymbol, 0xfe51, 0xfe59, NoSymbol, NoSymbol ], symbols[4]= [ 0x64, 0x44, 0x3a, 0x7e4, 0xffac, 0x2c, 0x7c4, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x27, 0x22 ], symbols[2]= [ 0x6dc, 0x6fc ], symbols[3]= [ 0xe8, 0xc8, 0x7b, NoSymbol, NoSymbol, 0xfe5a, NoSymbol, NoSymbol ], symbols[4]= [ 0x79, 0x59, 0x40, 0x7f5, 0x2e, 0xffae, 0x8c5, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x60, 0x7e ], symbols[2]= [ 0x6a3, 0x6b3 ], symbols[3]= [ 0x2f, 0x5c, 0x7c, NoSymbol, NoSymbol, 0xad, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe52, 0xfe5a, 0x10021bb, 0x10002de, 0xfe56, 0xfef9, 0xfe60, NoSymbol ] }; key { type[4]= "TWO_LEVEL", symbols[1]= [ 0xffe1 ], symbols[2]= [ 0xffe1 ], symbols[3]= [ 0xffe1 ], symbols[4]= [ 0xffe1, 0xffe5 ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "ONE_LEVEL", symbols[1]= [ 0x5c, 0x7c ], symbols[2]= [ 0x5c, 0x2f ], symbols[3]= [ 0xe0, 0xc0, 0x7d, NoSymbol, NoSymbol, 0xfe55, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe03 ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "FOUR_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x7a, 0x5a ], symbols[2]= [ 0x6d1, 0x6f1 ], symbols[3]= [ 0x7a, 0x5a, 0xab, NoSymbol ], symbols[4]= [ 0xfc, 0xdc, 0x23, NoSymbol, 0xff1b, 0xff1b, 0x8dd, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "FOUR_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x78, 0x58 ], symbols[2]= [ 0x6de, 0x6fe ], symbols[3]= [ 0x78, 0x58, 0xbb, NoSymbol ], symbols[4]= [ 0xf6, 0xd6, 0x24, 0x10003f5, 0xff09, 0xff09, 0x8dc, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x63, 0x43 ], symbols[2]= [ 0x6d3, 0x6f3 ], symbols[3]= [ 0x63, 0x43, NoSymbol, NoSymbol, 0xa2, 0xa9, NoSymbol, NoSymbol ], symbols[4]= [ 0xe4, 0xc4, 0x7c, 0x7e7, 0xff63, 0xff63, 0x1002135, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x76, 0x56 ], symbols[2]= [ 0x6cd, 0x6ed ], symbols[3]= [ 0x76, 0x56, NoSymbol, NoSymbol, 0xad2, 0xad0, NoSymbol, NoSymbol ], symbols[4]= [ 0x70, 0x50, 0x7e, 0x7f0, 0xff0d, 0xff0d, 0x7d0, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x62, 0x42 ], symbols[2]= [ 0x6c9, 0x6e9 ], symbols[3]= [ 0x62, 0x42, NoSymbol, NoSymbol, 0xad3, 0xad1, NoSymbol, NoSymbol ], symbols[4]= [ 0x7a, 0x5a, 0x60, 0x7e6, 0xff65, 0xff65, 0x1002124, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6e, 0x4e ], symbols[2]= [ 0x6d4, 0x6f4 ], symbols[3]= [ 0x6e, 0x4e, NoSymbol, NoSymbol, 0x1000149, 0x100266a, NoSymbol, NoSymbol ], symbols[4]= [ 0x62, 0x42, 0x2b, 0x7e2, 0x3a, NoSymbol, 0x10021d0, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x6d, 0x4d ], symbols[2]= [ 0x6d8, 0x6f8 ], symbols[3]= [ 0x6d, 0x4d, 0xb5, NoSymbol, 0xb5, 0xba, NoSymbol, NoSymbol ], symbols[4]= [ 0x6d, 0x4d, 0x25, 0x7ec, 0xffb1, 0xffb1, 0x8cd, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x2c, 0x3c ], symbols[2]= [ 0x6c2, 0x6e2 ], symbols[3]= [ 0x2c, 0x27, 0x3c, NoSymbol, 0x7af, 0xd7, NoSymbol, NoSymbol ], symbols[4]= [ 0x2c, 0xaaa, 0x22, 0x10003f1, 0xffb2, 0xffb2, 0x10021d2, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x2e, 0x3e ], symbols[2]= [ 0x6c0, 0x6e0 ], symbols[3]= [ 0x2e, 0x22, 0x3e, NoSymbol, 0xb7, 0xf7, NoSymbol, NoSymbol ], symbols[4]= [ 0x2e, 0xae6, 0x27, 0x10003d1, 0xffb3, 0xffb3, 0x10021a6, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ 0x2f, 0x3f ], symbols[2]= [ 0x2e, 0x2c ], symbols[3]= [ 0xe9, 0xc9, 0xfe51, NoSymbol, NoSymbol, 0xfe56, NoSymbol, NoSymbol ], symbols[4]= [ 0x6a, 0x4a, 0x3b, 0x7e8, 0x3b, NoSymbol, 0x7c8, NoSymbol ] }; key { type[4]= "TWO_LEVEL", symbols[1]= [ 0xffe2 ], symbols[2]= [ 0xffe2 ], symbols[3]= [ 0xffe2 ], symbols[4]= [ 0xffe2, 0xffe5 ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffaa, 0xffaa, 0xffaa, 0xffaa, 0x1008fe21 ], symbols[2]= [ 0xffaa, 0xffaa, 0xffaa, 0xffaa, 0x1008fe21 ], symbols[3]= [ 0xffaa, 0xffaa, 0xffaa, 0xffaa, 0x1008fe21 ], symbols[4]= [ 0xffaa, 0xffaa, 0x1002219, 0x1002299, 0xd7, NoSymbol, 0x1002297, NoSymbol ] }; key { [ 0xffe9, 0xffe7 ] }; key { type[3]= "FOUR_LEVEL", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0x20 ], symbols[2]= [ 0x20 ], symbols[3]= [ 0x20, 0x20, 0xa0, NoSymbol ], symbols[4]= [ 0x20, 0x20, 0x20, 0xa0, 0xffb0, 0xffb0, 0x100202f, NoSymbol ] }; key { type= "ONE_LEVEL", symbols[1]= [ 0xffe5 ], symbols[2]= [ 0xffe5 ], symbols[3]= [ 0xffe5 ], symbols[4]= [ 0xfe03 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffbe, 0xffbe, 0xffbe, 0xffbe, 0x1008fe01 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffbf, 0xffbf, 0xffbf, 0xffbf, 0x1008fe02 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0x1008fe03 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc1, 0xffc1, 0xffc1, 0xffc1, 0x1008fe04 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc2, 0xffc2, 0xffc2, 0xffc2, 0x1008fe05 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc3, 0xffc3, 0xffc3, 0xffc3, 0x1008fe06 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc4, 0xffc4, 0xffc4, 0xffc4, 0x1008fe07 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc5, 0xffc5, 0xffc5, 0xffc5, 0x1008fe08 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc6, 0xffc6, 0xffc6, 0xffc6, 0x1008fe09 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc7, 0xffc7, 0xffc7, 0xffc7, 0x1008fe0a ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff7f ], symbols[2]= [ 0xff7f ], symbols[3]= [ 0xff7f ], symbols[4]= [ 0xff09, 0xfe20, 0x3d, 0x1002248, 0x8bd, 0xfef9, 0x8cf, NoSymbol ] }; key { [ 0xff14 ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff95, 0xffb7 ], symbols[2]= [ 0xff95, 0xffb7 ], symbols[3]= [ 0xff95, 0xffb7 ], symbols[4]= [ 0xffb7, 0x1002714, 0x1002195, 0x100226a, 0xff95, 0xff95, 0xbd3, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff97, 0xffb8 ], symbols[2]= [ 0xff97, 0xffb8 ], symbols[3]= [ 0xff97, 0xffb8 ], symbols[4]= [ 0xffb8, 0x1002718, 0x8fc, 0x8dc, 0xff97, 0xff97, 0x10022c2, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9a, 0xffb9 ], symbols[2]= [ 0xff9a, 0xffb9 ], symbols[3]= [ 0xff9a, 0xffb9 ], symbols[4]= [ 0xffb9, 0xaf1, 0x10020d7, 0x100226b, 0xff9a, 0xff9a, 0x1002309, NoSymbol ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffad, 0xffad, 0xffad, 0xffad, 0x1008fe23 ], symbols[2]= [ 0xffad, 0xffad, 0xffad, 0xffad, 0x1008fe23 ], symbols[3]= [ 0xffad, 0xffad, 0xffad, 0xffad, 0x1008fe23 ], symbols[4]= [ 0xffad, 0xffad, 0x1002212, 0x1002296, 0x1002216, NoSymbol, 0x1002238, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff96, 0xffb4 ], symbols[2]= [ 0xff96, 0xffb4 ], symbols[3]= [ 0xff96, 0xffb4 ], symbols[4]= [ 0xffb4, 0xaec, 0x8fb, 0x8da, 0xff96, 0xff96, 0x1002286, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9d, 0xffb5 ], symbols[2]= [ 0xff9d, 0xffb5 ], symbols[3]= [ 0xff9d, 0xffb5 ], symbols[4]= [ 0xffb5, 0x20ac, 0x3a, 0x10022b6, 0xff9d, 0xff9d, 0x10022b7, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff98, 0xffb6 ], symbols[2]= [ 0xff98, 0xffb6 ], symbols[3]= [ 0xff98, 0xffb6 ], symbols[4]= [ 0xffb6, 0x1002023, 0x8fd, 0x8db, 0xff98, 0xff98, 0x1002287, NoSymbol ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffab, 0xffab, 0xffab, 0xffab, 0x1008fe22 ], symbols[2]= [ 0xffab, 0xffab, 0xffab, 0xffab, 0x1008fe22 ], symbols[3]= [ 0xffab, 0xffab, 0xffab, 0xffab, 0x1008fe22 ], symbols[4]= [ 0xffab, 0xffab, 0xb1, 0x1002295, 0x1002213, NoSymbol, 0x1002214, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9c, 0xffb1 ], symbols[2]= [ 0xff9c, 0xffb1 ], symbols[3]= [ 0xff9c, 0xffb1 ], symbols[4]= [ 0xffb1, 0xaed, 0x1002194, 0x8bc, 0xff9c, 0xff9c, 0xbc4, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff99, 0xffb2 ], symbols[2]= [ 0xff99, 0xffb2 ], symbols[3]= [ 0xff99, 0xffb2 ], symbols[4]= [ 0xffb2, 0xaee, 0x8fe, 0x8dd, 0xff99, 0xff99, 0x10022c3, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9b, 0xffb3 ], symbols[2]= [ 0xff9b, 0xffb3 ], symbols[3]= [ 0xff9b, 0xffb3 ], symbols[4]= [ 0xffb3, 0x1002660, 0x10021cc, 0x8be, 0xff9b, 0xff9b, 0x100230b, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9e, 0xffb0 ], symbols[2]= [ 0xff9e, 0xffb0 ], symbols[3]= [ 0xff9e, 0xffb0 ], symbols[4]= [ 0xffb0, 0x1002423, 0x25, 0x1002030, 0xff9e, 0xff9e, 0x10025a1, NoSymbol ] }; key { type[2]= "KEYPAD", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff9f, 0xffae ], symbols[2]= [ 0xff9f, 0xffac ], symbols[3]= [ 0xff9f, 0xffae ], symbols[4]= [ 0xffac, 0x2e, 0x2c, 0xad6, 0xff9f, 0xff9f, 0xad7, NoSymbol ] }; key { [ 0xfe03 ] }; key { type[1]= "FOUR_LEVEL", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "ONE_LEVEL", symbols[1]= [ 0x3c, 0x3e, 0x7c, 0xa6 ], symbols[2]= [ 0x2f, 0x7c ], symbols[3]= [ 0xf9, 0xd9, 0xb0, NoSymbol, NoSymbol, 0xa6, NoSymbol, NoSymbol ], symbols[4]= [ 0xfe11 ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc8, 0xffc8, 0xffc8, 0xffc8, 0x1008fe0b ] }; key { type= "CTRL+ALT", symbols[1]= [ 0xffc9, 0xffc9, 0xffc9, 0xffc9, 0x1008fe0c ] }; key { [ 0xff26 ] }; key { [ 0xff25 ] }; key { [ 0xff23 ] }; key { [ 0xff27 ] }; key { [ 0xff22 ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xff8d ], symbols[2]= [ 0xff8d ], symbols[3]= [ 0xff8d ], symbols[4]= [ 0xff8d, 0xff8d, 0xff8d, 0xff8d, 0xff8d, 0xff8d, 0xff8d, NoSymbol ] }; key { type= "ONE_LEVEL", symbols[1]= [ 0xffe4 ], symbols[2]= [ 0xffe4 ], symbols[3]= [ 0xfe11 ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffaf, 0xffaf, 0xffaf, 0xffaf, 0x1008fe20 ], symbols[2]= [ 0xffaf, 0xffaf, 0xffaf, 0xffaf, 0x1008fe20 ], symbols[3]= [ 0xffaf, 0xffaf, 0xffaf, 0xffaf, 0x1008fe20 ], symbols[4]= [ 0xffaf, 0xffaf, 0xf7, 0x1002300, 0x1002215, NoSymbol, 0x1002223, NoSymbol ] }; key { type= "PC_ALT_LEVEL2", symbols[1]= [ 0xff61, 0xff15 ] }; key { type[1]= "TWO_LEVEL", type[2]= "TWO_LEVEL", type[3]= "ONE_LEVEL", type[4]= "ONE_LEVEL", symbols[1]= [ 0xffea, 0xffe8 ], symbols[2]= [ 0xffea, 0xffe8 ], symbols[3]= [ 0xfe03 ], symbols[4]= [ 0xfe11 ] }; key { [ 0xff0a ] }; key { [ 0xff50 ] }; key { [ 0xff52 ] }; key { [ 0xff55 ] }; key { [ 0xff51 ] }; key { [ 0xff53 ] }; key { [ 0xff57 ] }; key { [ 0xff54 ] }; key { [ 0xff56 ] }; key { [ 0xff63 ] }; key { [ 0xffff ] }; key { [ 0x1008ff12 ] }; key { [ 0x1008ff11 ] }; key { [ 0x1008ff13 ] }; key { [ 0x1008ff2a ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ 0xffbd ], symbols[2]= [ 0xffbd ], symbols[3]= [ 0xffbd ], symbols[4]= [ 0xffbd, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; key { [ 0xb1 ] }; key { type= "PC_CONTROL_LEVEL2", symbols[1]= [ 0xff13, 0xff6b ] }; key { [ 0x1008ff4a ] }; key { [ 0xffae, 0xffae ] }; key { [ 0xff31 ] }; key { [ 0xff34 ] }; key { [ 0xffeb ] }; key { [ 0xffec ] }; key { [ 0xff67 ] }; key { [ 0xff69 ] }; key { [ 0xff66 ] }; key { [ 0x1005ff70 ] }; key { [ 0xff65 ] }; key { [ 0x1005ff71 ] }; key { [ 0x1008ff57 ] }; key { [ 0x1005ff73 ] }; key { [ 0x1008ff6d ] }; key { [ 0xff68 ] }; key { [ 0x1008ff58 ] }; key { [ 0xff6a ] }; key { [ 0x1008ff65 ] }; key { [ 0x1008ff1d ] }; key { [ 0x1008ff2f ] }; key { [ 0x1008ff2b ] }; key { [ 0x1008ff5d ] }; key { [ 0x1008ff7b ] }; key { [ 0x1008ff8a ] }; key { [ 0x1008ff41 ] }; key { [ 0x1008ff42 ] }; key { [ 0x1008ff2e ] }; key { [ 0x1008ff5a ] }; key { [ 0x1008ff2d ] }; key { [ 0x1008ff74 ] }; key { [ 0x1008ff19 ] }; key { [ 0x1008ff30 ] }; key { [ 0x1008ff33 ] }; key { [ 0x1008ff26 ] }; key { [ 0x1008ff27 ] }; key { [ 0x1008ff2c ] }; key { [ 0x1008ff2c, 0x1008ff2c ] }; key { [ 0x1008ff17 ] }; key { [ 0x1008ff14, 0x1008ff31 ] }; key { [ 0x1008ff16 ] }; key { [ 0x1008ff15, 0x1008ff2c ] }; key { [ 0x1008ff1c ] }; key { [ 0x1008ff3e ] }; key { [ 0x1008ff6e ] }; key { [ 0x1008ff81 ] }; key { [ 0x1008ff18 ] }; key { [ 0x1008ff73 ] }; key { [ 0x1008ff56 ] }; key { [ 0x1008ff78 ] }; key { [ 0x1008ff79 ] }; key { [ 0x28 ] }; key { [ 0x29 ] }; key { [ 0x1008ff68 ] }; key { [ 0xff66 ] }; key { [ 0x1008ff81 ] }; key { [ 0x1008ff45 ] }; key { [ 0x1008ff46 ] }; key { [ 0x1008ff47 ] }; key { [ 0x1008ff48 ] }; key { [ 0x1008ff49 ] }; key { [ 0x1008ffa9 ] }; key { [ 0x1008ffb0 ] }; key { [ 0x1008ffb1 ] }; key { [ 0xff7e ] }; key { [ NoSymbol, 0xffe9 ] }; key { [ NoSymbol, 0xffe7 ] }; key { [ NoSymbol, 0xffeb ] }; key { [ NoSymbol, 0xffed ] }; key { [ 0x1008ff14 ] }; key { [ 0x1008ff31 ] }; key { [ 0x1008ff43 ] }; key { [ 0x1008ff44 ] }; key { [ 0x1008ff4b ] }; key { [ 0x1008ffa7 ] }; key { [ 0x1008ff56 ] }; key { [ 0x1008ff14 ] }; key { [ 0x1008ff97 ] }; key { [ 0xff61 ] }; key { [ 0x1008ff8f ] }; key { [ 0x1008ff19 ] }; key { [ 0x1008ff8e ] }; key { [ 0x1008ff1b ] }; key { [ 0x1008ff5f ] }; key { [ 0x1008ff3c ] }; key { [ 0x1008ff5e ] }; key { [ 0x1008ff36 ] }; key { [ 0xff69 ] }; key { [ 0x1008ff03 ] }; key { [ 0x1008ff02 ] }; key { [ 0x1008ff32 ] }; key { [ 0x1008ff59 ] }; key { [ 0x1008ff04 ] }; key { [ 0x1008ff06 ] }; key { [ 0x1008ff05 ] }; key { [ 0x1008ff7b ] }; key { [ 0x1008ff72 ] }; key { [ 0x1008ff90 ] }; key { [ 0x1008ff77 ] }; key { [ 0x1008ff5b ] }; key { [ 0x1008ff93 ] }; key { [ 0x1008ff94 ] }; key { [ 0x1008ff95 ] }; modifier_map Shift { , }; modifier_map Lock { }; modifier_map Control { }; modifier_map Mod1 { , , }; modifier_map Mod2 { }; modifier_map Mod3 { }; modifier_map Mod4 { , , , }; modifier_map Mod5 { , }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/stringcomp-v1.xkb000066400000000000000000002205701510033435100254510ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev_aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; indicator 12 = "Shift Lock"; indicator 13 = "Group 2"; indicator 14 = "Mouse Keys"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt=Mod1,RAlt=0x100,RControl=0x210001,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= 2; level_name[1]= "Base"; level_name[2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= 2; level_name[1]= "Base"; level_name[2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= 2; level_name[1]= "Base"; level_name[2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= 2; level_name[1]= "Base"; level_name[2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= 2; level_name[1]= "Base"; level_name[2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= 2; level_name[1]= "Base"; level_name[2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= 2; level_name[1]= "Base"; level_name[2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Control+Alt]= 5; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+Lock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Control]= 5; map[Shift+Lock+Control]= 5; map[Shift+Control]= 6; map[Lock+Control]= 6; map[Control+LevelThree]= 7; map[Shift+Lock+Control+LevelThree]= 7; map[Shift+Control+LevelThree]= 8; map[Lock+Control+LevelThree]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Level3"; level_name[4]= "Shift Level3"; level_name[5]= "Ctrl"; level_name[6]= "Shift Ctrl"; level_name[7]= "Level3 Ctrl"; level_name[8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 8; map[Shift+Lock+LevelThree+LevelFive]= 7; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; preserve[Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= 8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelFive]= 1; preserve[Shift+Lock+LevelFive]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= 2; map[Shift]= 2; map[LevelThree]= 3; map[NumLock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= 2; map[Shift+LevelThree]= 3; map[Control+Alt]= 4; level_name[1]= "Base"; level_name[2]= "Alt Base"; level_name[3]= "Shift Alt"; level_name[4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 4; preserve[Lock]= Lock; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr Base"; level_name[4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock]= 5; map[Shift+Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Lock"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= 2; map[NumLock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[NumLock+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Alt Number"; }; }; xkb_compatibility "complete_caps(caps_lock)_4_misc(assign_shift_left_action)_4_level5(level5_lock)_4" { virtual_modifiers NumLock,Alt,LevelThree,LAlt=Mod1,RAlt=0x100,RControl=0x210001,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Lock+AnyOf(all) { action= NoAction(); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86LogGrabInfo+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret XF86LogWindowTree+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=NumLock); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; indicator "Group 2" { groups= 0xfe; }; indicator "Mouse Keys" { controls= MouseKeys; }; }; xkb_symbols "pc_us_ru_2_ca(multix)_3_de(neo)_4_inet(evdev)" { name[1]="English (US)"; name[2]="Russian"; name[3]="Canadian Multilingual"; name[4]="German (Neo 2)"; key { [ Escape ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 1, exclam ], symbols[2]= [ 1, exclam ], symbols[3]= [ 1, exclam, plusminus, NoSymbol, onesuperior, exclamdown, NoSymbol, NoSymbol ], symbols[4]= [ 1, degree, onesuperior, onesubscript, ordfeminine, NoSymbol, notsign, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 2, at ], symbols[2]= [ 2, quotedbl ], symbols[3]= [ 2, at, at, NoSymbol, twosuperior, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 2, section, twosuperior, twosubscript, masculine, NoSymbol, logicalor, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 3, numbersign ], symbols[2]= [ 3, numerosign ], symbols[3]= [ 3, numbersign, sterling, NoSymbol, threesuperior, sterling, NoSymbol, NoSymbol ], symbols[4]= [ 3, U2113, threesuperior, threesubscript, numerosign, NoSymbol, logicaland, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 4, dollar ], symbols[2]= [ 4, semicolon ], symbols[3]= [ 4, dollar, cent, NoSymbol, onequarter, currency, NoSymbol, NoSymbol ], symbols[4]= [ 4, guillemotright, U203A, femalesymbol, NoSymbol, NoSymbol, U22A5, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 5, percent ], symbols[2]= [ 5, percent ], symbols[3]= [ 5, percent, currency, NoSymbol, onehalf, threeeighths, NoSymbol, NoSymbol ], symbols[4]= [ 5, guillemotleft, U2039, malesymbol, periodcentered, NoSymbol, U2221, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ { H, E, L, L, O }, asciicircum ], symbols[2]= [ 6, colon ], symbols[3]= [ 6, question, notsign, NoSymbol, threequarters, fiveeighths, NoSymbol, NoSymbol ], symbols[4]= [ 6, dollar, cent, U26A5, sterling, NoSymbol, U2225, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ { Y, E, S, space, T, H, I, S, space, I, S, space, D, O, G }, ampersand ], symbols[2]= [ 7, question ], symbols[3]= [ 7, ampersand, braceleft, NoSymbol, NoSymbol, seveneighths, NoSymbol, NoSymbol ], symbols[4]= [ 7, EuroSign, yen, U03F0, currency, NoSymbol, rightarrow, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 8, asterisk ], symbols[2]= [ 8, asterisk ], symbols[3]= [ 8, asterisk, braceright, NoSymbol, NoSymbol, trademark, NoSymbol, NoSymbol ], symbols[4]= [ 8, doublelowquotemark, singlelowquotemark, U27E8, Tab, ISO_Left_Tab, U221E, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 9, parenleft ], symbols[2]= [ 9, parenleft ], symbols[3]= [ 9, parenleft, bracketleft, NoSymbol, NoSymbol, plusminus, NoSymbol, NoSymbol ], symbols[4]= [ 9, leftdoublequotemark, leftsinglequotemark, U27E9, KP_Divide, KP_Divide, variation, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0, parenright ], symbols[2]= [ 0, parenright ], symbols[3]= [ 0, parenright, bracketright, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 0, rightdoublequotemark, rightsinglequotemark, zerosubscript, KP_Multiply, KP_Multiply, emptyset, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ minus, underscore ], symbols[2]= [ minus, underscore ], symbols[3]= [ minus, underscore, onehalf, NoSymbol, NoSymbol, questiondown, NoSymbol, NoSymbol ], symbols[4]= [ minus, emdash, NoSymbol, U2011, KP_Subtract, KP_Subtract, hyphen, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ equal, plus ], symbols[2]= [ equal, plus ], symbols[3]= [ equal, plus, notsign, NoSymbol, dead_cedilla, dead_ogonek, NoSymbol, NoSymbol ], symbols[4]= [ dead_grave, dead_cedilla, dead_abovering, dead_abovereversedcomma, dead_diaeresis, NoSymbol, dead_macron, NoSymbol ] }; key { [ BackSpace, BackSpace ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ Tab, ISO_Left_Tab ], symbols[2]= [ Tab, ISO_Left_Tab ], symbols[3]= [ Tab, ISO_Left_Tab ], symbols[4]= [ Tab, ISO_Left_Tab, Multi_key, ISO_Level5_Lock, NoSymbol, NoSymbol, NoSymbol, ISO_Level5_Lock ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ q, Q ], symbols[2]= [ Cyrillic_shorti, Cyrillic_SHORTI ], symbols[3]= [ q, Q, NoSymbol, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol, NoSymbol ], symbols[4]= [ x, X, ellipsis, Greek_xi, Prior, Prior, Greek_XI, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ w, W ], symbols[2]= [ Cyrillic_tse, Cyrillic_TSE ], symbols[3]= [ w, W, NoSymbol, NoSymbol, lstroke, Lstroke, NoSymbol, NoSymbol ], symbols[4]= [ v, V, underscore, NoSymbol, BackSpace, BackSpace, radical, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ e, E ], symbols[2]= [ Cyrillic_u, Cyrillic_U ], symbols[3]= [ e, E, NoSymbol, NoSymbol, oe, OE, NoSymbol, NoSymbol ], symbols[4]= [ l, L, bracketleft, Greek_lamda, Up, Up, Greek_LAMDA, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ r, R ], symbols[2]= [ Cyrillic_ka, Cyrillic_KA ], symbols[3]= [ r, R, NoSymbol, NoSymbol, paragraph, registered, NoSymbol, NoSymbol ], symbols[4]= [ c, C, bracketright, Greek_chi, Delete, Delete, U2102, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ t, T ], symbols[2]= [ Cyrillic_ie, Cyrillic_IE ], symbols[3]= [ t, T, NoSymbol, NoSymbol, tslash, Tslash, NoSymbol, NoSymbol ], symbols[4]= [ w, W, asciicircum, Greek_omega, Next, Next, Greek_OMEGA, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ y, Y ], symbols[2]= [ Cyrillic_en, Cyrillic_EN ], symbols[3]= [ y, Y, NoSymbol, NoSymbol, leftarrow, yen, NoSymbol, NoSymbol ], symbols[4]= [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ u, U ], symbols[2]= [ Cyrillic_ghe, Cyrillic_GHE ], symbols[3]= [ u, U, NoSymbol, NoSymbol, downarrow, uparrow, NoSymbol, NoSymbol ], symbols[4]= [ h, H, less, Greek_psi, KP_7, KP_7, Greek_PSI, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ i, I ], symbols[2]= [ Cyrillic_sha, Cyrillic_SHA ], symbols[3]= [ i, I, NoSymbol, NoSymbol, rightarrow, idotless, NoSymbol, NoSymbol ], symbols[4]= [ g, G, greater, Greek_gamma, KP_8, KP_8, Greek_GAMMA, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ o, O ], symbols[2]= [ Cyrillic_shcha, Cyrillic_SHCHA ], symbols[3]= [ o, O, section, NoSymbol, oslash, Oslash, NoSymbol, NoSymbol ], symbols[4]= [ f, F, equal, Greek_phi, KP_9, KP_9, Greek_PHI, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ p, P ], symbols[2]= [ Cyrillic_ze, Cyrillic_ZE ], symbols[3]= [ p, P, paragraph, NoSymbol, thorn, THORN, NoSymbol, NoSymbol ], symbols[4]= [ q, Q, ampersand, U03D5, KP_Add, KP_Add, U211A, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ bracketleft, braceleft ], symbols[2]= [ Cyrillic_ha, Cyrillic_HA ], symbols[3]= [ dead_circumflex, dead_diaeresis, dead_grave, NoSymbol, NoSymbol, dead_abovering, NoSymbol, NoSymbol ], symbols[4]= [ ssharp, U1E9E, U017F, Greek_finalsmallsigma, U2212, NoSymbol, jot, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ bracketright, braceright ], symbols[2]= [ Cyrillic_hardsign, Cyrillic_HARDSIGN ], symbols[3]= [ ccedilla, Ccedilla, asciitilde, NoSymbol, dead_tilde, dead_macron, NoSymbol, NoSymbol ], symbols[4]= [ dead_acute, dead_tilde, dead_stroke, dead_abovecomma, dead_doubleacute, NoSymbol, dead_breve, NoSymbol ] }; key { [ Return ] }; key { [ Control_L ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ a, A ], symbols[2]= [ Cyrillic_ef, Cyrillic_EF ], symbols[3]= [ a, A, NoSymbol, NoSymbol, ae, AE, NoSymbol, NoSymbol ], symbols[4]= [ u, U, backslash, NoSymbol, Home, Home, includedin, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ s, S ], symbols[2]= [ Cyrillic_yeru, Cyrillic_YERU ], symbols[3]= [ s, S, NoSymbol, NoSymbol, ssharp, section, NoSymbol, NoSymbol ], symbols[4]= [ i, I, slash, Greek_iota, Left, Left, integral, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ d, D ], symbols[2]= [ Cyrillic_ve, Cyrillic_VE ], symbols[3]= [ d, D, NoSymbol, NoSymbol, eth, ETH, NoSymbol, NoSymbol ], symbols[4]= [ a, A, braceleft, Greek_alpha, Down, Down, U2200, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ f, F ], symbols[2]= [ Cyrillic_a, Cyrillic_A ], symbols[3]= [ f, F, NoSymbol, NoSymbol, NoSymbol, ordfeminine, NoSymbol, NoSymbol ], symbols[4]= [ e, E, braceright, Greek_epsilon, Right, Right, U2203, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ g, G ], symbols[2]= [ Cyrillic_pe, Cyrillic_PE ], symbols[3]= [ g, G, NoSymbol, NoSymbol, eng, ENG, NoSymbol, NoSymbol ], symbols[4]= [ o, O, asterisk, Greek_omicron, End, End, elementof, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ h, H ], symbols[2]= [ Cyrillic_er, Cyrillic_ER ], symbols[3]= [ h, H, NoSymbol, NoSymbol, hstroke, Hstroke, NoSymbol, NoSymbol ], symbols[4]= [ s, S, question, Greek_sigma, questiondown, NoSymbol, Greek_SIGMA, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ j, J ], symbols[2]= [ Cyrillic_o, Cyrillic_O ], symbols[3]= [ j, J, NoSymbol, NoSymbol, U0133, U0132, NoSymbol, NoSymbol ], symbols[4]= [ n, N, parenleft, Greek_nu, KP_4, KP_4, U2115, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ k, K ], symbols[2]= [ Cyrillic_el, Cyrillic_EL ], symbols[3]= [ k, K, NoSymbol, NoSymbol, kra, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ r, R, parenright, Greek_rho, KP_5, KP_5, U211D, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ l, L ], symbols[2]= [ Cyrillic_de, Cyrillic_DE ], symbols[3]= [ l, L, NoSymbol, NoSymbol, U0140, U013F, NoSymbol, NoSymbol ], symbols[4]= [ t, T, minus, Greek_tau, KP_6, KP_6, partialderivative, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ semicolon, colon ], symbols[2]= [ Cyrillic_zhe, Cyrillic_ZHE ], symbols[3]= [ semicolon, colon, degree, NoSymbol, dead_acute, dead_doubleacute, NoSymbol, NoSymbol ], symbols[4]= [ d, D, colon, Greek_delta, KP_Separator, comma, Greek_DELTA, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ apostrophe, quotedbl ], symbols[2]= [ Cyrillic_e, Cyrillic_E ], symbols[3]= [ egrave, Egrave, braceleft, NoSymbol, NoSymbol, dead_caron, NoSymbol, NoSymbol ], symbols[4]= [ y, Y, at, Greek_upsilon, period, KP_Decimal, nabla, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ grave, asciitilde ], symbols[2]= [ Cyrillic_io, Cyrillic_IO ], symbols[3]= [ slash, backslash, bar, NoSymbol, NoSymbol, hyphen, NoSymbol, NoSymbol ], symbols[4]= [ dead_circumflex, dead_caron, U21BB, U02DE, dead_abovedot, Pointer_EnableKeys, dead_belowdot, NoSymbol ] }; key { type[4]= "TWO_LEVEL", symbols[1]= [ Shift_L ], symbols[2]= [ Shift_L ], symbols[3]= [ Shift_L ], symbols[4]= [ Shift_L, Caps_Lock ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "ONE_LEVEL", symbols[1]= [ backslash, bar ], symbols[2]= [ backslash, slash ], symbols[3]= [ agrave, Agrave, braceright, NoSymbol, NoSymbol, dead_breve, NoSymbol, NoSymbol ], symbols[4]= [ ISO_Level3_Shift ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "FOUR_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ z, Z ], symbols[2]= [ Cyrillic_ya, Cyrillic_YA ], symbols[3]= [ z, Z, guillemotleft, NoSymbol ], symbols[4]= [ udiaeresis, Udiaeresis, numbersign, NoSymbol, Escape, Escape, union, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "FOUR_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ x, X ], symbols[2]= [ Cyrillic_che, Cyrillic_CHE ], symbols[3]= [ x, X, guillemotright, NoSymbol ], symbols[4]= [ odiaeresis, Odiaeresis, dollar, U03F5, Tab, Tab, intersection, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ c, C ], symbols[2]= [ Cyrillic_es, Cyrillic_ES ], symbols[3]= [ c, C, NoSymbol, NoSymbol, cent, copyright, NoSymbol, NoSymbol ], symbols[4]= [ adiaeresis, Adiaeresis, bar, Greek_eta, Insert, Insert, U2135, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ v, V ], symbols[2]= [ Cyrillic_em, Cyrillic_EM ], symbols[3]= [ v, V, NoSymbol, NoSymbol, leftdoublequotemark, leftsinglequotemark, NoSymbol, NoSymbol ], symbols[4]= [ p, P, asciitilde, Greek_pi, Return, Return, Greek_PI, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ b, B ], symbols[2]= [ Cyrillic_i, Cyrillic_I ], symbols[3]= [ b, B, NoSymbol, NoSymbol, rightdoublequotemark, rightsinglequotemark, NoSymbol, NoSymbol ], symbols[4]= [ z, Z, grave, Greek_zeta, Undo, Undo, U2124, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ n, N ], symbols[2]= [ Cyrillic_te, Cyrillic_TE ], symbols[3]= [ n, N, NoSymbol, NoSymbol, U0149, U266A, NoSymbol, NoSymbol ], symbols[4]= [ b, B, plus, Greek_beta, colon, NoSymbol, U21D0, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ m, M ], symbols[2]= [ Cyrillic_softsign, Cyrillic_SOFTSIGN ], symbols[3]= [ m, M, mu, NoSymbol, mu, masculine, NoSymbol, NoSymbol ], symbols[4]= [ m, M, percent, Greek_mu, KP_1, KP_1, ifonlyif, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ comma, less ], symbols[2]= [ Cyrillic_be, Cyrillic_BE ], symbols[3]= [ comma, apostrophe, less, NoSymbol, Greek_horizbar, multiply, NoSymbol, NoSymbol ], symbols[4]= [ comma, endash, quotedbl, U03F1, KP_2, KP_2, U21D2, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ period, greater ], symbols[2]= [ Cyrillic_yu, Cyrillic_YU ], symbols[3]= [ period, quotedbl, greater, NoSymbol, periodcentered, division, NoSymbol, NoSymbol ], symbols[4]= [ period, enfilledcircbullet, apostrophe, U03D1, KP_3, KP_3, U21A6, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ slash, question ], symbols[2]= [ period, comma ], symbols[3]= [ eacute, Eacute, dead_acute, NoSymbol, NoSymbol, dead_abovedot, NoSymbol, NoSymbol ], symbols[4]= [ j, J, semicolon, Greek_theta, semicolon, NoSymbol, Greek_THETA, NoSymbol ] }; key { type[4]= "TWO_LEVEL", symbols[1]= [ Shift_R ], symbols[2]= [ Shift_R ], symbols[3]= [ Shift_R ], symbols[4]= [ Shift_R, Caps_Lock ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ], symbols[2]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ], symbols[3]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ], symbols[4]= [ KP_Multiply, KP_Multiply, U2219, U2299, multiply, NoSymbol, U2297, NoSymbol ] }; key { [ Alt_L, Meta_L ] }; key { type[3]= "FOUR_LEVEL", type[4]= "EIGHT_LEVEL", symbols[1]= [ space ], symbols[2]= [ space ], symbols[3]= [ space, space, nobreakspace, NoSymbol ], symbols[4]= [ space, space, space, nobreakspace, KP_0, KP_0, U202F, NoSymbol ] }; key { type= "ONE_LEVEL", symbols[1]= [ Caps_Lock ], symbols[2]= [ Caps_Lock ], symbols[3]= [ Caps_Lock ], symbols[4]= [ ISO_Level3_Shift ] }; key { type= "CTRL+ALT", symbols[1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ] }; key { type= "CTRL+ALT", symbols[1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ] }; key { type= "CTRL+ALT", symbols[1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ] }; key { type= "CTRL+ALT", symbols[1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ] }; key { type= "CTRL+ALT", symbols[1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ] }; key { type= "CTRL+ALT", symbols[1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ] }; key { type= "CTRL+ALT", symbols[1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ] }; key { type= "CTRL+ALT", symbols[1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ] }; key { type= "CTRL+ALT", symbols[1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ] }; key { type= "CTRL+ALT", symbols[1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ Num_Lock ], symbols[2]= [ Num_Lock ], symbols[3]= [ Num_Lock ], symbols[4]= [ Tab, ISO_Left_Tab, equal, approxeq, notequal, Pointer_EnableKeys, identical, NoSymbol ] }; key { [ Scroll_Lock ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Home, KP_7 ], symbols[2]= [ KP_Home, KP_7 ], symbols[3]= [ KP_Home, KP_7 ], symbols[4]= [ KP_7, U2714, U2195, U226A, KP_Home, KP_Home, upstile, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Up, KP_8 ], symbols[2]= [ KP_Up, KP_8 ], symbols[3]= [ KP_Up, KP_8 ], symbols[4]= [ KP_8, U2718, uparrow, intersection, KP_Up, KP_Up, U22C2, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Prior, KP_9 ], symbols[2]= [ KP_Prior, KP_9 ], symbols[3]= [ KP_Prior, KP_9 ], symbols[4]= [ KP_9, dagger, U20D7, U226B, KP_Prior, KP_Prior, U2309, NoSymbol ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ], symbols[2]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ], symbols[3]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ], symbols[4]= [ KP_Subtract, KP_Subtract, U2212, U2296, U2216, NoSymbol, U2238, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Left, KP_4 ], symbols[2]= [ KP_Left, KP_4 ], symbols[3]= [ KP_Left, KP_4 ], symbols[4]= [ KP_4, club, leftarrow, includedin, KP_Left, KP_Left, U2286, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Begin, KP_5 ], symbols[2]= [ KP_Begin, KP_5 ], symbols[3]= [ KP_Begin, KP_5 ], symbols[4]= [ KP_5, EuroSign, colon, U22B6, KP_Begin, KP_Begin, U22B7, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Right, KP_6 ], symbols[2]= [ KP_Right, KP_6 ], symbols[3]= [ KP_Right, KP_6 ], symbols[4]= [ KP_6, U2023, rightarrow, includes, KP_Right, KP_Right, U2287, NoSymbol ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ], symbols[2]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ], symbols[3]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ], symbols[4]= [ KP_Add, KP_Add, plusminus, U2295, U2213, NoSymbol, U2214, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_End, KP_1 ], symbols[2]= [ KP_End, KP_1 ], symbols[3]= [ KP_End, KP_1 ], symbols[4]= [ KP_1, diamond, U2194, lessthanequal, KP_End, KP_End, downstile, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Down, KP_2 ], symbols[2]= [ KP_Down, KP_2 ], symbols[3]= [ KP_Down, KP_2 ], symbols[4]= [ KP_2, heart, downarrow, union, KP_Down, KP_Down, U22C3, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Next, KP_3 ], symbols[2]= [ KP_Next, KP_3 ], symbols[3]= [ KP_Next, KP_3 ], symbols[4]= [ KP_3, U2660, U21CC, greaterthanequal, KP_Next, KP_Next, U230B, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Insert, KP_0 ], symbols[2]= [ KP_Insert, KP_0 ], symbols[3]= [ KP_Insert, KP_0 ], symbols[4]= [ KP_0, U2423, percent, U2030, KP_Insert, KP_Insert, U25A1, NoSymbol ] }; key { type[2]= "KEYPAD", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Delete, KP_Decimal ], symbols[2]= [ KP_Delete, KP_Separator ], symbols[3]= [ KP_Delete, KP_Decimal ], symbols[4]= [ KP_Separator, period, comma, minutes, KP_Delete, KP_Delete, seconds, NoSymbol ] }; key { [ ISO_Level3_Shift ] }; key { type[1]= "FOUR_LEVEL", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "ONE_LEVEL", symbols[1]= [ less, greater, bar, brokenbar ], symbols[2]= [ slash, bar ], symbols[3]= [ ugrave, Ugrave, degree, NoSymbol, NoSymbol, brokenbar, NoSymbol, NoSymbol ], symbols[4]= [ ISO_Level5_Shift ] }; key { type= "CTRL+ALT", symbols[1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ] }; key { type= "CTRL+ALT", symbols[1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Henkan_Mode ] }; key { [ Hiragana_Katakana ] }; key { [ Muhenkan ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Enter ], symbols[2]= [ KP_Enter ], symbols[3]= [ KP_Enter ], symbols[4]= [ KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, NoSymbol ] }; key { type= "ONE_LEVEL", symbols[1]= [ Control_R ], symbols[2]= [ Control_R ], symbols[3]= [ ISO_Level5_Shift ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ], symbols[2]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ], symbols[3]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ], symbols[4]= [ KP_Divide, KP_Divide, division, U2300, U2215, NoSymbol, U2223, NoSymbol ] }; key { type= "PC_ALT_LEVEL2", symbols[1]= [ Print, Sys_Req ] }; key { type[1]= "TWO_LEVEL", type[2]= "TWO_LEVEL", type[3]= "ONE_LEVEL", type[4]= "ONE_LEVEL", symbols[1]= [ Alt_R, Meta_R ], symbols[2]= [ Alt_R, Meta_R ], symbols[3]= [ ISO_Level3_Shift ], symbols[4]= [ ISO_Level5_Shift ] }; key { [ Linefeed ] }; key { [ Home ] }; key { [ Up ] }; key { [ Prior ] }; key { [ Left ] }; key { [ Right ] }; key { [ End ] }; key { [ Down ] }; key { [ Next ] }; key { [ Insert ] }; key { [ Delete ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Equal ], symbols[2]= [ KP_Equal ], symbols[3]= [ KP_Equal ], symbols[4]= [ KP_Equal, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; key { [ plusminus ] }; key { type= "PC_CONTROL_LEVEL2", symbols[1]= [ Pause, Break ] }; key { [ XF86LaunchA ] }; key { [ KP_Decimal, KP_Decimal ] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ Super_L ] }; key { [ Super_R ] }; key { [ Menu ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ SunOpen ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Eject ] }; key { [ XF86Eject, XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ Mode_switch ] }; key { [ NoSymbol, Alt_L ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; key { [ NoSymbol, Hyper_L ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; key { [ Print ] }; key { [ XF86WebCam ] }; key { [ XF86Mail ] }; key { [ XF86Messenger ] }; key { [ XF86Search ] }; key { [ XF86Go ] }; key { [ XF86Finance ] }; key { [ XF86Game ] }; key { [ XF86Shop ] }; key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; modifier_map Shift { , }; modifier_map Lock { }; modifier_map Control { }; modifier_map Mod1 { , , }; modifier_map Mod2 { }; modifier_map Mod3 { }; modifier_map Mod4 { , , , }; modifier_map Mod5 { , }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/stringcomp-v2.xkb000066400000000000000000002216511510033435100254530ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev_aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; indicator 12 = "Shift Lock"; indicator 13 = "Group 2"; indicator 14 = "Mouse Keys"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt=Mod1,RAlt=0x100,RControl=0x210001,LControl=0x4000,ScrollLock=0x8000,LevelFive=0x10000,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= 2; level_name[1]= "Base"; level_name[2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= 2; level_name[1]= "Base"; level_name[2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= 2; level_name[1]= "Base"; level_name[2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= 2; level_name[1]= "Base"; level_name[2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= 2; level_name[1]= "Base"; level_name[2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= 2; level_name[1]= "Base"; level_name[2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= 2; level_name[1]= "Base"; level_name[2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Control+Alt]= 5; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+Lock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Control]= 5; map[Shift+Lock+Control]= 5; map[Shift+Control]= 6; map[Lock+Control]= 6; map[Control+LevelThree]= 7; map[Shift+Lock+Control+LevelThree]= 7; map[Shift+Control+LevelThree]= 8; map[Lock+Control+LevelThree]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Level3"; level_name[4]= "Shift Level3"; level_name[5]= "Ctrl"; level_name[6]= "Shift Ctrl"; level_name[7]= "Level3 Ctrl"; level_name[8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 8; map[Shift+Lock+LevelThree+LevelFive]= 7; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= 5; map[Shift+LevelFive]= 6; map[Lock+LevelFive]= 6; preserve[Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= 7; map[Shift+LevelThree+LevelFive]= 8; map[Lock+LevelThree+LevelFive]= 7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= 8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelFive]= 1; preserve[Shift+Lock+LevelFive]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "X"; level_name[6]= "X Shift"; level_name[7]= "X Alt Base"; level_name[8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= 2; map[Shift]= 2; map[LevelThree]= 3; map[NumLock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= 2; map[Shift+LevelThree]= 3; map[Control+Alt]= 4; level_name[1]= "Base"; level_name[2]= "Alt Base"; level_name[3]= "Shift Alt"; level_name[4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 4; preserve[Lock]= Lock; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr Base"; level_name[4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock]= 5; map[Shift+Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Lock"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= 2; map[NumLock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[NumLock+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Alt Number"; }; }; xkb_compatibility "complete_caps(caps_lock)_4_misc(assign_shift_left_action)_4_level5(level5_lock)_4" { virtual_modifiers NumLock,Alt,LevelThree,LAlt=Mod1,RAlt=0x100,RControl=0x210001,LControl=0x4000,ScrollLock=0x8000,LevelFive=0x10000,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Lock+AnyOf(all) { action= NoAction(); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86LogGrabInfo+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret XF86LogWindowTree+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=NumLock); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; indicator "Group 2" { groups= 0xfe; }; indicator "Mouse Keys" { controls= MouseKeys; }; }; xkb_symbols "pc_us_ru_2_ca(multix)_3_de(neo)_4_inet(evdev)" { name[1]="English (US)"; name[2]="Russian"; name[3]="Canadian Multilingual"; name[4]="German (Neo 2)"; key { [ Escape ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 1, exclam ], symbols[2]= [ 1, exclam ], symbols[3]= [ 1, exclam, plusminus, NoSymbol, onesuperior, exclamdown, NoSymbol, NoSymbol ], symbols[4]= [ 1, degree, onesuperior, onesubscript, ordfeminine, NoSymbol, notsign, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 2, at ], symbols[2]= [ 2, quotedbl ], symbols[3]= [ 2, at, at, NoSymbol, twosuperior, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 2, section, twosuperior, twosubscript, masculine, NoSymbol, logicalor, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 3, numbersign ], symbols[2]= [ 3, numerosign ], symbols[3]= [ 3, numbersign, sterling, NoSymbol, threesuperior, sterling, NoSymbol, NoSymbol ], symbols[4]= [ 3, U2113, threesuperior, threesubscript, numerosign, NoSymbol, logicaland, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 4, dollar ], symbols[2]= [ 4, semicolon ], symbols[3]= [ 4, dollar, cent, NoSymbol, onequarter, currency, NoSymbol, NoSymbol ], symbols[4]= [ 4, guillemotright, U203A, femalesymbol, NoSymbol, NoSymbol, U22A5, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 5, percent ], symbols[2]= [ 5, percent ], symbols[3]= [ 5, percent, currency, NoSymbol, onehalf, threeeighths, NoSymbol, NoSymbol ], symbols[4]= [ 5, guillemotleft, U2039, malesymbol, periodcentered, NoSymbol, U2221, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ { H, E, L, L, O }, asciicircum ], symbols[2]= [ 6, colon ], symbols[3]= [ 6, question, notsign, NoSymbol, threequarters, fiveeighths, NoSymbol, NoSymbol ], symbols[4]= [ 6, dollar, cent, U26A5, sterling, NoSymbol, U2225, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ { Y, E, S, space, T, H, I, S, space, I, S, space, D, O, G }, ampersand ], symbols[2]= [ 7, question ], symbols[3]= [ 7, ampersand, braceleft, NoSymbol, NoSymbol, seveneighths, NoSymbol, NoSymbol ], symbols[4]= [ 7, EuroSign, yen, U03F0, currency, NoSymbol, rightarrow, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 8, asterisk ], symbols[2]= [ 8, asterisk ], symbols[3]= [ 8, asterisk, braceright, NoSymbol, NoSymbol, trademark, NoSymbol, NoSymbol ], symbols[4]= [ 8, doublelowquotemark, singlelowquotemark, U27E8, Tab, ISO_Left_Tab, U221E, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 9, parenleft ], symbols[2]= [ 9, parenleft ], symbols[3]= [ 9, parenleft, bracketleft, NoSymbol, NoSymbol, plusminus, NoSymbol, NoSymbol ], symbols[4]= [ 9, leftdoublequotemark, leftsinglequotemark, U27E9, KP_Divide, KP_Divide, variation, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ 0, parenright ], symbols[2]= [ 0, parenright ], symbols[3]= [ 0, parenright, bracketright, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ 0, rightdoublequotemark, rightsinglequotemark, zerosubscript, KP_Multiply, KP_Multiply, emptyset, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ minus, underscore ], symbols[2]= [ minus, underscore ], symbols[3]= [ minus, underscore, onehalf, NoSymbol, NoSymbol, questiondown, NoSymbol, NoSymbol ], symbols[4]= [ minus, emdash, NoSymbol, U2011, KP_Subtract, KP_Subtract, hyphen, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ equal, plus ], symbols[2]= [ equal, plus ], symbols[3]= [ equal, plus, notsign, NoSymbol, dead_cedilla, dead_ogonek, NoSymbol, NoSymbol ], symbols[4]= [ dead_grave, dead_cedilla, dead_abovering, dead_abovereversedcomma, dead_diaeresis, NoSymbol, dead_macron, NoSymbol ] }; key { [ BackSpace, BackSpace ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ Tab, ISO_Left_Tab ], symbols[2]= [ Tab, ISO_Left_Tab ], symbols[3]= [ Tab, ISO_Left_Tab ], symbols[4]= [ Tab, ISO_Left_Tab, Multi_key, ISO_Level5_Lock, NoSymbol, NoSymbol, NoSymbol, ISO_Level5_Lock ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ q, Q ], symbols[2]= [ Cyrillic_shorti, Cyrillic_SHORTI ], symbols[3]= [ q, Q, NoSymbol, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol, NoSymbol ], symbols[4]= [ x, X, ellipsis, Greek_xi, Prior, Prior, Greek_XI, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ w, W ], symbols[2]= [ Cyrillic_tse, Cyrillic_TSE ], symbols[3]= [ w, W, NoSymbol, NoSymbol, lstroke, Lstroke, NoSymbol, NoSymbol ], symbols[4]= [ v, V, underscore, NoSymbol, BackSpace, BackSpace, radical, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ e, E ], symbols[2]= [ Cyrillic_u, Cyrillic_U ], symbols[3]= [ e, E, NoSymbol, NoSymbol, oe, OE, NoSymbol, NoSymbol ], symbols[4]= [ l, L, bracketleft, Greek_lamda, Up, Up, Greek_LAMDA, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ r, R ], symbols[2]= [ Cyrillic_ka, Cyrillic_KA ], symbols[3]= [ r, R, NoSymbol, NoSymbol, paragraph, registered, NoSymbol, NoSymbol ], symbols[4]= [ c, C, bracketright, Greek_chi, Delete, Delete, U2102, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ t, T ], symbols[2]= [ Cyrillic_ie, Cyrillic_IE ], symbols[3]= [ t, T, NoSymbol, NoSymbol, tslash, Tslash, NoSymbol, NoSymbol ], symbols[4]= [ w, W, asciicircum, Greek_omega, Next, Next, Greek_OMEGA, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ y, Y ], symbols[2]= [ Cyrillic_en, Cyrillic_EN ], symbols[3]= [ y, Y, NoSymbol, NoSymbol, leftarrow, yen, NoSymbol, NoSymbol ], symbols[4]= [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ u, U ], symbols[2]= [ Cyrillic_ghe, Cyrillic_GHE ], symbols[3]= [ u, U, NoSymbol, NoSymbol, downarrow, uparrow, NoSymbol, NoSymbol ], symbols[4]= [ h, H, less, Greek_psi, KP_7, KP_7, Greek_PSI, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ i, I ], symbols[2]= [ Cyrillic_sha, Cyrillic_SHA ], symbols[3]= [ i, I, NoSymbol, NoSymbol, rightarrow, idotless, NoSymbol, NoSymbol ], symbols[4]= [ g, G, greater, Greek_gamma, KP_8, KP_8, Greek_GAMMA, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ o, O ], symbols[2]= [ Cyrillic_shcha, Cyrillic_SHCHA ], symbols[3]= [ o, O, section, NoSymbol, oslash, Oslash, NoSymbol, NoSymbol ], symbols[4]= [ f, F, equal, Greek_phi, KP_9, KP_9, Greek_PHI, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ p, P ], symbols[2]= [ Cyrillic_ze, Cyrillic_ZE ], symbols[3]= [ p, P, paragraph, NoSymbol, thorn, THORN, NoSymbol, NoSymbol ], symbols[4]= [ q, Q, ampersand, U03D5, KP_Add, KP_Add, U211A, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ bracketleft, braceleft ], symbols[2]= [ Cyrillic_ha, Cyrillic_HA ], symbols[3]= [ dead_circumflex, dead_diaeresis, dead_grave, NoSymbol, NoSymbol, dead_abovering, NoSymbol, NoSymbol ], symbols[4]= [ ssharp, U1E9E, U017F, Greek_finalsmallsigma, U2212, NoSymbol, jot, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ bracketright, braceright ], symbols[2]= [ Cyrillic_hardsign, Cyrillic_HARDSIGN ], symbols[3]= [ ccedilla, Ccedilla, asciitilde, NoSymbol, dead_tilde, dead_macron, NoSymbol, NoSymbol ], symbols[4]= [ dead_acute, dead_tilde, dead_stroke, dead_abovecomma, dead_doubleacute, NoSymbol, dead_breve, NoSymbol ] }; key { [ Return ] }; key { [ Control_L ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ a, A ], symbols[2]= [ Cyrillic_ef, Cyrillic_EF ], symbols[3]= [ a, A, NoSymbol, NoSymbol, ae, AE, NoSymbol, NoSymbol ], symbols[4]= [ u, U, backslash, NoSymbol, Home, Home, includedin, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ s, S ], symbols[2]= [ Cyrillic_yeru, Cyrillic_YERU ], symbols[3]= [ s, S, NoSymbol, NoSymbol, ssharp, section, NoSymbol, NoSymbol ], symbols[4]= [ i, I, slash, Greek_iota, Left, Left, integral, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ d, D ], symbols[2]= [ Cyrillic_ve, Cyrillic_VE ], symbols[3]= [ d, D, NoSymbol, NoSymbol, eth, ETH, NoSymbol, NoSymbol ], symbols[4]= [ a, A, braceleft, Greek_alpha, Down, Down, U2200, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ f, F ], symbols[2]= [ Cyrillic_a, Cyrillic_A ], symbols[3]= [ f, F, NoSymbol, NoSymbol, NoSymbol, ordfeminine, NoSymbol, NoSymbol ], symbols[4]= [ e, E, braceright, Greek_epsilon, Right, Right, U2203, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ g, G ], symbols[2]= [ Cyrillic_pe, Cyrillic_PE ], symbols[3]= [ g, G, NoSymbol, NoSymbol, eng, ENG, NoSymbol, NoSymbol ], symbols[4]= [ o, O, asterisk, Greek_omicron, End, End, elementof, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ h, H ], symbols[2]= [ Cyrillic_er, Cyrillic_ER ], symbols[3]= [ h, H, NoSymbol, NoSymbol, hstroke, Hstroke, NoSymbol, NoSymbol ], symbols[4]= [ s, S, question, Greek_sigma, questiondown, NoSymbol, Greek_SIGMA, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ j, J ], symbols[2]= [ Cyrillic_o, Cyrillic_O ], symbols[3]= [ j, J, NoSymbol, NoSymbol, U0133, U0132, NoSymbol, NoSymbol ], symbols[4]= [ n, N, parenleft, Greek_nu, KP_4, KP_4, U2115, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ k, K ], symbols[2]= [ Cyrillic_el, Cyrillic_EL ], symbols[3]= [ k, K, NoSymbol, NoSymbol, kra, NoSymbol, NoSymbol, NoSymbol ], symbols[4]= [ r, R, parenright, Greek_rho, KP_5, KP_5, U211D, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ l, L ], symbols[2]= [ Cyrillic_de, Cyrillic_DE ], symbols[3]= [ l, L, NoSymbol, NoSymbol, U0140, U013F, NoSymbol, NoSymbol ], symbols[4]= [ t, T, minus, Greek_tau, KP_6, KP_6, partialderivative, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ semicolon, colon ], symbols[2]= [ Cyrillic_zhe, Cyrillic_ZHE ], symbols[3]= [ semicolon, colon, degree, NoSymbol, dead_acute, dead_doubleacute, NoSymbol, NoSymbol ], symbols[4]= [ d, D, colon, Greek_delta, KP_Separator, comma, Greek_DELTA, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ apostrophe, quotedbl ], symbols[2]= [ Cyrillic_e, Cyrillic_E ], symbols[3]= [ egrave, Egrave, braceleft, NoSymbol, NoSymbol, dead_caron, NoSymbol, NoSymbol ], symbols[4]= [ y, Y, at, Greek_upsilon, period, KP_Decimal, nabla, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ grave, asciitilde ], symbols[2]= [ Cyrillic_io, Cyrillic_IO ], symbols[3]= [ slash, backslash, bar, NoSymbol, NoSymbol, hyphen, NoSymbol, NoSymbol ], symbols[4]= [ dead_circumflex, dead_caron, U21BB, U02DE, dead_abovedot, Pointer_EnableKeys, dead_belowdot, NoSymbol ] }; key { type[4]= "TWO_LEVEL", symbols[1]= [ Shift_L ], symbols[2]= [ Shift_L ], symbols[3]= [ Shift_L ], symbols[4]= [ Shift_L, Caps_Lock ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "ONE_LEVEL", symbols[1]= [ backslash, bar ], symbols[2]= [ backslash, slash ], symbols[3]= [ agrave, Agrave, braceright, NoSymbol, NoSymbol, dead_breve, NoSymbol, NoSymbol ], symbols[4]= [ ISO_Level3_Shift ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "FOUR_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ z, Z ], symbols[2]= [ Cyrillic_ya, Cyrillic_YA ], symbols[3]= [ z, Z, guillemotleft, NoSymbol ], symbols[4]= [ udiaeresis, Udiaeresis, numbersign, NoSymbol, Escape, Escape, union, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "FOUR_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ x, X ], symbols[2]= [ Cyrillic_che, Cyrillic_CHE ], symbols[3]= [ x, X, guillemotright, NoSymbol ], symbols[4]= [ odiaeresis, Odiaeresis, dollar, U03F5, Tab, Tab, intersection, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ c, C ], symbols[2]= [ Cyrillic_es, Cyrillic_ES ], symbols[3]= [ c, C, NoSymbol, NoSymbol, cent, copyright, NoSymbol, NoSymbol ], symbols[4]= [ adiaeresis, Adiaeresis, bar, Greek_eta, Insert, Insert, U2135, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ v, V ], symbols[2]= [ Cyrillic_em, Cyrillic_EM ], symbols[3]= [ v, V, NoSymbol, NoSymbol, leftdoublequotemark, leftsinglequotemark, NoSymbol, NoSymbol ], symbols[4]= [ p, P, asciitilde, Greek_pi, Return, Return, Greek_PI, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ b, B ], symbols[2]= [ Cyrillic_i, Cyrillic_I ], symbols[3]= [ b, B, NoSymbol, NoSymbol, rightdoublequotemark, rightsinglequotemark, NoSymbol, NoSymbol ], symbols[4]= [ z, Z, grave, Greek_zeta, Undo, Undo, U2124, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ n, N ], symbols[2]= [ Cyrillic_te, Cyrillic_TE ], symbols[3]= [ n, N, NoSymbol, NoSymbol, U0149, U266A, NoSymbol, NoSymbol ], symbols[4]= [ b, B, plus, Greek_beta, colon, NoSymbol, U21D0, NoSymbol ] }; key { type[1]= "ALPHABETIC", type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ m, M ], symbols[2]= [ Cyrillic_softsign, Cyrillic_SOFTSIGN ], symbols[3]= [ m, M, mu, NoSymbol, mu, masculine, NoSymbol, NoSymbol ], symbols[4]= [ m, M, percent, Greek_mu, KP_1, KP_1, ifonlyif, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ comma, less ], symbols[2]= [ Cyrillic_be, Cyrillic_BE ], symbols[3]= [ comma, apostrophe, less, NoSymbol, Greek_horizbar, multiply, NoSymbol, NoSymbol ], symbols[4]= [ comma, endash, quotedbl, U03F1, KP_2, KP_2, U21D2, NoSymbol ] }; key { type[2]= "ALPHABETIC", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL", symbols[1]= [ period, greater ], symbols[2]= [ Cyrillic_yu, Cyrillic_YU ], symbols[3]= [ period, quotedbl, greater, NoSymbol, periodcentered, division, NoSymbol, NoSymbol ], symbols[4]= [ period, enfilledcircbullet, apostrophe, U03D1, KP_3, KP_3, U21A6, NoSymbol ] }; key { type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "EIGHT_LEVEL_SEMIALPHABETIC", symbols[1]= [ slash, question ], symbols[2]= [ period, comma ], symbols[3]= [ eacute, Eacute, dead_acute, NoSymbol, NoSymbol, dead_abovedot, NoSymbol, NoSymbol ], symbols[4]= [ j, J, semicolon, Greek_theta, semicolon, NoSymbol, Greek_THETA, NoSymbol ] }; key { type[4]= "TWO_LEVEL", symbols[1]= [ Shift_R ], symbols[2]= [ Shift_R ], symbols[3]= [ Shift_R ], symbols[4]= [ Shift_R, Caps_Lock ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ], symbols[2]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ], symbols[3]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ], symbols[4]= [ KP_Multiply, KP_Multiply, U2219, U2299, multiply, NoSymbol, U2297, NoSymbol ] }; key { [ Alt_L, Meta_L ] }; key { type[3]= "FOUR_LEVEL", type[4]= "EIGHT_LEVEL", symbols[1]= [ space ], symbols[2]= [ space ], symbols[3]= [ space, space, nobreakspace, NoSymbol ], symbols[4]= [ space, space, space, nobreakspace, KP_0, KP_0, U202F, NoSymbol ] }; key { type= "ONE_LEVEL", symbols[1]= [ Caps_Lock ], symbols[2]= [ Caps_Lock ], symbols[3]= [ Caps_Lock ], symbols[4]= [ ISO_Level3_Shift ] }; key { type= "CTRL+ALT", symbols[1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ] }; key { type= "CTRL+ALT", symbols[1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ] }; key { type= "CTRL+ALT", symbols[1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ] }; key { type= "CTRL+ALT", symbols[1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ] }; key { type= "CTRL+ALT", symbols[1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ] }; key { type= "CTRL+ALT", symbols[1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ] }; key { type= "CTRL+ALT", symbols[1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ] }; key { type= "CTRL+ALT", symbols[1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ] }; key { type= "CTRL+ALT", symbols[1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ] }; key { type= "CTRL+ALT", symbols[1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ Num_Lock ], symbols[2]= [ Num_Lock ], symbols[3]= [ Num_Lock ], symbols[4]= [ Tab, ISO_Left_Tab, equal, approxeq, notequal, Pointer_EnableKeys, identical, NoSymbol ] }; key { [ Scroll_Lock ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Home, KP_7 ], symbols[2]= [ KP_Home, KP_7 ], symbols[3]= [ KP_Home, KP_7 ], symbols[4]= [ KP_7, U2714, U2195, U226A, KP_Home, KP_Home, upstile, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Up, KP_8 ], symbols[2]= [ KP_Up, KP_8 ], symbols[3]= [ KP_Up, KP_8 ], symbols[4]= [ KP_8, U2718, uparrow, intersection, KP_Up, KP_Up, U22C2, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Prior, KP_9 ], symbols[2]= [ KP_Prior, KP_9 ], symbols[3]= [ KP_Prior, KP_9 ], symbols[4]= [ KP_9, dagger, U20D7, U226B, KP_Prior, KP_Prior, U2309, NoSymbol ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ], symbols[2]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ], symbols[3]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ], symbols[4]= [ KP_Subtract, KP_Subtract, U2212, U2296, U2216, NoSymbol, U2238, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Left, KP_4 ], symbols[2]= [ KP_Left, KP_4 ], symbols[3]= [ KP_Left, KP_4 ], symbols[4]= [ KP_4, club, leftarrow, includedin, KP_Left, KP_Left, U2286, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Begin, KP_5 ], symbols[2]= [ KP_Begin, KP_5 ], symbols[3]= [ KP_Begin, KP_5 ], symbols[4]= [ KP_5, EuroSign, colon, U22B6, KP_Begin, KP_Begin, U22B7, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Right, KP_6 ], symbols[2]= [ KP_Right, KP_6 ], symbols[3]= [ KP_Right, KP_6 ], symbols[4]= [ KP_6, U2023, rightarrow, includes, KP_Right, KP_Right, U2287, NoSymbol ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ], symbols[2]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ], symbols[3]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ], symbols[4]= [ KP_Add, KP_Add, plusminus, U2295, U2213, NoSymbol, U2214, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_End, KP_1 ], symbols[2]= [ KP_End, KP_1 ], symbols[3]= [ KP_End, KP_1 ], symbols[4]= [ KP_1, diamond, U2194, lessthanequal, KP_End, KP_End, downstile, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Down, KP_2 ], symbols[2]= [ KP_Down, KP_2 ], symbols[3]= [ KP_Down, KP_2 ], symbols[4]= [ KP_2, heart, downarrow, union, KP_Down, KP_Down, U22C3, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Next, KP_3 ], symbols[2]= [ KP_Next, KP_3 ], symbols[3]= [ KP_Next, KP_3 ], symbols[4]= [ KP_3, U2660, U21CC, greaterthanequal, KP_Next, KP_Next, U230B, NoSymbol ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Insert, KP_0 ], symbols[2]= [ KP_Insert, KP_0 ], symbols[3]= [ KP_Insert, KP_0 ], symbols[4]= [ KP_0, U2423, percent, U2030, KP_Insert, KP_Insert, U25A1, NoSymbol ] }; key { type[2]= "KEYPAD", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Delete, KP_Decimal ], symbols[2]= [ KP_Delete, KP_Separator ], symbols[3]= [ KP_Delete, KP_Decimal ], symbols[4]= [ KP_Separator, period, comma, minutes, KP_Delete, KP_Delete, seconds, NoSymbol ] }; key { [ ISO_Level3_Shift ] }; key { type[1]= "FOUR_LEVEL", type[3]= "EIGHT_LEVEL_SEMIALPHABETIC", type[4]= "ONE_LEVEL", symbols[1]= [ less, greater, bar, brokenbar ], symbols[2]= [ slash, bar ], symbols[3]= [ ugrave, Ugrave, degree, NoSymbol, NoSymbol, brokenbar, NoSymbol, NoSymbol ], symbols[4]= [ ISO_Level5_Shift ] }; key { type= "CTRL+ALT", symbols[1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ] }; key { type= "CTRL+ALT", symbols[1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ] }; key { repeat= No, symbols[1]= [ Control_L, { Control_L, Mode_switch } ], actions[1]= [ SetMods(modifiers=Control), { SetMods(modifiers=Control), SetGroup(group=+1) } ], symbols[2]= [ { Control_L, Mode_switch }, Control_L ], actions[2]= [ { SetMods(modifiers=Control), SetGroup(group=+1) }, SetMods(modifiers=Control) ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Henkan_Mode ] }; key { [ Hiragana_Katakana ] }; key { [ Muhenkan ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Enter ], symbols[2]= [ KP_Enter ], symbols[3]= [ KP_Enter ], symbols[4]= [ KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, NoSymbol ] }; key { type= "ONE_LEVEL", symbols[1]= [ Control_R ], symbols[2]= [ Control_R ], symbols[3]= [ ISO_Level5_Shift ] }; key { type[1]= "CTRL+ALT", type[2]= "CTRL+ALT", type[3]= "CTRL+ALT", type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ], symbols[2]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ], symbols[3]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ], symbols[4]= [ KP_Divide, KP_Divide, division, U2300, U2215, NoSymbol, U2223, NoSymbol ] }; key { type= "PC_ALT_LEVEL2", symbols[1]= [ Print, Sys_Req ] }; key { type[1]= "TWO_LEVEL", type[2]= "TWO_LEVEL", type[3]= "ONE_LEVEL", type[4]= "ONE_LEVEL", symbols[1]= [ Alt_R, Meta_R ], symbols[2]= [ Alt_R, Meta_R ], symbols[3]= [ ISO_Level3_Shift ], symbols[4]= [ ISO_Level5_Shift ] }; key { [ Linefeed ] }; key { [ Home ] }; key { [ Up ] }; key { [ Prior ] }; key { [ Left ] }; key { [ Right ] }; key { [ End ] }; key { [ Down ] }; key { [ Next ] }; key { [ Insert ] }; key { [ Delete ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { type[4]= "EIGHT_LEVEL", symbols[1]= [ KP_Equal ], symbols[2]= [ KP_Equal ], symbols[3]= [ KP_Equal ], symbols[4]= [ KP_Equal, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; key { [ plusminus ] }; key { type= "PC_CONTROL_LEVEL2", symbols[1]= [ Pause, Break ] }; key { [ XF86LaunchA ] }; key { [ KP_Decimal, KP_Decimal ] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ Super_L ] }; key { [ Super_R ] }; key { [ Menu ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ SunOpen ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Eject ] }; key { [ XF86Eject, XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ Mode_switch ] }; key { [ NoSymbol, Alt_L ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; key { [ NoSymbol, Hyper_L ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; key { [ Print ] }; key { [ XF86WebCam ] }; key { [ XF86Mail ] }; key { [ XF86Messenger ] }; key { [ XF86Search ] }; key { [ XF86Go ] }; key { [ XF86Finance ] }; key { [ XF86Game ] }; key { [ XF86Shop ] }; key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; modifier_map Shift { , }; modifier_map Lock { }; modifier_map Control { }; modifier_map Mod1 { , , }; modifier_map Mod2 { }; modifier_map Mod3 { }; modifier_map Mod4 { , , , }; modifier_map Mod5 { , }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/symbols-modifier_map.xkb000066400000000000000000000037541510033435100270640ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 0; maximum = 255; <0> = 0; <1> = 1; <2> = 2; <3> = 3; <4> = 4; <5> = 5; <6> = 6; <7> = 7; = 10; = 11; = 61; = 62; = 63; = 66; <100> = 100; alias = ; }; xkb_types "basic" { virtual_modifiers NumLock; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; }; xkb_compatibility { virtual_modifiers NumLock; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key <0> { [ 0 ] }; key <1> { [ 1 ] }; key <2> { [ 2 ] }; key <3> { [ NoSymbol, 3 ] }; key <4> { [ U1F54A ] }; key <5> { [ UFFFD, UFFFD ] }; key <6> { [ UFDD0, UFDEF ] }; key <7> { [ UFFFE, UFFFF ] }; key { [ NoSymbol, A ] }; key { [ VoidSymbol, N ] }; key { [ a ] }; key { [ b ] }; key { [ U1F3BA ] }; key { [ Caps_Lock ] }; key <100> { [ C ] }; modifier_map Lock { <0>, <1>, <4>, <5>, <6>, <7>, , , , , , <100> }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/symbols-multi-actions-v1.xkb000066400000000000000000000007661510033435100275450ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <> = 1; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret A+AnyOfOrNone(all) { action= LockControls(controls=none,affect=neither); }; }; xkb_symbols { key <> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ LockControls(controls=none,affect=neither) ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/symbols-multi-actions.xkb000066400000000000000000000174041510033435100272160ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <01> = 1; <02> = 2; <03> = 3; <04> = 4; <05> = 5; <06> = 6; <07> = 7; <08> = 8; <09> = 9; <10> = 10; <11> = 11; <12> = 12; <13> = 13; <14> = 14; <15> = 15; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Shift Lock"; }; xkb_types "basic_extra" { virtual_modifiers NumLock=0x100,Alt=0x200,LevelThree=0x400,AltGr=0x800; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= 2; map[Shift]= 2; map[LevelThree]= 3; map[NumLock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= 2; map[Shift+LevelThree]= 3; map[Control+Alt]= 4; level_name[1]= "Base"; level_name[2]= "Alt Base"; level_name[3]= "Shift Alt"; level_name[4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 4; preserve[Lock]= Lock; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr Base"; level_name[4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock]= 5; map[Shift+Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Lock"; }; }; xkb_compatibility "basic" { virtual_modifiers NumLock=0x100,Alt=0x200,LevelThree=0x400,AltGr=0x800; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; }; xkb_symbols { key <01> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=Control) ] }; key <02> { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetMods(modifiers=Control), SetGroup(group=+1) ] }; key <04> { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=+1) ] }; key <05> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=Control) ] }; key <07> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=Control) ] }; key <08> { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetMods(modifiers=Control), SetGroup(group=+1) ] }; key <09> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ { SetMods(modifiers=Control), SetGroup(group=+1) } ] }; key <10> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ { SetMods(modifiers=Control), SetGroup(group=+1), Private(type=0x11,data[0]=0x66,data[1]=0x6f,data[2]=0x6f,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00) } ] }; key <11> { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetMods(modifiers=Control), { SetGroup(group=+1), Private(type=0x11,data[0]=0x66,data[1]=0x6f,data[2]=0x6f,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00) } ] }; key <12> { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetMods(modifiers=Control), SetGroup(group=+1) }, Private(type=0x11,data[0]=0x66,data[1]=0x6f,data[2]=0x6f,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00) ] }; key <13> { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetMods(modifiers=Control), SetGroup(group=+1) }, { Private(type=0x11,data[0]=0x66,data[1]=0x6f,data[2]=0x6f,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00), Private(type=0x11,data[0]=0x62,data[1]=0x61,data[2]=0x72,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00) } ] }; key <14> { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ { SetMods(modifiers=Control), SetGroup(group=+1) }, Private(type=0x11,data[0]=0x66,data[1]=0x6f,data[2]=0x6f,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00), { Private(type=0x11,data[0]=0x62,data[1]=0x61,data[2]=0x72,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00), SetMods(modifiers=Control) }, NoAction() ] }; key <15> { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ { SetMods(modifiers=Control), SetGroup(group=+1) }, { Private(type=0x11,data[0]=0x66,data[1]=0x6f,data[2]=0x6f,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00), Private(type=0x11,data[0]=0x62,data[1]=0x61,data[2]=0x72,data[3]=0x00,data[4]=0x00,data[5]=0x00,data[6]=0x00) }, SetMods(modifiers=Control), NoAction() ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/symbols-multi-keysyms-empty.xkb000066400000000000000000000151551510033435100304170ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; <10> = 10; <11> = 11; <12> = 12; <13> = 13; <14> = 14; <15> = 15; <16> = 16; <17> = 17; <18> = 18; <19> = 19; <20> = 20; <21> = 21; <22> = 22; <23> = 23; <30> = 30; <31> = 31; <32> = 32; <33> = 33; <34> = 34; <35> = 35; <36> = 36; <37> = 37; <38> = 38; <39> = 39; }; xkb_types "basic_extra" { virtual_modifiers NumLock=0x100,Alt=0x200,LevelThree=0x400; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= 2; map[Shift]= 2; map[LevelThree]= 3; map[NumLock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= 2; map[Shift+LevelThree]= 3; map[Control+Alt]= 4; level_name[1]= "Base"; level_name[2]= "Alt Base"; level_name[3]= "Shift Alt"; level_name[4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 4; preserve[Lock]= Lock; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr Base"; level_name[4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock]= 5; map[Shift+Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Lock"; }; }; xkb_compatibility { virtual_modifiers NumLock=0x100,Alt=0x200,LevelThree=0x400; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret 1+AnyOfOrNone(all) { action= NoAction(); }; interpret 2+AnyOfOrNone(all) { action= NoAction(); }; interpret 3+AnyOfOrNone(all) { action= SetMods(modifiers=none); }; interpret 4+AnyOfOrNone(all) { action= {SetMods(modifiers=none), SetGroup(group=1)}; }; }; xkb_symbols { key <12> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=Shift) ] }; key <13> { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=Shift) ] }; key <14> { type= "TWO_LEVEL", symbols[1]= [ NoSymbol, NoSymbol ] }; key <15> { type= "TWO_LEVEL", symbols[1]= [ NoSymbol, NoSymbol ] }; key <16> { [ a, A ] }; key <17> { [ a, A ] }; key <18> { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[1]= [ a, A, NoSymbol, NoSymbol ] }; key <19> { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[1]= [ a, A, NoSymbol, NoSymbol ] }; key <20> { [ a, A, ae, NoSymbol ] }; key <21> { [ a, A, ae, NoSymbol ] }; key <22> { [ a, A, ae, AE ] }; key <23> { [ a, A, ae, AE ] }; key <32> { repeat= No, symbols[1]= [ a ], actions[1]= [ NoAction() ] }; key <33> { repeat= No, symbols[1]= [ a ], actions[1]= [ NoAction() ] }; key <34> { type= "TWO_LEVEL", repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), NoAction() ] }; key <35> { type= "TWO_LEVEL", repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), NoAction() ] }; key <38> { type= "FOUR_LEVEL_SEMIALPHABETIC", repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ NoAction(), NoAction(), NoAction(), NoAction() ] }; key <39> { type= "FOUR_LEVEL_SEMIALPHABETIC", repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ NoAction(), NoAction(), NoAction(), NoAction() ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/symbols-multi-keysyms.xkb000066400000000000000000000116731510033435100272640ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <01> = 1; <02> = 2; <03> = 3; <04> = 4; <05> = 5; <06> = 6; <07> = 7; <08> = 8; <09> = 9; <10> = 10; <11> = 11; <12> = 12; <13> = 13; <14> = 14; <15> = 15; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Shift Lock"; }; xkb_types "basic_extra" { virtual_modifiers NumLock=0x100,Alt=0x200,LevelThree=0x400,AltGr=0x800; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= 2; map[Shift]= 2; map[LevelThree]= 3; map[NumLock+LevelThree]= 3; map[Shift+LevelThree]= 4; map[Shift+NumLock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Number"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= 2; map[Shift+LevelThree]= 3; map[Control+Alt]= 4; level_name[1]= "Base"; level_name[2]= "Alt Base"; level_name[3]= "Shift Alt"; level_name[4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 4; preserve[Lock]= Lock; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "AltGr Base"; level_name[4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock]= 5; map[Shift+Lock]= 2; map[Lock+LevelThree]= 3; map[Shift+Lock+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; level_name[5]= "Lock"; }; }; xkb_compatibility "basic" { virtual_modifiers NumLock=0x100,Alt=0x200,LevelThree=0x400,AltGr=0x800; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; }; xkb_symbols { key <01> { [ a ] }; key <02> { [ a, b ] }; key <04> { [ NoSymbol, b ] }; key <05> { [ a ] }; key <07> { [ a ] }; key <08> { [ a, b ] }; key <09> { [ { a, b } ] }; key <10> { [ { a, b, c } ] }; key <11> { [ a, { b, c } ] }; key <12> { [ { a, b }, c ] }; key <13> { [ { a, b }, { c, d } ] }; key <14> { [ { a, b }, c, { d, a }, NoSymbol ] }; key <15> { [ { a, b }, { c, d }, a, NoSymbol ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/syntax-error.xkb000066400000000000000000001601661510033435100254210ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev+aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; virtual indicator 12 = "Shift Lock"; virtual indicator 13 = "Group 2"; virtual indicator 14 = "Mouse Keys"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= Level2; map[Lock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= Level2; map[NumLock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Number"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Control+Alt]= Level5; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift+Lock]= Level1; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Control]= Level5; map[Shift+Lock+Control]= Level5; map[Shift+Control]= Level6; map[Lock+Control]= Level6; map[Control+LevelThree]= Level7; map[Shift+Lock+Control+LevelThree]= Level7; map[Shift+Control+LevelThree]= Level8; map[Lock+Control+LevelThree]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; level_name[Level4]= "Shift Level3"; level_name[Level5]= "Ctrl"; level_name[Level6]= "Shift Ctrl"; level_name[Level7]= "Level3 Ctrl"; level_name[Level8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level8; map[Shift+Lock+LevelThree+LevelFive]= Level7; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; preserve[Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= Level8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelFive]= Level1; preserve[Shift+Lock+LevelFive]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift+NumLock]= Level1; map[NumLock]= Level2; map[Shift]= Level2; map[LevelThree]= Level3; map[NumLock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= Level2; map[Shift+LevelThree]= Level3; map[Control+Alt]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Alt Base"; level_name[Level3]= "Shift Alt"; level_name[Level4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level4; preserve[Lock]= Lock; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "AltGr Base"; level_name[Level4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock]= Level5; map[Shift+Lock]= Level2; map[Lock+LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Lock"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= Level2; map[NumLock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[NumLock+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Alt Number"; }; }; xkb_compatibility "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Lock+AnyOf(all) { action= ISOLock(modifiers=modMapMods,affect=all); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay1); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay2); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86LogGrabInfo+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret XF86LogWindowTree+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { !allowExplicit; whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { !allowExplicit; whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { !allowExplicit; whichModState= locked; modifiers= Shift; }; indicator "Group 2" { !allowExplicit; groups= 0xfe; }; indicator "Mouse Keys" { indicatorDrivesKeyboard; controls= mouseKeys; }; }; xkb_symbols "pc+us+inet(evdev)+ctrl(nocaps)+compose(rwin)+terminate(ctrl_alt_bksp)" { name[group1]="English (US)"; key { [ Escape ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ 5, percent ] }; key { [ 6, asciicircum ] }; key { [ 7, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { type= "CTRL+ALT", symbols[Group1]= [ BackSpace, BackSpace, NoSymbol, NoSymbol, Terminate_Server ] SYNTAX ERROR }; key { [ Tab, ISO_Left_Tab ] }; key { type= "ALPHABETIC", symbols[Group1]= [ q, Q ] }; key { type= "ALPHABETIC", symbols[Group1]= [ w, W ] }; key { type= "ALPHABETIC", symbols[Group1]= [ e, E ] }; key { type= "ALPHABETIC", symbols[Group1]= [ r, R ] }; key { type= "ALPHABETIC", symbols[Group1]= [ t, T ] }; key { type= "ALPHABETIC", symbols[Group1]= [ y, Y ] }; key { type= "ALPHABETIC", symbols[Group1]= [ u, U ] }; key { type= "ALPHABETIC", symbols[Group1]= [ i, I ] }; key { type= "ALPHABETIC", symbols[Group1]= [ o, O ] }; key { type= "ALPHABETIC", symbols[Group1]= [ p, P ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ Return ] }; key { [ Control_L ] }; key { type= "ALPHABETIC", symbols[Group1]= [ a, A ] }; key { type= "ALPHABETIC", symbols[Group1]= [ s, S ] }; key { type= "ALPHABETIC", symbols[Group1]= [ d, D ] }; key { type= "ALPHABETIC", symbols[Group1]= [ f, F ] }; key { type= "ALPHABETIC", symbols[Group1]= [ g, G ] }; key { type= "ALPHABETIC", symbols[Group1]= [ h, H ] }; key { type= "ALPHABETIC", symbols[Group1]= [ j, J ] }; key { type= "ALPHABETIC", symbols[Group1]= [ k, K ] }; key { type= "ALPHABETIC", symbols[Group1]= [ l, L ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ grave, asciitilde ] }; key { [ Shift_L ] }; key { [ backslash, bar ] }; key { type= "ALPHABETIC", symbols[Group1]= [ z, Z ] }; key { type= "ALPHABETIC", symbols[Group1]= [ x, X ] }; key { type= "ALPHABETIC", symbols[Group1]= [ c, C ] }; key { type= "ALPHABETIC", symbols[Group1]= [ v, V ] }; key { type= "ALPHABETIC", symbols[Group1]= [ b, B ] }; key { type= "ALPHABETIC", symbols[Group1]= [ n, N ] }; key { type= "ALPHABETIC", symbols[Group1]= [ m, M ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ slash, question ] }; key { [ Shift_R ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ] }; key { [ Alt_L, Meta_L ] }; key { [ space ] }; key { [ Control_L, Control_L ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ] }; key { [ Num_Lock ] }; key { [ Scroll_Lock ] }; key { [ KP_Home, KP_7 ] }; key { [ KP_Up, KP_8 ] }; key { [ KP_Prior, KP_9 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ] }; key { [ KP_Left, KP_4 ] }; key { [ KP_Begin, KP_5 ] }; key { [ KP_Right, KP_6 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ] }; key { [ KP_End, KP_1 ] }; key { [ KP_Down, KP_2 ] }; key { [ KP_Next, KP_3 ] }; key { [ KP_Insert, KP_0 ] }; key { [ KP_Delete, KP_Decimal ] }; key { [ ISO_Level3_Shift ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ less, greater, bar, brokenbar ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Henkan_Mode ] }; key { [ Hiragana_Katakana ] }; key { [ Muhenkan ] }; key { [ KP_Enter ] }; key { [ Control_R ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ] }; key { type= "PC_ALT_LEVEL2", symbols[Group1]= [ Print, Sys_Req ] }; key { type= "TWO_LEVEL", symbols[Group1]= [ Alt_R, Meta_R ] }; key { [ Linefeed ] }; key { [ Home ] }; key { [ Up ] }; key { [ Prior ] }; key { [ Left ] }; key { [ Right ] }; key { [ End ] }; key { [ Down ] }; key { [ Next ] }; key { [ Insert ] }; key { [ Delete ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { [ KP_Equal ] }; key { [ plusminus ] }; key { type= "PC_CONTROL_LEVEL2", symbols[Group1]= [ Pause, Break ] }; key { [ XF86LaunchA ] }; key { [ KP_Decimal, KP_Decimal ] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ Super_L ] }; key { type= "TWO_LEVEL", symbols[Group1]= [ Multi_key, Multi_key ] }; key { [ Menu ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ SunOpen ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Eject ] }; key { [ XF86Eject, XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ Mode_switch ] }; key { [ NoSymbol, Alt_L ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; key { [ NoSymbol, Hyper_L ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; key { [ Print ] }; key { [ XF86WebCam ] }; key { [ XF86Mail ] }; key { [ XF86Messenger ] }; key { [ XF86Search ] }; key { [ XF86Go ] }; key { [ XF86Finance ] }; key { [ XF86Game ] }; key { [ XF86Shop ] }; key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; modifier_map Control { }; modifier_map Shift { }; modifier_map Shift { }; modifier_map Mod1 { }; modifier_map Control { }; modifier_map Mod2 { }; modifier_map Mod5 { }; modifier_map Control { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod5 { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod4 { }; }; xkb_geometry "pc(pc105)" { width= 470; height= 180; alias = ; alias = ; baseColor= "white"; labelColor= "black"; xfont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; description= "Generic 105"; shape "NORM" { corner= 1, { [ 18, 18 ] }, { [ 2, 1 ], [ 16, 16 ] } }; shape "BKSP" { corner= 1, { [ 38, 18 ] }, { [ 2, 1 ], [ 36, 16 ] } }; shape "TABK" { corner= 1, { [ 28, 18 ] }, { [ 2, 1 ], [ 26, 16 ] } }; shape "BKSL" { corner= 1, { [ 28, 18 ] }, { [ 2, 1 ], [ 26, 16 ] } }; shape "RTRN" { corner= 1, { [ 0, 0 ], [ 28, 0 ], [ 28, 37 ], [ 5, 37 ], [ 5, 18 ], [ 0, 18 ] }, { [ 2, 1 ], [ 26, 1 ], [ 26, 35 ], [ 7, 35 ], [ 7, 16 ], [ 2, 16 ] }, approx= { [ 5, 0 ], [ 28, 37 ] } }; shape "CAPS" { corner= 1, { [ 33, 18 ] }, { [ 2, 1 ], [ 31, 16 ] } }; shape "LFSH" { corner= 1, { [ 25, 18 ] }, { [ 2, 1 ], [ 23, 16 ] } }; shape "RTSH" { corner= 1, { [ 50, 18 ] }, { [ 2, 1 ], [ 48, 16 ] } }; shape "MODK" { corner= 1, { [ 27, 18 ] }, { [ 2, 1 ], [ 25, 16 ] } }; shape "SMOD" { corner= 1, { [ 23, 18 ] }, { [ 2, 1 ], [ 21, 16 ] } }; shape "SPCE" { corner= 1, { [ 113, 18 ] }, { [ 2, 1 ], [ 111, 16 ] } }; shape "KP0" { corner= 1, { [ 37, 18 ] }, { [ 2, 1 ], [ 35, 16 ] } }; shape "KPAD" { corner= 1, { [ 18, 37 ] }, { [ 2, 1 ], [ 16, 35 ] } }; shape "LEDS" { { [ 75, 20 ] } }; shape "LED" { { [ 5, 1 ] } }; section "Function" { key.color= "grey20"; priority= 7; top= 22; left= 19; width= 351; height= 19; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 20, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 11, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 11, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 8, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" } }; }; }; // End of "Function" section section "Alpha" { key.color= "white"; priority= 8; top= 61; left= 19; width= 287; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "BKSP", 1, color="grey20" } }; }; row { top= 20; left= 1; keys { { , "TABK", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "RTRN", 1, color="grey20" } }; }; row { top= 39; left= 1; keys { { , "CAPS", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 58; left= 1; keys { { , "LFSH", 1, color="grey20" }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "RTSH", 1, color="grey20" } }; }; row { top= 77; left= 1; keys { { , "MODK", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SPCE", 1 }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" }, { , "SMOD", 1, color="grey20" } }; }; }; // End of "Alpha" section section "Editing" { key.color= "grey20"; priority= 9; top= 61; left= 312; width= 58; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 20; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 58; left= 20; keys { { , "NORM", 1 } }; }; row { top= 77; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; }; // End of "Editing" section section "Keypad" { key.color= "grey20"; priority= 10; top= 61; left= 376; width= 77; height= 95; row { top= 1; left= 1; keys { { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 }, { , "NORM", 1 } }; }; row { top= 20; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "KPAD", 1 } }; }; row { top= 39; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" } }; }; row { top= 58; left= 1; keys { { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "NORM", 1, color="white" }, { , "KPAD", 1 } }; }; row { top= 77; left= 1; keys { { , "KP0", 1, color="white" }, { , "NORM", 1, color="white" } }; }; }; // End of "Keypad" section solid "LedPanel" { top= 22; left= 377; priority= 0; color= "grey10"; shape= "LEDS"; }; indicator "Num Lock" { top= 37; left= 382; priority= 1; onColor= "green"; offColor= "green30"; shape= "LED"; }; indicator "Caps Lock" { top= 37; left= 407; priority= 2; onColor= "green"; offColor= "green30"; shape= "LED"; }; indicator "Scroll Lock" { top= 37; left= 433; priority= 3; onColor= "green"; offColor= "green30"; shape= "LED"; }; text "NumLockLabel" { top= 25; left= 378; priority= 4; width= 19.8; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Num\nLock"; }; text "CapsLockLabel" { top= 25; left= 403; priority= 5; width= 26.4; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Caps\nLock"; }; text "ScrollLockLabel" { top= 25; left= 428; priority= 6; width= 39.6; height= 10; XFont= "-*-helvetica-medium-r-normal--*-120-*-*-*-*-iso8859-1"; text= "Scroll\nLock"; }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/syntax-error2.xkb000066400000000000000000000002561510033435100254740ustar00rootroot00000000000000xkb_keymap { xkb_compatibility "complete" { interpret ISO_Level2_Latch+Exactly(Shift) { action == LatchMods(modifiers=Shift,clearLocks,latchToLock); }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/unbound-vmod.xkb000066400000000000000000001422471510033435100253610ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev+aliases(qwertz)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; virtual indicator 12 = "Shift Lock"; virtual indicator 13 = "Group 2"; virtual indicator 14 = "Mouse Keys"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= Level2; map[Lock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= Level2; map[NumLock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Number"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= Level2; preserve[Shift]= Shift; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; preserve[Shift+LevelThree]= Shift; map[Control+Alt]= Level5; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift+Lock]= Level1; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Control]= Level5; map[Shift+Lock+Control]= Level5; map[Shift+Control]= Level6; map[Lock+Control]= Level6; map[Control+LevelThree]= Level7; map[Shift+Lock+Control+LevelThree]= Level7; map[Shift+Control+LevelThree]= Level8; map[Lock+Control+LevelThree]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; level_name[Level4]= "Shift Level3"; level_name[Level5]= "Ctrl"; level_name[Level6]= "Shift Ctrl"; level_name[Level7]= "Level3 Ctrl"; level_name[Level8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level8; map[Shift+Lock+LevelThree+LevelFive]= Level7; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; preserve[Lock+LevelFive]= Lock; map[Shift+Lock+LevelFive]= Level6; preserve[Shift+Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= Level8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift+NumLock]= Level1; map[NumLock]= Level2; map[Shift]= Level2; map[LevelThree]= Level3; map[NumLock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= Level2; map[Shift+LevelThree]= Level3; map[Control+Alt]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Alt Base"; level_name[Level3]= "Shift Alt"; level_name[Level4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level4; preserve[Lock]= Lock; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "AltGr Base"; level_name[Level4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock]= Level5; map[Shift+Lock]= Level2; map[Lock+LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Lock"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= Level2; map[NumLock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[NumLock+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Alt Number"; }; }; xkb_compatibility "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default,affect=both); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1,affect=both); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2,affect=both); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3,affect=both); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay1); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=Overlay2); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86LogGrabInfo+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret XF86LogWindowTree+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; group 2 = AltGr; group 3 = AltGr; group 4 = AltGr; indicator "Caps Lock" { !allowExplicit; whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { !allowExplicit; whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { !allowExplicit; whichModState= locked; modifiers= Shift; }; indicator "Group 2" { !allowExplicit; groups= 0xfe; }; indicator "Mouse Keys" { indicatorDrivesKeyboard; controls= mouseKeys; }; }; xkb_symbols "pc+de+inet(evdev)+group(menu_toggle)+ctrl(nocaps)" { name[group1]="German"; key { [ Escape ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 1, exclam, onesuperior, exclamdown ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 2, quotedbl, twosuperior, oneeighth ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 3, section, threesuperior, sterling ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 4, dollar, onequarter, currency ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 5, percent, onehalf, threeeighths ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 6, ampersand, notsign, fiveeighths ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 7, slash, braceleft, seveneighths ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 8, parenleft, bracketleft, trademark ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 9, parenright, bracketright, plusminus ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ 0, equal, braceright, degree ] }; key { type= "FOUR_LEVEL_PLUS_LOCK", symbols[Group1]= [ ssharp, question, backslash, questiondown, U1E9E ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ dead_acute, dead_grave, dead_cedilla, dead_ogonek ] }; key { [ BackSpace, BackSpace ] }; key { [ Tab, ISO_Left_Tab ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ q, Q, at, Greek_OMEGA ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ w, W, lstroke, Lstroke ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ e, E, EuroSign, EuroSign ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ r, R, paragraph, registered ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ t, T, tslash, Tslash ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ z, Z, leftarrow, yen ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ u, U, downarrow, uparrow ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ i, I, rightarrow, idotless ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ o, O, oslash, Oslash ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ p, P, thorn, THORN ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ plus, asterisk, asciitilde, macron ] }; key { [ Return ] }; key { [ Control_L ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ a, A, ae, AE ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ s, S, U017F, U1E9E ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ d, D, eth, ETH ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ f, F, dstroke, ordfeminine ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ g, G, eng, ENG ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ h, H, hstroke, Hstroke ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ j, J, dead_belowdot, dead_abovedot ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ k, K, kra, ampersand ] }; key { type= "FOUR_LEVEL_ALPHABETIC", symbols[Group1]= [ l, L, lstroke, Lstroke ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ dead_circumflex, degree, U2032, U2033 ] }; key { [ Shift_L ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ numbersign, apostrophe, rightsinglequotemark, dead_breve ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ y, Y, guillemotright, U203A ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ x, X, guillemotleft, U2039 ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ c, C, cent, copyright ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ v, V, doublelowquotemark, singlelowquotemark ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ b, B, leftdoublequotemark, leftsinglequotemark ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ n, N, rightdoublequotemark, rightsinglequotemark ] }; key { type= "FOUR_LEVEL_SEMIALPHABETIC", symbols[Group1]= [ m, M, mu, masculine ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ comma, semicolon, periodcentered, multiply ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ period, colon, U2026, division ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ minus, underscore, endash, emdash ] }; key { [ Shift_R ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ] }; key { [ Alt_L, Meta_L ] }; key { [ space ] }; key { [ Control_L, Control_L ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ] }; key { [ Num_Lock ] }; key { [ Scroll_Lock ] }; key { [ KP_Home, KP_7 ] }; key { [ KP_Up, KP_8 ] }; key { [ KP_Prior, KP_9 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ] }; key { [ KP_Left, KP_4 ] }; key { [ KP_Begin, KP_5 ] }; key { [ KP_Right, KP_6 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ] }; key { [ KP_End, KP_1 ] }; key { [ KP_Down, KP_2 ] }; key { [ KP_Next, KP_3 ] }; key { [ KP_Insert, KP_0 ] }; key { type= "KEYPAD", symbols[Group1]= [ KP_Delete, KP_Separator ] }; key { type= "ONE_LEVEL", symbols[Group1]= [ ISO_Level3_Shift ], actions[Group1]= [ SetMods(modifiers=LevelThree) ] }; key { type= "FOUR_LEVEL", symbols[Group1]= [ less, greater, bar, brokenbar ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Henkan_Mode ] }; key { [ Hiragana_Katakana ] }; key { [ Muhenkan ] }; key { [ KP_Enter ] }; key { [ Control_R ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ] }; key { type= "PC_ALT_LEVEL2", symbols[Group1]= [ Print, Sys_Req ] }; key { type= "ONE_LEVEL", symbols[Group1]= [ ISO_Level3_Shift ] }; key { [ Linefeed ] }; key { [ Home ] }; key { [ Up ] }; key { [ Prior ] }; key { [ Left ] }; key { [ Right ] }; key { [ End ] }; key { [ Down ] }; key { [ Next ] }; key { [ Insert ] }; key { [ Delete ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { [ KP_Equal ] }; key { [ plusminus ] }; key { type= "PC_CONTROL_LEVEL2", symbols[Group1]= [ Pause, Break ] }; key { [ XF86LaunchA ] }; key { [ KP_Decimal, KP_Decimal ] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ Super_L ] }; key { [ Super_R ] }; key { [ ISO_Next_Group, Menu ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ XF86Open ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Eject ] }; key { [ XF86Eject, XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ Mode_switch ] }; key { [ NoSymbol, Alt_L ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; key { [ NoSymbol, Hyper_L ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; key { [ Print ] }; key { [ XF86WebCam ] }; key { [ XF86Mail ] }; key { [ XF86Messenger ] }; key { [ XF86Search ] }; key { [ XF86Go ] }; key { [ XF86Finance ] }; key { [ XF86Game ] }; key { [ XF86Shop ] }; key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; modifier_map Control { }; modifier_map Shift { }; modifier_map Shift { }; modifier_map Mod1 { }; modifier_map Control { }; modifier_map Mod2 { }; modifier_map Mod5 { }; modifier_map Control { }; modifier_map Mod4 { }; modifier_map Mod4 { }; modifier_map Mod5 { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod4 { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/unicode-keysyms.xkb000066400000000000000000000241421510033435100260650ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev" { minimum = 8; maximum = 569; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; = 254; = 255; = 372; = 380; = 382; = 569; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; }; xkb_types "basic" { virtual_modifiers NumLock; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; }; xkb_compatibility { virtual_modifiers NumLock; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key { [ NoSymbol, 0x01000000 ] }; key { [ 0x01000001, 0x01000001 ] }; key { [ Linefeed, 0x0100000a ] }; key { [ 0x0100001f, 0x0100001f ] }; key { [ space, 0x01000020 ] }; key { [ asciitilde, 0x0100007e ] }; key { [ Delete, 0x0100007f ] }; key { [ 0x01000080, 0x01000080 ] }; key { [ 0x0100009f, 0x0100009f ] }; key { [ nobreakspace, 0x010000a0 ] }; key { [ ydiaeresis, 0x010000ff ] }; key { [ U0100, U0100 ] }; key { [ UD7FF, UD7FF ] }; key { [ UD800, UD800 ] }; key { [ UDFFF, UDFFF ] }; key { [ UE000, UE000 ] }; key { [ UFDCF, UFDCF ] }; key { [ UFDD0, UFDD0 ] }; key { [ UFDEF, UFDEF ] }; key { [ UFDF0, UFDF0 ] }; key { [ UFFFD, UFFFD ] }; key { [ UFFFE, UFFFE ] }; key { [ UFFFF, UFFFF ] }; key { [ U10000, U10000 ] }; key { [ U1FFFE, U1FFFE ] }; key { [ U1FFFF, U1FFFF ] }; key { [ U10FFFE, U10FFFE ] }; key { [ U10FFFF, U10FFFF ] }; key { [ NoSymbol, 0x01110000 ] }; key { [ Wcircumflex, Wcircumflex ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/unsupported-x11-actions000066400000000000000000000010121510033435100265760ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; <1> = 1; <2> = 2; <3> = 3; <4> = 4; <5> = 5; <6> = 6; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret ISO_Lock+AnyOfOrNone(all) { action= NoAction(); }; interpret VoidSymbol+AnyOfOrNone(all) { action= NoAction(); }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/locale/000077500000000000000000000000001510033435100220125ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/locale/compose.dir000066400000000000000000000775641510033435100242020ustar00rootroot00000000000000# # This file contains compose table file names. # The first word is the compose table file name # and the second word is the full locale name. # # iso8859-1/Compose C iso8859-1/Compose af_ZA.ISO8859-1 iso8859-6/Compose ar_AA.ISO8859-6 iso8859-6/Compose ar_AE.ISO8859-6 iso8859-6/Compose ar_BH.ISO8859-6 iso8859-6/Compose ar_DZ.ISO8859-6 iso8859-6/Compose ar_EG.ISO8859-6 iso8859-6/Compose ar_IQ.ISO8859-6 iso8859-6/Compose ar_JO.ISO8859-6 iso8859-6/Compose ar_KW.ISO8859-6 iso8859-6/Compose ar_LB.ISO8859-6 iso8859-6/Compose ar_LY.ISO8859-6 iso8859-6/Compose ar_MA.ISO8859-6 iso8859-6/Compose ar_OM.ISO8859-6 iso8859-6/Compose ar_QA.ISO8859-6 iso8859-6/Compose ar_SA.ISO8859-6 iso8859-6/Compose ar_SD.ISO8859-6 iso8859-6/Compose ar_SY.ISO8859-6 iso8859-6/Compose ar_TN.ISO8859-6 iso8859-6/Compose ar_YE.ISO8859-6 iso8859-9e/Compose az_AZ.ISO8859-9E koi8-c/Compose az_AZ.KOI8-C microsoft-cp1251/Compose be_BY.CP1251 iso8859-5/Compose be_BY.ISO8859-5 iso8859-5/Compose bg_BG.ISO8859-5 microsoft-cp1251/Compose bg_BG.CP1251 koi8-r/Compose bg_BG.KOI8-R iso8859-1/Compose br_FR.ISO8859-1 iso8859-14/Compose br_FR.ISO8859-14 iso8859-15/Compose br_FR.ISO8859-15 iso8859-2/Compose bs_BA.ISO8859-2 iso8859-1/Compose ca_AD.ISO8859-1 iso8859-15/Compose ca_AD.ISO8859-15 iso8859-1/Compose ca_ES.ISO8859-1 iso8859-15/Compose ca_ES.ISO8859-15 iso8859-1/Compose ca_FR.ISO8859-1 iso8859-15/Compose ca_FR.ISO8859-15 iso8859-1/Compose ca_IT.ISO8859-1 iso8859-15/Compose ca_IT.ISO8859-15 iso8859-2/Compose cs_CZ.ISO8859-2 iso8859-1/Compose cy_GB.ISO8859-1 iso8859-14/Compose cy_GB.ISO8859-14 iso8859-15/Compose cy_GB.ISO8859-15 iso8859-1/Compose da_DK.ISO8859-1 iso8859-15/Compose da_DK.ISO8859-15 iso8859-1/Compose de_AT.ISO8859-1 iso8859-15/Compose de_AT.ISO8859-15 iso8859-1/Compose de_BE.ISO8859-1 iso8859-15/Compose de_BE.ISO8859-15 iso8859-1/Compose de_CH.ISO8859-1 iso8859-15/Compose de_CH.ISO8859-15 iso8859-1/Compose de_DE.ISO8859-1 iso8859-15/Compose de_DE.ISO8859-15 iso8859-1/Compose de_LI.ISO8859-1 iso8859-15/Compose de_LI.ISO8859-15 iso8859-1/Compose de_LU.ISO8859-1 iso8859-15/Compose de_LU.ISO8859-15 iso8859-4/Compose ee_EE.ISO8859-4 iso8859-7/Compose el_GR.ISO8859-7 iso8859-15/Compose el_GR.ISO8859-15 iso8859-1/Compose en_AU.ISO8859-1 iso8859-1/Compose en_BE.ISO8859-1 iso8859-15/Compose en_BE.ISO8859-15 iso8859-1/Compose en_BW.ISO8859-1 iso8859-1/Compose en_BZ.ISO8859-1 iso8859-1/Compose en_CA.ISO8859-1 iso8859-1/Compose en_EN.ISO8859-1 iso8859-1/Compose en_GB.ISO8859-1 iso8859-15/Compose en_GB.ISO8859-15 iso8859-1/Compose en_HK.ISO8859-1 iso8859-1/Compose en_IE.ISO8859-1 iso8859-15/Compose en_IE.ISO8859-15 iso8859-15/Compose en_IN.ISO8859-15 iso8859-1/Compose en_JM.ISO8859-1 iso8859-1/Compose en_NZ.ISO8859-1 iso8859-1/Compose en_PH.ISO8859-1 iso8859-1/Compose en_SG.ISO8859-1 iso8859-1/Compose en_TT.ISO8859-1 iso8859-1/Compose en_UK.ISO8859-1 iso8859-15/Compose en_UK.ISO8859-15 iso8859-1/Compose en_US.ISO8859-1 iso8859-15/Compose en_US.ISO8859-15 iso8859-1/Compose en_ZA.ISO8859-1 iso8859-15/Compose en_ZA.ISO8859-15 iso8859-1/Compose en_ZW.ISO8859-1 iso8859-3/Compose eo_EO.ISO8859-3 iso8859-3/Compose eo_XX.ISO8859-3 iso8859-1/Compose es_AR.ISO8859-1 iso8859-1/Compose es_BO.ISO8859-1 iso8859-1/Compose es_CL.ISO8859-1 iso8859-1/Compose es_CO.ISO8859-1 iso8859-1/Compose es_CR.ISO8859-1 iso8859-1/Compose es_DO.ISO8859-1 iso8859-1/Compose es_EC.ISO8859-1 iso8859-1/Compose es_ES.ISO8859-1 iso8859-15/Compose es_ES.ISO8859-15 iso8859-1/Compose es_GT.ISO8859-1 iso8859-1/Compose es_HN.ISO8859-1 iso8859-1/Compose es_MX.ISO8859-1 iso8859-1/Compose es_NI.ISO8859-1 iso8859-1/Compose es_PA.ISO8859-1 iso8859-15/Compose es_PA.ISO8859-15 iso8859-1/Compose es_PE.ISO8859-1 iso8859-15/Compose es_PE.ISO8859-15 iso8859-1/Compose es_PR.ISO8859-1 iso8859-1/Compose es_PY.ISO8859-1 iso8859-15/Compose es_PY.ISO8859-15 iso8859-1/Compose es_SV.ISO8859-1 iso8859-15/Compose es_SV.ISO8859-15 iso8859-1/Compose es_US.ISO8859-1 iso8859-1/Compose es_UY.ISO8859-1 iso8859-15/Compose es_UY.ISO8859-15 iso8859-1/Compose es_VE.ISO8859-1 iso8859-15/Compose es_VE.ISO8859-15 iso8859-1/Compose et_EE.ISO8859-1 iso8859-4/Compose et_EE.ISO8859-4 iso8859-13/Compose et_EE.ISO8859-13 iso8859-15/Compose et_EE.ISO8859-15 iso8859-1/Compose eu_ES.ISO8859-1 iso8859-15/Compose eu_ES.ISO8859-15 isiri-3342/Compose fa_IR.ISIRI-3342 iso8859-1/Compose fi_FI.ISO8859-1 iso8859-15/Compose fi_FI.ISO8859-15 iso8859-1/Compose fo_FO.ISO8859-1 iso8859-15/Compose fo_FO.ISO8859-15 iso8859-1/Compose fr_BE.ISO8859-1 iso8859-15/Compose fr_BE.ISO8859-15 iso8859-1/Compose fr_CA.ISO8859-1 iso8859-15/Compose fr_CA.ISO8859-15 iso8859-1/Compose fr_CH.ISO8859-1 iso8859-15/Compose fr_CH.ISO8859-15 iso8859-1/Compose fr_FR.ISO8859-1 iso8859-15/Compose fr_FR.ISO8859-15 iso8859-1/Compose fr_LU.ISO8859-1 iso8859-15/Compose fr_LU.ISO8859-15 iso8859-1/Compose ga_IE.ISO8859-1 iso8859-14/Compose ga_IE.ISO8859-14 iso8859-15/Compose ga_IE.ISO8859-15 iso8859-1/Compose gd_GB.ISO8859-1 iso8859-14/Compose gd_GB.ISO8859-14 iso8859-15/Compose gd_GB.ISO8859-15 iso8859-1/Compose gl_ES.ISO8859-1 iso8859-15/Compose gl_ES.ISO8859-15 iso8859-1/Compose gv_GB.ISO8859-1 iso8859-14/Compose gv_GB.ISO8859-14 iso8859-15/Compose gv_GB.ISO8859-15 iso8859-8/Compose he_IL.ISO8859-8 microsoft-cp1255/Compose he_IL.CP1255 iscii-dev/Compose hi_IN.ISCII-DEV iso8859-2/Compose hr_HR.ISO8859-2 iso8859-2/Compose hu_HU.ISO8859-2 armscii-8/Compose hy_AM.ARMSCII-8 iso8859-1/Compose id_ID.ISO8859-1 iso8859-15/Compose id_ID.ISO8859-15 iso8859-1/Compose is_IS.ISO8859-1 iso8859-15/Compose is_IS.ISO8859-15 iso8859-1/Compose it_CH.ISO8859-1 iso8859-15/Compose it_CH.ISO8859-15 iso8859-1/Compose it_IT.ISO8859-1 iso8859-15/Compose it_IT.ISO8859-15 ja/Compose ja_JP.eucJP ja.SJIS/Compose ja_JP.SJIS ja.JIS/Compose ja_JP.JIS7 georgian-academy/Compose ka_GE.GEORGIAN-ACADEMY georgian-ps/Compose ka_GE.GEORGIAN-PS iso8859-1/Compose kl_GL.ISO8859-1 iso8859-15/Compose kl_GL.ISO8859-15 iso8859-1/Compose kw_GB.ISO8859-1 iso8859-14/Compose kw_GB.ISO8859-14 iso8859-15/Compose kw_GB.ISO8859-15 ko/Compose ko_KR.eucKR ibm-cp1133/Compose lo_LA.IBM-CP1133 mulelao-1/Compose lo_LA.MULELAO-1 iso8859-4/Compose lt_LT.ISO8859-4 iso8859-13/Compose lt_LT.ISO8859-13 iso8859-4/Compose lv_LV.ISO8859-4 iso8859-13/Compose lv_LV.ISO8859-13 iso8859-13/Compose mi_NZ.ISO8859-13 iso8859-5/Compose mk_MK.ISO8859-5 microsoft-cp1251/Compose mk_MK.CP1251 iso8859-1/Compose ms_MY.ISO8859-1 iso8859-3/Compose mt_MT.ISO8859-3 iso8859-1/Compose nl_BE.ISO8859-1 iso8859-15/Compose nl_BE.ISO8859-15 iso8859-1/Compose nl_NL.ISO8859-1 iso8859-15/Compose nl_NL.ISO8859-15 iso8859-1/Compose no_NO.ISO8859-1 iso8859-15/Compose no_NO.ISO8859-15 iso8859-1/Compose nb_NO.ISO8859-1 iso8859-15/Compose nb_NO.ISO8859-15 iso8859-1/Compose nn_NO.ISO8859-1 iso8859-15/Compose nn_NO.ISO8859-15 iso8859-1/Compose nr_ZA.ISO8859-1 iso8859-15/Compose nso_ZA.ISO8859-15 iso8859-1/Compose ny_NO.ISO8859-1 iso8859-15/Compose ny_NO.ISO8859-15 iso8859-1/Compose oc_FR.ISO8859-1 iso8859-15/Compose oc_FR.ISO8859-15 iso8859-1/Compose pd_DE.ISO8859-1 iso8859-15/Compose pd_DE.ISO8859-15 iso8859-1/Compose pd_US.ISO8859-1 iso8859-15/Compose pd_US.ISO8859-15 iso8859-1/Compose ph_PH.ISO8859-1 iso8859-2/Compose pl_PL.ISO8859-2 iso8859-1/Compose pp_AN.ISO8859-1 iso8859-1/Compose pt_BR.ISO8859-1 iso8859-15/Compose pt_BR.ISO8859-15 iso8859-1/Compose pt_PT.ISO8859-1 iso8859-15/Compose pt_PT.ISO8859-15 iso8859-2/Compose ro_RO.ISO8859-2 koi8-r/Compose ru_RU.KOI8-R iso8859-5/Compose ru_RU.ISO8859-5 microsoft-cp1251/Compose ru_RU.CP1251 microsoft-cp1251/Compose ru_UA.CP1251 koi8-u/Compose ru_UA.KOI8-U iso8859-1/Compose rw_RW.ISO8859-1 iso8859-2/Compose sh_YU.ISO8859-2 iso8859-2/Compose sk_SK.ISO8859-2 iso8859-2/Compose sl_SI.ISO8859-2 iso8859-2/Compose sq_AL.ISO8859-2 iso8859-2/Compose sr_YU.ISO8859-2 microsoft-cp1251/Compose sr_YU.CP1251 iso8859-5/Compose sr_YU.ISO8859-5 iso8859-1/Compose ss_ZA.ISO8859-1 iso8859-1/Compose st_ZA.ISO8859-1 iso8859-1/Compose sv_FI.ISO8859-1 iso8859-15/Compose sv_FI.ISO8859-15 iso8859-1/Compose sv_SE.ISO8859-1 iso8859-15/Compose sv_SE.ISO8859-15 tscii-0/Compose ta_IN.TSCII-0 koi8-c/Compose tg_TJ.KOI8-C iso8859-1/Compose tl_PH.ISO8859-1 iso8859-11/Compose th_TH.ISO8859-11 th_TH/Compose th_TH.TIS620 iso8859-15/Compose tn_ZA.ISO8859-15 iso8859-9/Compose tr_TR.ISO8859-9 iso8859-1/Compose ts_ZA.ISO8859-1 tatar-cyr/Compose tt_RU.TATAR-CYR microsoft-cp1251/Compose uk_UA.CP1251 koi8-c/Compose tt_RU.KOI8-C koi8-u/Compose uk_UA.KOI8-U iso8859-5/Compose uk_UA.ISO8859-5 microsoft-cp1256/Compose ur_PK.CP1256 iso8859-1/Compose uz_UZ.ISO8859-1 vi_VN.viscii/Compose vi_VN.VISCII vi_VN.tcvn/Compose vi_VN.TCVN iso8859-1/Compose wa_BE.ISO8859-1 iso8859-15/Compose wa_BE.ISO8859-15 iso8859-1/Compose xh_ZA.ISO8859-1 microsoft-cp1255/Compose yi_US.CP1255 zh_CN/Compose zh_CN.eucCN zh_CN/Compose zh_CN.gb2312 zh_CN.gbk/Compose zh_CN.gbk zh_CN.gb18030/Compose zh_CN.gb18030 zh_HK.big5/Compose zh_HK.big5 zh_HK.big5hkscs/Compose zh_HK.big5hkscs zh_TW.big5/Compose zh_TW.big5 zh_TW/Compose zh_TW.eucTW iso8859-1/Compose zu_ZA.ISO8859-1 # # en_US.UTF-8/Compose C.UTF-8 en_US.UTF-8/Compose af_ZA.UTF-8 am_ET.UTF-8/Compose am_ET.UTF-8 en_US.UTF-8/Compose ar_AA.UTF-8 en_US.UTF-8/Compose ar_AE.UTF-8 en_US.UTF-8/Compose ar_BH.UTF-8 en_US.UTF-8/Compose ar_DZ.UTF-8 en_US.UTF-8/Compose ar_EG.UTF-8 en_US.UTF-8/Compose ar_IN.UTF-8 en_US.UTF-8/Compose ar_IQ.UTF-8 en_US.UTF-8/Compose ar_JO.UTF-8 en_US.UTF-8/Compose ar_KW.UTF-8 en_US.UTF-8/Compose ar_LB.UTF-8 en_US.UTF-8/Compose ar_LY.UTF-8 en_US.UTF-8/Compose ar_MA.UTF-8 en_US.UTF-8/Compose ar_OM.UTF-8 en_US.UTF-8/Compose ar_QA.UTF-8 en_US.UTF-8/Compose ar_SA.UTF-8 en_US.UTF-8/Compose ar_SD.UTF-8 en_US.UTF-8/Compose ar_SY.UTF-8 en_US.UTF-8/Compose ar_TN.UTF-8 en_US.UTF-8/Compose ar_YE.UTF-8 en_US.UTF-8/Compose ast_ES.UTF-8 en_US.UTF-8/Compose as_IN.UTF-8 en_US.UTF-8/Compose az_AZ.UTF-8 en_US.UTF-8/Compose be_BY.UTF-8 en_US.UTF-8/Compose bg_BG.UTF-8 en_US.UTF-8/Compose bn_BD.UTF-8 en_US.UTF-8/Compose bn_IN.UTF-8 en_US.UTF-8/Compose bo_IN.UTF-8 en_US.UTF-8/Compose br_FR.UTF-8 en_US.UTF-8/Compose bs_BA.UTF-8 en_US.UTF-8/Compose ca_AD.UTF-8 en_US.UTF-8/Compose ca_ES.UTF-8 en_US.UTF-8/Compose ca_FR.UTF-8 en_US.UTF-8/Compose ca_IT.UTF-8 cs_CZ.UTF-8/Compose cs_CZ.UTF-8 en_US.UTF-8/Compose cy_GB.UTF-8 en_US.UTF-8/Compose da_DK.UTF-8 en_US.UTF-8/Compose de_AT.UTF-8 en_US.UTF-8/Compose de_BE.UTF-8 en_US.UTF-8/Compose de_CH.UTF-8 en_US.UTF-8/Compose de_DE.UTF-8 en_US.UTF-8/Compose de_IT.UTF-8 en_US.UTF-8/Compose de_LI.UTF-8 en_US.UTF-8/Compose de_LU.UTF-8 el_GR.UTF-8/Compose el_CY.UTF-8 el_GR.UTF-8/Compose el_GR.UTF-8 en_US.UTF-8/Compose en_AU.UTF-8 en_US.UTF-8/Compose en_BE.UTF-8 en_US.UTF-8/Compose en_BW.UTF-8 en_US.UTF-8/Compose en_BZ.UTF-8 en_US.UTF-8/Compose en_CA.UTF-8 en_US.UTF-8/Compose en_DK.UTF-8 en_US.UTF-8/Compose en_EN.UTF-8 en_US.UTF-8/Compose en_GB.UTF-8 en_US.UTF-8/Compose en_HK.UTF-8 en_US.UTF-8/Compose en_IE.UTF-8 en_US.UTF-8/Compose en_IN.UTF-8 en_US.UTF-8/Compose en_JM.UTF-8 en_US.UTF-8/Compose en_MT.UTF-8 en_US.UTF-8/Compose en_NZ.UTF-8 en_US.UTF-8/Compose en_PH.UTF-8 en_US.UTF-8/Compose en_SG.UTF-8 en_US.UTF-8/Compose en_TT.UTF-8 en_US.UTF-8/Compose en_UK.UTF-8 en_US.UTF-8/Compose en_US.UTF-8 en_US.UTF-8/Compose en_ZA.UTF-8 en_US.UTF-8/Compose en_ZW.UTF-8 en_US.UTF-8/Compose eo_EO.UTF-8 en_US.UTF-8/Compose eo_XX.UTF-8 en_US.UTF-8/Compose es_AR.UTF-8 en_US.UTF-8/Compose es_BO.UTF-8 en_US.UTF-8/Compose es_CL.UTF-8 en_US.UTF-8/Compose es_CO.UTF-8 en_US.UTF-8/Compose es_CR.UTF-8 en_US.UTF-8/Compose es_DO.UTF-8 en_US.UTF-8/Compose es_EC.UTF-8 en_US.UTF-8/Compose es_ES.UTF-8 en_US.UTF-8/Compose es_GT.UTF-8 en_US.UTF-8/Compose es_HN.UTF-8 en_US.UTF-8/Compose es_MX.UTF-8 en_US.UTF-8/Compose es_NI.UTF-8 en_US.UTF-8/Compose es_PA.UTF-8 en_US.UTF-8/Compose es_PE.UTF-8 en_US.UTF-8/Compose es_PR.UTF-8 en_US.UTF-8/Compose es_PY.UTF-8 en_US.UTF-8/Compose es_SV.UTF-8 en_US.UTF-8/Compose es_US.UTF-8 en_US.UTF-8/Compose es_UY.UTF-8 en_US.UTF-8/Compose es_VE.UTF-8 en_US.UTF-8/Compose et_EE.UTF-8 en_US.UTF-8/Compose eu_ES.UTF-8 en_US.UTF-8/Compose fa_IR.UTF-8 fi_FI.UTF-8/Compose fi_FI.UTF-8 en_US.UTF-8/Compose fo_FO.UTF-8 en_US.UTF-8/Compose fr_BE.UTF-8 en_US.UTF-8/Compose fr_CA.UTF-8 en_US.UTF-8/Compose fr_CH.UTF-8 en_US.UTF-8/Compose fr_FR.UTF-8 en_US.UTF-8/Compose fr_LU.UTF-8 en_US.UTF-8/Compose ga_IE.UTF-8 en_US.UTF-8/Compose gd_GB.UTF-8 en_US.UTF-8/Compose gl_ES.UTF-8 en_US.UTF-8/Compose gu_IN.UTF-8 en_US.UTF-8/Compose gv_GB.UTF-8 en_US.UTF-8/Compose he_IL.UTF-8 en_US.UTF-8/Compose hi_IN.UTF-8 en_US.UTF-8/Compose hne_IN.UTF-8 en_US.UTF-8/Compose hr_HR.UTF-8 en_US.UTF-8/Compose hu_HU.UTF-8 en_US.UTF-8/Compose hy_AM.UTF-8 en_US.UTF-8/Compose id_ID.UTF-8 en_US.UTF-8/Compose is_IS.UTF-8 en_US.UTF-8/Compose it_CH.UTF-8 en_US.UTF-8/Compose it_IT.UTF-8 en_US.UTF-8/Compose iu_CA.UTF-8 ja_JP.UTF-8/Compose ja_JP.UTF-8 en_US.UTF-8/Compose ka_GE.UTF-8 en_US.UTF-8/Compose kk_KZ.UTF-8 en_US.UTF-8/Compose kl_GL.UTF-8 km_KH.UTF-8/Compose km_KH.UTF-8 en_US.UTF-8/Compose kn_IN.UTF-8 ko_KR.UTF-8/Compose ko_KR.UTF-8 en_US.UTF-8/Compose ks_IN.UTF-8 en_US.UTF-8/Compose ks_IN.UTF-8@devanagari en_US.UTF-8/Compose ku_TR.UTF-8 en_US.UTF-8/Compose kw_GB.UTF-8 en_US.UTF-8/Compose ky_KG.UTF-8 en_US.UTF-8/Compose lo_LA.UTF-8 en_US.UTF-8/Compose lt_LT.UTF-8 en_US.UTF-8/Compose lv_LV.UTF-8 en_US.UTF-8/Compose mai_IN.UTF-8 en_US.UTF-8/Compose mi_NZ.UTF-8 en_US.UTF-8/Compose mk_MK.UTF-8 en_US.UTF-8/Compose ml_IN.UTF-8 en_US.UTF-8/Compose mr_IN.UTF-8 en_US.UTF-8/Compose ms_MY.UTF-8 en_US.UTF-8/Compose mt_MT.UTF-8 en_US.UTF-8/Compose ne_NP.UTF-8 en_US.UTF-8/Compose nl_BE.UTF-8 en_US.UTF-8/Compose nl_NL.UTF-8 en_US.UTF-8/Compose nn_NO.UTF-8 en_US.UTF-8/Compose no_NO.UTF-8 en_US.UTF-8/Compose nb_NO.UTF-8 en_US.UTF-8/Compose nr_ZA.UTF-8 en_US.UTF-8/Compose nso_ZA.UTF-8 en_US.UTF-8/Compose ny_NO.UTF-8 en_US.UTF-8/Compose oc_FR.UTF-8 en_US.UTF-8/Compose or_IN.UTF-8 en_US.UTF-8/Compose pa_IN.UTF-8 en_US.UTF-8/Compose pa_PK.UTF-8 en_US.UTF-8/Compose pd_DE.UTF-8 en_US.UTF-8/Compose pd_US.UTF-8 en_US.UTF-8/Compose ph_PH.UTF-8 en_US.UTF-8/Compose pl_PL.UTF-8 en_US.UTF-8/Compose pp_AN.UTF-8 pt_BR.UTF-8/Compose pt_BR.UTF-8 pt_PT.UTF-8/Compose pt_PT.UTF-8 en_US.UTF-8/Compose ro_RO.UTF-8 ru_RU.UTF-8/Compose ru_RU.UTF-8 en_US.UTF-8/Compose ru_UA.UTF-8 en_US.UTF-8/Compose rw_RW.UTF-8 en_US.UTF-8/Compose sa_IN.UTF-8 en_US.UTF-8/Compose sd_IN.UTF-8 en_US.UTF-8/Compose sd_IN.UTF-8@devanagari en_US.UTF-8/Compose se_NO.UTF-8 en_US.UTF-8/Compose sh_BA.UTF-8 en_US.UTF-8/Compose sh_YU.UTF-8 en_US.UTF-8/Compose si_LK.UTF-8 en_US.UTF-8/Compose sk_SK.UTF-8 en_US.UTF-8/Compose sl_SI.UTF-8 en_US.UTF-8/Compose sq_AL.UTF-8 en_US.UTF-8/Compose sr_ME.UTF-8 en_US.UTF-8/Compose sr_RS.UTF-8 en_US.UTF-8/Compose sr_YU.UTF-8 en_US.UTF-8/Compose ss_ZA.UTF-8 en_US.UTF-8/Compose st_ZA.UTF-8 en_US.UTF-8/Compose sv_FI.UTF-8 en_US.UTF-8/Compose sv_SE.UTF-8 en_US.UTF-8/Compose ta_IN.UTF-8 en_US.UTF-8/Compose te_IN.UTF-8 en_US.UTF-8/Compose tg_TJ.UTF-8 th_TH.UTF-8/Compose th_TH.UTF-8 en_US.UTF-8/Compose ti_ER.UTF-8 en_US.UTF-8/Compose ti_ET.UTF-8 en_US.UTF-8/Compose tl_PH.UTF-8 en_US.UTF-8/Compose tn_ZA.UTF-8 en_US.UTF-8/Compose tr_TR.UTF-8 en_US.UTF-8/Compose ts_ZA.UTF-8 en_US.UTF-8/Compose tt_RU.UTF-8 en_US.UTF-8/Compose uk_UA.UTF-8 en_US.UTF-8/Compose ur_IN.UTF-8 en_US.UTF-8/Compose ur_PK.UTF-8 en_US.UTF-8/Compose uz_UZ.UTF-8 en_US.UTF-8/Compose ve_ZA.UTF-8 en_US.UTF-8/Compose vi_VN.UTF-8 en_US.UTF-8/Compose wa_BE.UTF-8 en_US.UTF-8/Compose xh_ZA.UTF-8 en_US.UTF-8/Compose yi_US.UTF-8 zh_CN.UTF-8/Compose zh_CN.UTF-8 zh_HK.UTF-8/Compose zh_HK.UTF-8 en_US.UTF-8/Compose zh_SG.UTF-8 zh_TW.UTF-8/Compose zh_TW.UTF-8 en_US.UTF-8/Compose zu_ZA.UTF-8 # # This file contains compose table file names. # The first word is the compose table file name # and the second word is the full locale name. # # iso8859-1/Compose: C iso8859-1/Compose: af_ZA.ISO8859-1 iso8859-6/Compose: ar_AA.ISO8859-6 iso8859-6/Compose: ar_AE.ISO8859-6 iso8859-6/Compose: ar_BH.ISO8859-6 iso8859-6/Compose: ar_DZ.ISO8859-6 iso8859-6/Compose: ar_EG.ISO8859-6 iso8859-6/Compose: ar_IQ.ISO8859-6 iso8859-6/Compose: ar_JO.ISO8859-6 iso8859-6/Compose: ar_KW.ISO8859-6 iso8859-6/Compose: ar_LB.ISO8859-6 iso8859-6/Compose: ar_LY.ISO8859-6 iso8859-6/Compose: ar_MA.ISO8859-6 iso8859-6/Compose: ar_OM.ISO8859-6 iso8859-6/Compose: ar_QA.ISO8859-6 iso8859-6/Compose: ar_SA.ISO8859-6 iso8859-6/Compose: ar_SD.ISO8859-6 iso8859-6/Compose: ar_SY.ISO8859-6 iso8859-6/Compose: ar_TN.ISO8859-6 iso8859-6/Compose: ar_YE.ISO8859-6 iso8859-9e/Compose: az_AZ.ISO8859-9E koi8-c/Compose: az_AZ.KOI8-C microsoft-cp1251/Compose: be_BY.CP1251 iso8859-5/Compose: be_BY.ISO8859-5 iso8859-5/Compose: bg_BG.ISO8859-5 microsoft-cp1251/Compose: bg_BG.CP1251 koi8-r/Compose: bg_BG.KOI8-R iso8859-1/Compose: br_FR.ISO8859-1 iso8859-14/Compose: br_FR.ISO8859-14 iso8859-15/Compose: br_FR.ISO8859-15 iso8859-2/Compose: bs_BA.ISO8859-2 iso8859-1/Compose: ca_AD.ISO8859-1 iso8859-15/Compose: ca_AD.ISO8859-15 iso8859-1/Compose: ca_ES.ISO8859-1 iso8859-15/Compose: ca_ES.ISO8859-15 iso8859-1/Compose: ca_FR.ISO8859-1 iso8859-15/Compose: ca_FR.ISO8859-15 iso8859-1/Compose: ca_IT.ISO8859-1 iso8859-15/Compose: ca_IT.ISO8859-15 iso8859-2/Compose: cs_CZ.ISO8859-2 iso8859-1/Compose: cy_GB.ISO8859-1 iso8859-14/Compose: cy_GB.ISO8859-14 iso8859-15/Compose: cy_GB.ISO8859-15 iso8859-1/Compose: da_DK.ISO8859-1 iso8859-15/Compose: da_DK.ISO8859-15 iso8859-1/Compose: de_AT.ISO8859-1 iso8859-15/Compose: de_AT.ISO8859-15 iso8859-1/Compose: de_BE.ISO8859-1 iso8859-15/Compose: de_BE.ISO8859-15 iso8859-1/Compose: de_CH.ISO8859-1 iso8859-15/Compose: de_CH.ISO8859-15 iso8859-1/Compose: de_DE.ISO8859-1 iso8859-15/Compose: de_DE.ISO8859-15 iso8859-1/Compose: de_LI.ISO8859-1 iso8859-15/Compose: de_LI.ISO8859-15 iso8859-1/Compose: de_LU.ISO8859-1 iso8859-15/Compose: de_LU.ISO8859-15 iso8859-4/Compose: ee_EE.ISO8859-4 iso8859-7/Compose: el_GR.ISO8859-7 iso8859-15/Compose: el_GR.ISO8859-15 iso8859-1/Compose: en_AU.ISO8859-1 iso8859-1/Compose: en_BE.ISO8859-1 iso8859-15/Compose: en_BE.ISO8859-15 iso8859-1/Compose: en_BW.ISO8859-1 iso8859-1/Compose: en_BZ.ISO8859-1 iso8859-1/Compose: en_CA.ISO8859-1 iso8859-1/Compose: en_EN.ISO8859-1 iso8859-1/Compose: en_GB.ISO8859-1 iso8859-15/Compose: en_GB.ISO8859-15 iso8859-1/Compose: en_HK.ISO8859-1 iso8859-1/Compose: en_IE.ISO8859-1 iso8859-15/Compose: en_IE.ISO8859-15 iso8859-15/Compose: en_IN.ISO8859-15 iso8859-1/Compose: en_JM.ISO8859-1 iso8859-1/Compose: en_NZ.ISO8859-1 iso8859-1/Compose: en_PH.ISO8859-1 iso8859-1/Compose: en_SG.ISO8859-1 iso8859-1/Compose: en_TT.ISO8859-1 iso8859-1/Compose: en_UK.ISO8859-1 iso8859-15/Compose: en_UK.ISO8859-15 iso8859-1/Compose: en_US.ISO8859-1 iso8859-15/Compose: en_US.ISO8859-15 iso8859-1/Compose: en_ZA.ISO8859-1 iso8859-15/Compose: en_ZA.ISO8859-15 iso8859-1/Compose: en_ZW.ISO8859-1 iso8859-3/Compose: eo_EO.ISO8859-3 iso8859-3/Compose: eo_XX.ISO8859-3 iso8859-1/Compose: es_AR.ISO8859-1 iso8859-1/Compose: es_BO.ISO8859-1 iso8859-1/Compose: es_CL.ISO8859-1 iso8859-1/Compose: es_CO.ISO8859-1 iso8859-1/Compose: es_CR.ISO8859-1 iso8859-1/Compose: es_DO.ISO8859-1 iso8859-1/Compose: es_EC.ISO8859-1 iso8859-1/Compose: es_ES.ISO8859-1 iso8859-15/Compose: es_ES.ISO8859-15 iso8859-1/Compose: es_GT.ISO8859-1 iso8859-1/Compose: es_HN.ISO8859-1 iso8859-1/Compose: es_MX.ISO8859-1 iso8859-1/Compose: es_NI.ISO8859-1 iso8859-1/Compose: es_PA.ISO8859-1 iso8859-15/Compose: es_PA.ISO8859-15 iso8859-1/Compose: es_PE.ISO8859-1 iso8859-15/Compose: es_PE.ISO8859-15 iso8859-1/Compose: es_PR.ISO8859-1 iso8859-1/Compose: es_PY.ISO8859-1 iso8859-15/Compose: es_PY.ISO8859-15 iso8859-1/Compose: es_SV.ISO8859-1 iso8859-15/Compose: es_SV.ISO8859-15 iso8859-1/Compose: es_US.ISO8859-1 iso8859-1/Compose: es_UY.ISO8859-1 iso8859-15/Compose: es_UY.ISO8859-15 iso8859-1/Compose: es_VE.ISO8859-1 iso8859-15/Compose: es_VE.ISO8859-15 iso8859-1/Compose: et_EE.ISO8859-1 iso8859-4/Compose: et_EE.ISO8859-4 iso8859-13/Compose: et_EE.ISO8859-13 iso8859-15/Compose: et_EE.ISO8859-15 iso8859-1/Compose: eu_ES.ISO8859-1 iso8859-15/Compose: eu_ES.ISO8859-15 isiri-3342/Compose: fa_IR.ISIRI-3342 iso8859-1/Compose: fi_FI.ISO8859-1 iso8859-15/Compose: fi_FI.ISO8859-15 iso8859-1/Compose: fo_FO.ISO8859-1 iso8859-15/Compose: fo_FO.ISO8859-15 iso8859-1/Compose: fr_BE.ISO8859-1 iso8859-15/Compose: fr_BE.ISO8859-15 iso8859-1/Compose: fr_CA.ISO8859-1 iso8859-15/Compose: fr_CA.ISO8859-15 iso8859-1/Compose: fr_CH.ISO8859-1 iso8859-15/Compose: fr_CH.ISO8859-15 iso8859-1/Compose: fr_FR.ISO8859-1 iso8859-15/Compose: fr_FR.ISO8859-15 iso8859-1/Compose: fr_LU.ISO8859-1 iso8859-15/Compose: fr_LU.ISO8859-15 iso8859-1/Compose: ga_IE.ISO8859-1 iso8859-14/Compose: ga_IE.ISO8859-14 iso8859-15/Compose: ga_IE.ISO8859-15 iso8859-1/Compose: gd_GB.ISO8859-1 iso8859-14/Compose: gd_GB.ISO8859-14 iso8859-15/Compose: gd_GB.ISO8859-15 iso8859-1/Compose: gl_ES.ISO8859-1 iso8859-15/Compose: gl_ES.ISO8859-15 iso8859-1/Compose: gv_GB.ISO8859-1 iso8859-14/Compose: gv_GB.ISO8859-14 iso8859-15/Compose: gv_GB.ISO8859-15 iso8859-8/Compose: he_IL.ISO8859-8 microsoft-cp1255/Compose: he_IL.CP1255 iscii-dev/Compose: hi_IN.ISCII-DEV iso8859-2/Compose: hr_HR.ISO8859-2 iso8859-2/Compose: hu_HU.ISO8859-2 armscii-8/Compose: hy_AM.ARMSCII-8 iso8859-1/Compose: id_ID.ISO8859-1 iso8859-15/Compose: id_ID.ISO8859-15 iso8859-1/Compose: is_IS.ISO8859-1 iso8859-15/Compose: is_IS.ISO8859-15 iso8859-1/Compose: it_CH.ISO8859-1 iso8859-15/Compose: it_CH.ISO8859-15 iso8859-1/Compose: it_IT.ISO8859-1 iso8859-15/Compose: it_IT.ISO8859-15 ja/Compose: ja_JP.eucJP ja.SJIS/Compose: ja_JP.SJIS ja.JIS/Compose: ja_JP.JIS7 georgian-academy/Compose: ka_GE.GEORGIAN-ACADEMY georgian-ps/Compose: ka_GE.GEORGIAN-PS iso8859-1/Compose: kl_GL.ISO8859-1 iso8859-15/Compose: kl_GL.ISO8859-15 iso8859-1/Compose: kw_GB.ISO8859-1 iso8859-14/Compose: kw_GB.ISO8859-14 iso8859-15/Compose: kw_GB.ISO8859-15 ko/Compose: ko_KR.eucKR ibm-cp1133/Compose: lo_LA.IBM-CP1133 mulelao-1/Compose: lo_LA.MULELAO-1 iso8859-4/Compose: lt_LT.ISO8859-4 iso8859-13/Compose: lt_LT.ISO8859-13 iso8859-4/Compose: lv_LV.ISO8859-4 iso8859-13/Compose: lv_LV.ISO8859-13 iso8859-13/Compose: mi_NZ.ISO8859-13 iso8859-5/Compose: mk_MK.ISO8859-5 microsoft-cp1251/Compose: mk_MK.CP1251 iso8859-1/Compose: ms_MY.ISO8859-1 iso8859-3/Compose: mt_MT.ISO8859-3 iso8859-1/Compose: nl_BE.ISO8859-1 iso8859-15/Compose: nl_BE.ISO8859-15 iso8859-1/Compose: nl_NL.ISO8859-1 iso8859-15/Compose: nl_NL.ISO8859-15 iso8859-1/Compose: no_NO.ISO8859-1 iso8859-15/Compose: no_NO.ISO8859-15 iso8859-1/Compose: nb_NO.ISO8859-1 iso8859-15/Compose: nb_NO.ISO8859-15 iso8859-1/Compose: nn_NO.ISO8859-1 iso8859-15/Compose: nn_NO.ISO8859-15 iso8859-1/Compose: nr_ZA.ISO8859-1 iso8859-15/Compose: nso_ZA.ISO8859-15 iso8859-1/Compose: ny_NO.ISO8859-1 iso8859-15/Compose: ny_NO.ISO8859-15 iso8859-1/Compose: oc_FR.ISO8859-1 iso8859-15/Compose: oc_FR.ISO8859-15 iso8859-1/Compose: pd_DE.ISO8859-1 iso8859-15/Compose: pd_DE.ISO8859-15 iso8859-1/Compose: pd_US.ISO8859-1 iso8859-15/Compose: pd_US.ISO8859-15 iso8859-1/Compose: ph_PH.ISO8859-1 iso8859-2/Compose: pl_PL.ISO8859-2 iso8859-1/Compose: pp_AN.ISO8859-1 iso8859-1/Compose: pt_BR.ISO8859-1 iso8859-15/Compose: pt_BR.ISO8859-15 iso8859-1/Compose: pt_PT.ISO8859-1 iso8859-15/Compose: pt_PT.ISO8859-15 iso8859-2/Compose: ro_RO.ISO8859-2 koi8-r/Compose: ru_RU.KOI8-R iso8859-5/Compose: ru_RU.ISO8859-5 microsoft-cp1251/Compose: ru_RU.CP1251 microsoft-cp1251/Compose: ru_UA.CP1251 koi8-u/Compose: ru_UA.KOI8-U iso8859-1/Compose: rw_RW.ISO8859-1 iso8859-2/Compose: sh_YU.ISO8859-2 iso8859-2/Compose: sk_SK.ISO8859-2 iso8859-2/Compose: sl_SI.ISO8859-2 iso8859-2/Compose: sq_AL.ISO8859-2 iso8859-2/Compose: sr_YU.ISO8859-2 microsoft-cp1251/Compose: sr_YU.CP1251 iso8859-5/Compose: sr_YU.ISO8859-5 iso8859-1/Compose: ss_ZA.ISO8859-1 iso8859-1/Compose: st_ZA.ISO8859-1 iso8859-1/Compose: sv_FI.ISO8859-1 iso8859-15/Compose: sv_FI.ISO8859-15 iso8859-1/Compose: sv_SE.ISO8859-1 iso8859-15/Compose: sv_SE.ISO8859-15 tscii-0/Compose: ta_IN.TSCII-0 koi8-c/Compose: tg_TJ.KOI8-C iso8859-1/Compose: tl_PH.ISO8859-1 iso8859-11/Compose: th_TH.ISO8859-11 th_TH/Compose: th_TH.TIS620 iso8859-15/Compose: tn_ZA.ISO8859-15 iso8859-9/Compose: tr_TR.ISO8859-9 iso8859-1/Compose: ts_ZA.ISO8859-1 tatar-cyr/Compose: tt_RU.TATAR-CYR microsoft-cp1251/Compose: uk_UA.CP1251 koi8-c/Compose: tt_RU.KOI8-C koi8-u/Compose: uk_UA.KOI8-U iso8859-5/Compose: uk_UA.ISO8859-5 microsoft-cp1256/Compose: ur_PK.CP1256 iso8859-1/Compose: uz_UZ.ISO8859-1 vi_VN.viscii/Compose: vi_VN.VISCII vi_VN.tcvn/Compose: vi_VN.TCVN iso8859-1/Compose: wa_BE.ISO8859-1 iso8859-15/Compose: wa_BE.ISO8859-15 iso8859-1/Compose: xh_ZA.ISO8859-1 microsoft-cp1255/Compose: yi_US.CP1255 zh_CN/Compose: zh_CN.eucCN zh_CN/Compose: zh_CN.gb2312 zh_CN.gbk/Compose: zh_CN.gbk zh_CN.gb18030/Compose: zh_CN.gb18030 zh_HK.big5/Compose: zh_HK.big5 zh_HK.big5hkscs/Compose: zh_HK.big5hkscs zh_TW.big5/Compose: zh_TW.big5 zh_TW/Compose: zh_TW.eucTW iso8859-1/Compose: zu_ZA.ISO8859-1 # # en_US.UTF-8/Compose: C.UTF-8 en_US.UTF-8/Compose: af_ZA.UTF-8 am_ET.UTF-8/Compose: am_ET.UTF-8 en_US.UTF-8/Compose: ar_AA.UTF-8 en_US.UTF-8/Compose: ar_AE.UTF-8 en_US.UTF-8/Compose: ar_BH.UTF-8 en_US.UTF-8/Compose: ar_DZ.UTF-8 en_US.UTF-8/Compose: ar_EG.UTF-8 en_US.UTF-8/Compose: ar_IN.UTF-8 en_US.UTF-8/Compose: ar_IQ.UTF-8 en_US.UTF-8/Compose: ar_JO.UTF-8 en_US.UTF-8/Compose: ar_KW.UTF-8 en_US.UTF-8/Compose: ar_LB.UTF-8 en_US.UTF-8/Compose: ar_LY.UTF-8 en_US.UTF-8/Compose: ar_MA.UTF-8 en_US.UTF-8/Compose: ar_OM.UTF-8 en_US.UTF-8/Compose: ar_QA.UTF-8 en_US.UTF-8/Compose: ar_SA.UTF-8 en_US.UTF-8/Compose: ar_SD.UTF-8 en_US.UTF-8/Compose: ar_SY.UTF-8 en_US.UTF-8/Compose: ar_TN.UTF-8 en_US.UTF-8/Compose: ar_YE.UTF-8 en_US.UTF-8/Compose: ast_ES.UTF-8 en_US.UTF-8/Compose: as_IN.UTF-8 en_US.UTF-8/Compose: az_AZ.UTF-8 en_US.UTF-8/Compose: be_BY.UTF-8 en_US.UTF-8/Compose: bg_BG.UTF-8 en_US.UTF-8/Compose: bn_BD.UTF-8 en_US.UTF-8/Compose: bn_IN.UTF-8 en_US.UTF-8/Compose: bo_IN.UTF-8 en_US.UTF-8/Compose: br_FR.UTF-8 en_US.UTF-8/Compose: bs_BA.UTF-8 en_US.UTF-8/Compose: ca_AD.UTF-8 en_US.UTF-8/Compose: ca_ES.UTF-8 en_US.UTF-8/Compose: ca_FR.UTF-8 en_US.UTF-8/Compose: ca_IT.UTF-8 cs_CZ.UTF-8/Compose: cs_CZ.UTF-8 en_US.UTF-8/Compose: cy_GB.UTF-8 en_US.UTF-8/Compose: da_DK.UTF-8 en_US.UTF-8/Compose: de_AT.UTF-8 en_US.UTF-8/Compose: de_BE.UTF-8 en_US.UTF-8/Compose: de_CH.UTF-8 en_US.UTF-8/Compose: de_DE.UTF-8 en_US.UTF-8/Compose: de_IT.UTF-8 en_US.UTF-8/Compose: de_LI.UTF-8 en_US.UTF-8/Compose: de_LU.UTF-8 el_GR.UTF-8/Compose: el_CY.UTF-8 el_GR.UTF-8/Compose: el_GR.UTF-8 en_US.UTF-8/Compose: en_AU.UTF-8 en_US.UTF-8/Compose: en_BE.UTF-8 en_US.UTF-8/Compose: en_BW.UTF-8 en_US.UTF-8/Compose: en_BZ.UTF-8 en_US.UTF-8/Compose: en_CA.UTF-8 en_US.UTF-8/Compose: en_DK.UTF-8 en_US.UTF-8/Compose: en_EN.UTF-8 en_US.UTF-8/Compose: en_GB.UTF-8 en_US.UTF-8/Compose: en_HK.UTF-8 en_US.UTF-8/Compose: en_IE.UTF-8 en_US.UTF-8/Compose: en_IN.UTF-8 en_US.UTF-8/Compose: en_JM.UTF-8 en_US.UTF-8/Compose: en_MT.UTF-8 en_US.UTF-8/Compose: en_NZ.UTF-8 en_US.UTF-8/Compose: en_PH.UTF-8 en_US.UTF-8/Compose: en_SG.UTF-8 en_US.UTF-8/Compose: en_TT.UTF-8 en_US.UTF-8/Compose: en_UK.UTF-8 en_US.UTF-8/Compose: en_US.UTF-8 en_US.UTF-8/Compose: en_ZA.UTF-8 en_US.UTF-8/Compose: en_ZW.UTF-8 en_US.UTF-8/Compose: eo_EO.UTF-8 en_US.UTF-8/Compose: eo_XX.UTF-8 en_US.UTF-8/Compose: es_AR.UTF-8 en_US.UTF-8/Compose: es_BO.UTF-8 en_US.UTF-8/Compose: es_CL.UTF-8 en_US.UTF-8/Compose: es_CO.UTF-8 en_US.UTF-8/Compose: es_CR.UTF-8 en_US.UTF-8/Compose: es_DO.UTF-8 en_US.UTF-8/Compose: es_EC.UTF-8 en_US.UTF-8/Compose: es_ES.UTF-8 en_US.UTF-8/Compose: es_GT.UTF-8 en_US.UTF-8/Compose: es_HN.UTF-8 en_US.UTF-8/Compose: es_MX.UTF-8 en_US.UTF-8/Compose: es_NI.UTF-8 en_US.UTF-8/Compose: es_PA.UTF-8 en_US.UTF-8/Compose: es_PE.UTF-8 en_US.UTF-8/Compose: es_PR.UTF-8 en_US.UTF-8/Compose: es_PY.UTF-8 en_US.UTF-8/Compose: es_SV.UTF-8 en_US.UTF-8/Compose: es_US.UTF-8 en_US.UTF-8/Compose: es_UY.UTF-8 en_US.UTF-8/Compose: es_VE.UTF-8 en_US.UTF-8/Compose: et_EE.UTF-8 en_US.UTF-8/Compose: eu_ES.UTF-8 en_US.UTF-8/Compose: fa_IR.UTF-8 fi_FI.UTF-8/Compose: fi_FI.UTF-8 en_US.UTF-8/Compose: fo_FO.UTF-8 en_US.UTF-8/Compose: fr_BE.UTF-8 en_US.UTF-8/Compose: fr_CA.UTF-8 en_US.UTF-8/Compose: fr_CH.UTF-8 en_US.UTF-8/Compose: fr_FR.UTF-8 en_US.UTF-8/Compose: fr_LU.UTF-8 en_US.UTF-8/Compose: ga_IE.UTF-8 en_US.UTF-8/Compose: gd_GB.UTF-8 en_US.UTF-8/Compose: gl_ES.UTF-8 en_US.UTF-8/Compose: gu_IN.UTF-8 en_US.UTF-8/Compose: gv_GB.UTF-8 en_US.UTF-8/Compose: he_IL.UTF-8 en_US.UTF-8/Compose: hi_IN.UTF-8 en_US.UTF-8/Compose: hne_IN.UTF-8 en_US.UTF-8/Compose: hr_HR.UTF-8 en_US.UTF-8/Compose: hu_HU.UTF-8 en_US.UTF-8/Compose: hy_AM.UTF-8 en_US.UTF-8/Compose: id_ID.UTF-8 en_US.UTF-8/Compose: is_IS.UTF-8 en_US.UTF-8/Compose: it_CH.UTF-8 en_US.UTF-8/Compose: it_IT.UTF-8 en_US.UTF-8/Compose: iu_CA.UTF-8 ja_JP.UTF-8/Compose: ja_JP.UTF-8 en_US.UTF-8/Compose: ka_GE.UTF-8 en_US.UTF-8/Compose: kk_KZ.UTF-8 en_US.UTF-8/Compose: kl_GL.UTF-8 km_KH.UTF-8/Compose: km_KH.UTF-8 en_US.UTF-8/Compose: kn_IN.UTF-8 ko_KR.UTF-8/Compose: ko_KR.UTF-8 en_US.UTF-8/Compose: ks_IN.UTF-8 en_US.UTF-8/Compose: ks_IN.UTF-8@devanagari en_US.UTF-8/Compose: ku_TR.UTF-8 en_US.UTF-8/Compose: kw_GB.UTF-8 en_US.UTF-8/Compose: ky_KG.UTF-8 en_US.UTF-8/Compose: lo_LA.UTF-8 en_US.UTF-8/Compose: lt_LT.UTF-8 en_US.UTF-8/Compose: lv_LV.UTF-8 en_US.UTF-8/Compose: mai_IN.UTF-8 en_US.UTF-8/Compose: mi_NZ.UTF-8 en_US.UTF-8/Compose: mk_MK.UTF-8 en_US.UTF-8/Compose: ml_IN.UTF-8 en_US.UTF-8/Compose: mr_IN.UTF-8 en_US.UTF-8/Compose: ms_MY.UTF-8 en_US.UTF-8/Compose: mt_MT.UTF-8 en_US.UTF-8/Compose: ne_NP.UTF-8 en_US.UTF-8/Compose: nl_BE.UTF-8 en_US.UTF-8/Compose: nl_NL.UTF-8 en_US.UTF-8/Compose: nn_NO.UTF-8 en_US.UTF-8/Compose: no_NO.UTF-8 en_US.UTF-8/Compose: nb_NO.UTF-8 en_US.UTF-8/Compose: nr_ZA.UTF-8 en_US.UTF-8/Compose: nso_ZA.UTF-8 en_US.UTF-8/Compose: ny_NO.UTF-8 en_US.UTF-8/Compose: oc_FR.UTF-8 en_US.UTF-8/Compose: or_IN.UTF-8 en_US.UTF-8/Compose: pa_IN.UTF-8 en_US.UTF-8/Compose: pa_PK.UTF-8 en_US.UTF-8/Compose: pd_DE.UTF-8 en_US.UTF-8/Compose: pd_US.UTF-8 en_US.UTF-8/Compose: ph_PH.UTF-8 en_US.UTF-8/Compose: pl_PL.UTF-8 en_US.UTF-8/Compose: pp_AN.UTF-8 pt_BR.UTF-8/Compose: pt_BR.UTF-8 pt_PT.UTF-8/Compose: pt_PT.UTF-8 en_US.UTF-8/Compose: ro_RO.UTF-8 ru_RU.UTF-8/Compose: ru_RU.UTF-8 en_US.UTF-8/Compose: ru_UA.UTF-8 en_US.UTF-8/Compose: rw_RW.UTF-8 en_US.UTF-8/Compose: sa_IN.UTF-8 en_US.UTF-8/Compose: sd_IN.UTF-8 en_US.UTF-8/Compose: sd_IN.UTF-8@devanagari en_US.UTF-8/Compose: se_NO.UTF-8 en_US.UTF-8/Compose: sh_BA.UTF-8 en_US.UTF-8/Compose: sh_YU.UTF-8 en_US.UTF-8/Compose: si_LK.UTF-8 en_US.UTF-8/Compose: sk_SK.UTF-8 en_US.UTF-8/Compose: sl_SI.UTF-8 en_US.UTF-8/Compose: sq_AL.UTF-8 en_US.UTF-8/Compose: sr_ME.UTF-8 en_US.UTF-8/Compose: sr_RS.UTF-8 en_US.UTF-8/Compose: sr_YU.UTF-8 en_US.UTF-8/Compose: ss_ZA.UTF-8 en_US.UTF-8/Compose: st_ZA.UTF-8 en_US.UTF-8/Compose: sv_FI.UTF-8 en_US.UTF-8/Compose: sv_SE.UTF-8 en_US.UTF-8/Compose: ta_IN.UTF-8 en_US.UTF-8/Compose: te_IN.UTF-8 en_US.UTF-8/Compose: tg_TJ.UTF-8 th_TH.UTF-8/Compose: th_TH.UTF-8 en_US.UTF-8/Compose: ti_ER.UTF-8 en_US.UTF-8/Compose: ti_ET.UTF-8 en_US.UTF-8/Compose: tl_PH.UTF-8 en_US.UTF-8/Compose: tn_ZA.UTF-8 en_US.UTF-8/Compose: tr_TR.UTF-8 en_US.UTF-8/Compose: ts_ZA.UTF-8 en_US.UTF-8/Compose: tt_RU.UTF-8 en_US.UTF-8/Compose: uk_UA.UTF-8 en_US.UTF-8/Compose: ur_IN.UTF-8 en_US.UTF-8/Compose: ur_PK.UTF-8 en_US.UTF-8/Compose: uz_UZ.UTF-8 en_US.UTF-8/Compose: ve_ZA.UTF-8 en_US.UTF-8/Compose: vi_VN.UTF-8 en_US.UTF-8/Compose: wa_BE.UTF-8 en_US.UTF-8/Compose: xh_ZA.UTF-8 en_US.UTF-8/Compose: yi_US.UTF-8 zh_CN.UTF-8/Compose: zh_CN.UTF-8 zh_HK.UTF-8/Compose: zh_HK.UTF-8 en_US.UTF-8/Compose: zh_SG.UTF-8 zh_TW.UTF-8/Compose: zh_TW.UTF-8 en_US.UTF-8/Compose: zu_ZA.UTF-8 xkbcommon-libxkbcommon-54ee7ac/test/data/locale/en_US.UTF-8/000077500000000000000000000000001510033435100236255ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/locale/en_US.UTF-8/Compose000066400000000000000000020740431510033435100251670ustar00rootroot00000000000000 # UTF-8 (Unicode) compose sequence # David.Monniaux@ens.fr # # Part 1 - Manual definitions # Spacing versions of dead accents : "~" asciitilde # TILDE : "~" asciitilde # TILDE : "'" apostrophe # APOSTROPHE : "´" acute # ACUTE ACCENT : "´" acute # ACUTE ACCENT : "`" grave # GRAVE ACCENT : "`" grave # GRAVE ACCENT : "^" asciicircum # CIRCUMFLEX ACCENT : "^" asciicircum # CIRCUMFLEX ACCENT : "°" degree # DEGREE SIGN : "°" degree # DEGREE SIGN : "¯" macron # MACRON : "¯" macron # MACRON : "¯" macron # MACRON : "¯" macron # MACRON : "¯" macron # MACRON : "¯" macron # MACRON : "˘" breve # BREVE : "˘" breve # BREVE : "˘" breve # BREVE : "˘" breve # BREVE : "˙" abovedot # DOT ABOVE : "˙" abovedot # DOT ABOVE : "¨" diaeresis # DIAERESIS : "¨" diaeresis # DIAERESIS : "\"" quotedbl # REVERSE SOLIDUS : "˝" U2dd # DOUBLE ACUTE ACCENT : "˝" U2dd # DOUBLE ACUTE ACCENT : "ˇ" caron # CARON : "ˇ" caron # CARON : "ˇ" caron # CARON : "ˇ" caron # CARON : "¸" cedilla # CEDILLA : "¸" cedilla # CEDILLA : "˛" ogonek # OGONEK : "˛" ogonek # OGONEK : "ͺ" U37a # GREEK YPOGEGRAMMENI : "ͺ" U37a # GREEK YPOGEGRAMMENI : "­" U00ad # SOFT HYPHEN # ASCII characters that may be difficult to access # on some keyboards. : "#" numbersign # NUMBER SIGN : "'" apostrophe # APOSTROPHE : "'" apostrophe # APOSTROPHE : "@" at # COMMERCIAL AT : "[" bracketleft # LEFT SQUARE BRACKET : "\\" backslash # REVERSE SOLIDUS : "\\" backslash # REVERSE SOLIDUS : "\\" backslash # REVERSE SOLIDUS : "]" bracketright # RIGHT SQUARE BRACKET : "^" asciicircum # CIRCUMFLEX ACCENT : "^" asciicircum # CIRCUMFLEX ACCENT : "^" asciicircum # CIRCUMFLEX ACCENT : "^" asciicircum # CIRCUMFLEX ACCENT : "`" grave # GRAVE ACCENT : "`" grave # GRAVE ACCENT : "¸" cedilla # CEDILLA : "¸" cedilla # CEDILLA : "¸" cedilla # CEDILLA : "{" braceleft # LEFT CURLY BRACKET : "{" braceleft # LEFT CURLY BRACKET : "|" bar # VERTICAL LINE : "|" bar # VERTICAL LINE : "|" bar # VERTICAL LINE : "|" bar # VERTICAL LINE : "|" bar # VERTICAL LINE : "|" bar # VERTICAL LINE : "}" braceright # RIGHT CURLY BRACKET : "}" braceright # RIGHT CURLY BRACKET : "~" asciitilde # TILDE : "~" asciitilde # TILDE : "~" asciitilde # TILDE : "~" asciitilde # TILDE # Spaces : " " nobreakspace # NO-BREAK SPACE : " " U2008 # PUNCTUATION SPACE : "©" copyright # COPYRIGHT SIGN : "©" copyright # COPYRIGHT SIGN : "©" copyright # COPYRIGHT SIGN : "©" copyright # COPYRIGHT SIGN : "©" copyright # COPYRIGHT SIGN : "©" copyright # COPYRIGHT SIGN : "®" registered # REGISTERED SIGN : "®" registered # REGISTERED SIGN : "®" registered # REGISTERED SIGN : "®" registered # REGISTERED SIGN : "®" registered # REGISTERED SIGN : "›" U203a # SINGLE RIGHT-POINTING ANGLE QUOTATION MARK : "‹" U2039 # SINGLE LEFT-POINTING ANGLE QUOTATION MARK : "…" ellipsis # HORIZONTAL ELLIPSIS : "·" periodcentered # MIDDLE DOT : "·" periodcentered # MIDDLE DOT : "·" periodcentered # MIDDLE DOT : "•" enfilledcircbullet # BULLET : "¦" brokenbar # BROKEN BAR : "¡" exclamdown # INVERTED EXCLAMATION MARK

: "¶" paragraph # PILCROW SIGN

: "¶" paragraph # PILCROW SIGN : "±" plusminus # PLUS-MINUS SIGN : "±" plusminus # PLUS-MINUS SIGN : "¿" questiondown # INVERTED QUESTION MARK : "đ" dstroke # LATIN SMALL LETTER D WITH STROKE : "Đ" Dstroke # LATIN CAPITAL LETTER D WITH STROKE : "ß" ssharp # LATIN SMALL LETTER SHARP S : "ẞ" U1e9e # LATIN CAPITAL LETTER SHARP S : "œ" oe # LATIN SMALL LIGATURE OE : "Œ" OE # LATIN CAPITAL LIGATURE OE : "æ" ae # LATIN SMALL LETTER AE : "Æ" AE # LATIN CAPITAL LETTER AE : "ff" Ufb00 # LATIN SMALL LIGATURE FF : "fi" Ufb01 # LATIN SMALL LIGATURE FI : "fl" Ufb02 # LATIN SMALL LIGATURE FL : "ffi" Ufb03 # LATIN SMALL LIGATURE FFI : "ffl" Ufb04 # LATIN SMALL LIGATURE FFL : "IJ" U0132 # LATIN CAPITAL LIGATURE IJ : "IJ" U0132 # LATIN CAPITAL LIGATURE IJ : "ij" U0133 # LATIN SMALL LIGATURE IJ : "°" degree # DEGREE SIGN <0> : "°" degree # DEGREE SIGN <0> : "°" degree # DEGREE SIGN # Quotation marks : "«" guillemotleft # LEFT-POINTING DOUBLE ANGLE QUOTATION MARK : "»" guillemetright # RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK : "‘" U2018 # LEFT SINGLE QUOTATION MARK : "‘" U2018 # LEFT SINGLE QUOTATION MARK : "’" U2019 # RIGHT SINGLE QUOTATION MARK : "’" U2019 # RIGHT SINGLE QUOTATION MARK : "‚" U201a # SINGLE LOW-9 QUOTATION MARK : "‚" U201a # SINGLE LOW-9 QUOTATION MARK : "“" U201c # LEFT DOUBLE QUOTATION MARK : "“" U201c # LEFT DOUBLE QUOTATION MARK : "”" U201d # RIGHT DOUBLE QUOTATION MARK : "”" U201d # RIGHT DOUBLE QUOTATION MARK : "„" U201e # DOUBLE LOW-9 QUOTATION MARK : "„" U201e # DOUBLE LOW-9 QUOTATION MARK # Per xxx : "‰" U2030 # PER MILLE SIGN # Currencies : "₠" U20a0 # EURO-CURRENCY SIGN : "₡" U20a1 # COLON SIGN : "₡" U20a1 # COLON SIGN : "₢" U20a2 # CRUZEIRO SIGN : "₣" U20a3 # FRENCH FRANC SIGN : "₤" U20a4 # LIRA SIGN : "₤" U20a4 # LIRA SIGN : "₥" U20a5 # MILL SIGN : "₥" U20a5 # MILL SIGN : "₦" U20a6 # NAIRA SIGN : "₦" U20a6 # NAIRA SIGN

: "₧" U20a7 # PESETA SIGN : "₨" U20a8 # RUPEE SIGN : "₩" U20a9 # WON SIGN : "₩" U20a9 # WON SIGN # "₪" U20aa NEW SHEQEL SIGN : "₫" U20ab # DONG SIGN : "₫" U20ab # DONG SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN : "€" EuroSign # EURO SIGN # "₭" U20ad KIP SIGN # "₮" U20ae TUGRIK SIGN # "₯" U20af DRACHMA SIGN # "₰" U20b0 GERMAN PENNY SIGN # "₱" U20b1 PESO SIGN # "₲" U20b2 GUARANI SIGN # "₳" U20b3 AUSTRAL SIGN # "₴" U20b4 HRYVNIA SIGN # "₵" U20b5 CEDI SIGN : "¢" cent # CENT SIGN : "¢" cent # CENT SIGN : "¢" cent # CENT SIGN : "¢" cent # CENT SIGN : "¢" cent # CENT SIGN : "¢" cent # CENT SIGN : "£" sterling # POUND SIGN : "£" sterling # POUND SIGN : "£" sterling # POUND SIGN : "£" sterling # POUND SIGN : "¥" yen # YEN SIGN : "¥" yen # YEN SIGN : "¥" yen # YEN SIGN : "¥" yen # YEN SIGN : "¥" yen # YEN SIGN : "¥" yen # YEN SIGN : "¥" yen # YEN SIGN : "¥" yen # YEN SIGN # Long S : "ſ" U017f # LATIN SMALL LETTER LONG S : "ſ" U017f # LATIN SMALL LETTER LONG S : "ẛ" U1e9b # LATIN SMALL LETTER LONG S WITH DOT ABOVE : "ẛ" U1e9b # LATIN SMALL LETTER LONG S WITH DOT ABOVE # Dashes : "–" U2013 # EN DASH : "—" U2014 # EM DASH # Musical alterations : "♩" U2669 # QUARTER NOTE : "♪" U266a # EIGHTH NOTE : "♫" U266b # BEAMED EIGHTH NOTES : "♬" U266c # BEAMED SIXTEENTH NOTES : "♭" U266d # MUSIC FLAT SIGN : "♮" U266e # MUSIC NATURAL SIGN : "♯" U266f # MUSIC SHARP SIGN # Other symbols : "§" section # SECTION SIGN : "§" section # SECTION SIGN : "§" section # SECTION SIGN : "§" section # SECTION SIGN : "§" section # SECTION SIGN : "§" section # SECTION SIGN : "§" section # SECTION SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN

: "¶" paragraph # PILCROW SIGN : "№" numerosign # NUMERO SIGN : "№" numerosign # NUMERO SIGN : "№" numerosign # NUMERO SIGN : "№" numerosign # NUMERO SIGN : "⸘" U2E18 # INVERTED INTERROBANG : "‽" U203D # INTERROBANG

: "☭" U262D # HAMMER AND SICKLE : "Ⓐ" U24B6 # CIRCLED LATIN CAPITAL LETTER A <3> : "♥" U2665 # BLACK HEART SUIT : "☺" U263A # WHITE SMILING FACE : "☹" U2639 # WHITE FROWNING FACE # Part 2 # Compose map for Korean Hangul(Choseongul) Conjoining Jamos automatically # generated from UnicodeData-2.0.14.txt at # ftp://ftp.unicode.org/Public/2.0-Update/UnicodeData-2.0.14.txt # by Jungshik Shin 2002-10-17 # There are some conflicts among sequences, but I left them alone. # # group 1: cluster jamos made of three basic jamos : "ᄁ" U1101 # HANGUL CHOSEONG SSANGKIYEOK : "ᄄ" U1104 # HANGUL CHOSEONG SSANGTIKEUT : "ᄈ" U1108 # HANGUL CHOSEONG SSANGPIEUP : "ᄊ" U110a # HANGUL CHOSEONG SSANGSIOS : "ᄍ" U110d # HANGUL CHOSEONG SSANGCIEUC : "ᄓ" U1113 # HANGUL CHOSEONG NIEUN-KIYEOK : "ᄔ" U1114 # HANGUL CHOSEONG SSANGNIEUN : "ᄕ" U1115 # HANGUL CHOSEONG NIEUN-TIKEUT : "ᄖ" U1116 # HANGUL CHOSEONG NIEUN-PIEUP : "ᄗ" U1117 # HANGUL CHOSEONG TIKEUT-KIYEOK : "ᄘ" U1118 # HANGUL CHOSEONG RIEUL-NIEUN : "ᄙ" U1119 # HANGUL CHOSEONG SSANGRIEUL : "ᄚ" U111a # HANGUL CHOSEONG RIEUL-HIEUH : "ᄛ" U111b # HANGUL CHOSEONG KAPYEOUNRIEUL : "ᄜ" U111c # HANGUL CHOSEONG MIEUM-PIEUP : "ᄝ" U111d # HANGUL CHOSEONG KAPYEOUNMIEUM : "ᄞ" U111e # HANGUL CHOSEONG PIEUP-KIYEOK : "ᄟ" U111f # HANGUL CHOSEONG PIEUP-NIEUN : "ᄠ" U1120 # HANGUL CHOSEONG PIEUP-TIKEUT : "ᄡ" U1121 # HANGUL CHOSEONG PIEUP-SIOS : "ᄧ" U1127 # HANGUL CHOSEONG PIEUP-CIEUC : "ᄨ" U1128 # HANGUL CHOSEONG PIEUP-CHIEUCH : "ᄩ" U1129 # HANGUL CHOSEONG PIEUP-THIEUTH : "ᄪ" U112a # HANGUL CHOSEONG PIEUP-PHIEUPH : "ᄫ" U112b # HANGUL CHOSEONG KAPYEOUNPIEUP : "ᄭ" U112d # HANGUL CHOSEONG SIOS-KIYEOK : "ᄮ" U112e # HANGUL CHOSEONG SIOS-NIEUN : "ᄯ" U112f # HANGUL CHOSEONG SIOS-TIKEUT : "ᄰ" U1130 # HANGUL CHOSEONG SIOS-RIEUL : "ᄱ" U1131 # HANGUL CHOSEONG SIOS-MIEUM : "ᄲ" U1132 # HANGUL CHOSEONG SIOS-PIEUP : "ᄵ" U1135 # HANGUL CHOSEONG SIOS-IEUNG : "ᄶ" U1136 # HANGUL CHOSEONG SIOS-CIEUC : "ᄷ" U1137 # HANGUL CHOSEONG SIOS-CHIEUCH : "ᄸ" U1138 # HANGUL CHOSEONG SIOS-KHIEUKH : "ᄹ" U1139 # HANGUL CHOSEONG SIOS-THIEUTH : "ᄺ" U113a # HANGUL CHOSEONG SIOS-PHIEUPH : "ᄻ" U113b # HANGUL CHOSEONG SIOS-HIEUH : "ᄽ" U113d # HANGUL CHOSEONG CHITUEUMSSANGSIOS : "ᄿ" U113f # HANGUL CHOSEONG CEONGCHIEUMSSANGSIOS : "ᅁ" U1141 # HANGUL CHOSEONG IEUNG-KIYEOK : "ᅂ" U1142 # HANGUL CHOSEONG IEUNG-TIKEUT : "ᅃ" U1143 # HANGUL CHOSEONG IEUNG-MIEUM : "ᅄ" U1144 # HANGUL CHOSEONG IEUNG-PIEUP : "ᅅ" U1145 # HANGUL CHOSEONG IEUNG-SIOS : "ᅆ" U1146 # HANGUL CHOSEONG IEUNG-PANSIOS : "ᅇ" U1147 # HANGUL CHOSEONG SSANGIEUNG : "ᅈ" U1148 # HANGUL CHOSEONG IEUNG-CIEUC : "ᅉ" U1149 # HANGUL CHOSEONG IEUNG-CHIEUCH : "ᅊ" U114a # HANGUL CHOSEONG IEUNG-THIEUTH : "ᅋ" U114b # HANGUL CHOSEONG IEUNG-PHIEUPH : "ᅍ" U114d # HANGUL CHOSEONG CIEUC-IEUNG : "ᅏ" U114f # HANGUL CHOSEONG CHITUEUMSSANGCIEUC : "ᅑ" U1151 # HANGUL CHOSEONG CEONGCHIEUMSSANGCIEUC : "ᅒ" U1152 # HANGUL CHOSEONG CHIEUCH-KHIEUKH : "ᅓ" U1153 # HANGUL CHOSEONG CHIEUCH-HIEUH : "ᅖ" U1156 # HANGUL CHOSEONG PHIEUPH-PIEUP : "ᅗ" U1157 # HANGUL CHOSEONG KAPYEOUNPHIEUPH : "ᅘ" U1158 # HANGUL CHOSEONG SSANGHIEUH : "ᅢ" U1162 # HANGUL JUNGSEONG AE : "ᅤ" U1164 # HANGUL JUNGSEONG YAE : "ᅦ" U1166 # HANGUL JUNGSEONG E : "ᅨ" U1168 # HANGUL JUNGSEONG YE : "ᅪ" U116a # HANGUL JUNGSEONG WA : "ᅬ" U116c # HANGUL JUNGSEONG OE : "ᅯ" U116f # HANGUL JUNGSEONG WEO : "ᅱ" U1171 # HANGUL JUNGSEONG WI : "ᅴ" U1174 # HANGUL JUNGSEONG YI : "ᅶ" U1176 # HANGUL JUNGSEONG A-O : "ᅷ" U1177 # HANGUL JUNGSEONG A-U : "ᅸ" U1178 # HANGUL JUNGSEONG YA-O : "ᅹ" U1179 # HANGUL JUNGSEONG YA-YO : "ᅺ" U117a # HANGUL JUNGSEONG EO-O : "ᅻ" U117b # HANGUL JUNGSEONG EO-U : "ᅼ" U117c # HANGUL JUNGSEONG EO-EU : "ᅽ" U117d # HANGUL JUNGSEONG YEO-O : "ᅾ" U117e # HANGUL JUNGSEONG YEO-U : "ᅿ" U117f # HANGUL JUNGSEONG O-EO : "ᆀ" U1180 # HANGUL JUNGSEONG O-E : "ᆁ" U1181 # HANGUL JUNGSEONG O-YE : "ᆂ" U1182 # HANGUL JUNGSEONG O-O : "ᆃ" U1183 # HANGUL JUNGSEONG O-U : "ᆄ" U1184 # HANGUL JUNGSEONG YO-YA : "ᆅ" U1185 # HANGUL JUNGSEONG YO-YAE : "ᆆ" U1186 # HANGUL JUNGSEONG YO-YEO : "ᆇ" U1187 # HANGUL JUNGSEONG YO-O : "ᆈ" U1188 # HANGUL JUNGSEONG YO-I : "ᆉ" U1189 # HANGUL JUNGSEONG U-A : "ᆊ" U118a # HANGUL JUNGSEONG U-AE : "ᆌ" U118c # HANGUL JUNGSEONG U-YE : "ᆍ" U118d # HANGUL JUNGSEONG U-U : "ᆎ" U118e # HANGUL JUNGSEONG YU-A : "ᆏ" U118f # HANGUL JUNGSEONG YU-EO : "ᆐ" U1190 # HANGUL JUNGSEONG YU-E : "ᆑ" U1191 # HANGUL JUNGSEONG YU-YEO : "ᆒ" U1192 # HANGUL JUNGSEONG YU-YE : "ᆓ" U1193 # HANGUL JUNGSEONG YU-U : "ᆔ" U1194 # HANGUL JUNGSEONG YU-I : "ᆕ" U1195 # HANGUL JUNGSEONG EU-U : "ᆖ" U1196 # HANGUL JUNGSEONG EU-EU : "ᆗ" U1197 # HANGUL JUNGSEONG YI-U : "ᆘ" U1198 # HANGUL JUNGSEONG I-A : "ᆙ" U1199 # HANGUL JUNGSEONG I-YA : "ᆚ" U119a # HANGUL JUNGSEONG I-O : "ᆛ" U119b # HANGUL JUNGSEONG I-U : "ᆜ" U119c # HANGUL JUNGSEONG I-EU : "ᆝ" U119d # HANGUL JUNGSEONG I-ARAEA : "ᆟ" U119f # HANGUL JUNGSEONG ARAEA-EO : "ᆠ" U11a0 # HANGUL JUNGSEONG ARAEA-U : "ᆡ" U11a1 # HANGUL JUNGSEONG ARAEA-I : "ᆢ" U11a2 # HANGUL JUNGSEONG SSANGARAEA : "ᆩ" U11a9 # HANGUL JONGSEONG SSANGKIYEOK : "ᆪ" U11aa # HANGUL JONGSEONG KIYEOK-SIOS : "ᆬ" U11ac # HANGUL JONGSEONG NIEUN-CIEUC : "ᆭ" U11ad # HANGUL JONGSEONG NIEUN-HIEUH : "ᆰ" U11b0 # HANGUL JONGSEONG RIEUL-KIYEOK : "ᆱ" U11b1 # HANGUL JONGSEONG RIEUL-MIEUM : "ᆲ" U11b2 # HANGUL JONGSEONG RIEUL-PIEUP : "ᆳ" U11b3 # HANGUL JONGSEONG RIEUL-SIOS : "ᆴ" U11b4 # HANGUL JONGSEONG RIEUL-THIEUTH : "ᆵ" U11b5 # HANGUL JONGSEONG RIEUL-PHIEUPH : "ᆶ" U11b6 # HANGUL JONGSEONG RIEUL-HIEUH : "ᆹ" U11b9 # HANGUL JONGSEONG PIEUP-SIOS : "ᆻ" U11bb # HANGUL JONGSEONG SSANGSIOS : "ᇃ" U11c3 # HANGUL JONGSEONG KIYEOK-RIEUL : "ᇅ" U11c5 # HANGUL JONGSEONG NIEUN-KIYEOK : "ᇆ" U11c6 # HANGUL JONGSEONG NIEUN-TIKEUT : "ᇇ" U11c7 # HANGUL JONGSEONG NIEUN-SIOS : "ᇈ" U11c8 # HANGUL JONGSEONG NIEUN-PANSIOS : "ᇉ" U11c9 # HANGUL JONGSEONG NIEUN-THIEUTH : "ᇊ" U11ca # HANGUL JONGSEONG TIKEUT-KIYEOK : "ᇋ" U11cb # HANGUL JONGSEONG TIKEUT-RIEUL : "ᇍ" U11cd # HANGUL JONGSEONG RIEUL-NIEUN : "ᇎ" U11ce # HANGUL JONGSEONG RIEUL-TIKEUT : "ᇐ" U11d0 # HANGUL JONGSEONG SSANGRIEUL : "ᇗ" U11d7 # HANGUL JONGSEONG RIEUL-PANSIOS : "ᇘ" U11d8 # HANGUL JONGSEONG RIEUL-KHIEUKH : "ᇙ" U11d9 # HANGUL JONGSEONG RIEUL-YEORINHIEUH : "ᇚ" U11da # HANGUL JONGSEONG MIEUM-KIYEOK : "ᇛ" U11db # HANGUL JONGSEONG MIEUM-RIEUL : "ᇜ" U11dc # HANGUL JONGSEONG MIEUM-PIEUP : "ᇝ" U11dd # HANGUL JONGSEONG MIEUM-SIOS : "ᇟ" U11df # HANGUL JONGSEONG MIEUM-PANSIOS : "ᇠ" U11e0 # HANGUL JONGSEONG MIEUM-CHIEUCH : "ᇡ" U11e1 # HANGUL JONGSEONG MIEUM-HIEUH : "ᇢ" U11e2 # HANGUL JONGSEONG KAPYEOUNMIEUM : "ᇣ" U11e3 # HANGUL JONGSEONG PIEUP-RIEUL : "ᇤ" U11e4 # HANGUL JONGSEONG PIEUP-PHIEUPH : "ᇥ" U11e5 # HANGUL JONGSEONG PIEUP-HIEUH : "ᇦ" U11e6 # HANGUL JONGSEONG KAPYEOUNPIEUP : "ᇧ" U11e7 # HANGUL JONGSEONG SIOS-KIYEOK : "ᇨ" U11e8 # HANGUL JONGSEONG SIOS-TIKEUT : "ᇩ" U11e9 # HANGUL JONGSEONG SIOS-RIEUL : "ᇪ" U11ea # HANGUL JONGSEONG SIOS-PIEUP : "ᇬ" U11ec # HANGUL JONGSEONG IEUNG-KIYEOK : "ᇮ" U11ee # HANGUL JONGSEONG SSANGIEUNG : "ᇯ" U11ef # HANGUL JONGSEONG IEUNG-KHIEUKH : "ᇱ" U11f1 # HANGUL JONGSEONG YESIEUNG-SIOS : "ᇲ" U11f2 # HANGUL JONGSEONG YESIEUNG-PANSIOS : "ᇳ" U11f3 # HANGUL JONGSEONG PHIEUPH-PIEUP : "ᇴ" U11f4 # HANGUL JONGSEONG KAPYEOUNPHIEUPH : "ᇵ" U11f5 # HANGUL JONGSEONG HIEUH-NIEUN : "ᇶ" U11f6 # HANGUL JONGSEONG HIEUH-RIEUL : "ᇷ" U11f7 # HANGUL JONGSEONG HIEUH-MIEUM : "ᇸ" U11f8 # HANGUL JONGSEONG HIEUH-PIEUP : "ᄢ" U1122 # HANGUL CHOSEONG PIEUP-SIOS-KIYEOK : "ᄣ" U1123 # HANGUL CHOSEONG PIEUP-SIOS-TIKEUT : "ᄤ" U1124 # HANGUL CHOSEONG PIEUP-SIOS-PIEUP : "ᄥ" U1125 # HANGUL CHOSEONG PIEUP-SSANGSIOS : "ᄦ" U1126 # HANGUL CHOSEONG PIEUP-SIOS-CIEUC : "ᄬ" U112c # HANGUL CHOSEONG KAPYEOUNSSANGPIEUP : "ᄳ" U1133 # HANGUL CHOSEONG SIOS-PIEUP-KIYEOK : "ᄴ" U1134 # HANGUL CHOSEONG SIOS-SSANGSIOS : "ᅫ" U116b # HANGUL JUNGSEONG WAE : "ᅰ" U1170 # HANGUL JUNGSEONG WE : "ᆋ" U118b # HANGUL JUNGSEONG U-EO-EU : "ᇄ" U11c4 # HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK : "ᇌ" U11cc # HANGUL JONGSEONG RIEUL-KIYEOK-SIOS : "ᇏ" U11cf # HANGUL JONGSEONG RIEUL-TIKEUT-HIEUH : "ᇑ" U11d1 # HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK : "ᇒ" U11d2 # HANGUL JONGSEONG RIEUL-MIEUM-SIOS : "ᇓ" U11d3 # HANGUL JONGSEONG RIEUL-PIEUP-SIOS : "ᇔ" U11d4 # HANGUL JONGSEONG RIEUL-PIEUP-HIEUH : "ᇕ" U11d5 # HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP : "ᇖ" U11d6 # HANGUL JONGSEONG RIEUL-SSANGSIOS : "ᇞ" U11de # HANGUL JONGSEONG MIEUM-SSANGSIOS : "ᇭ" U11ed # HANGUL JONGSEONG IEUNG-SSANGKIYEOK : "ᄢ" U1122 # HANGUL CHOSEONG PIEUP-SIOS-KIYEOK : "ᄣ" U1123 # HANGUL CHOSEONG PIEUP-SIOS-TIKEUT : "ᄤ" U1124 # HANGUL CHOSEONG PIEUP-SIOS-PIEUP : "ᄥ" U1125 # HANGUL CHOSEONG PIEUP-SSANGSIOS : "ᄦ" U1126 # HANGUL CHOSEONG PIEUP-SIOS-CIEUC : "ᄬ" U112c # HANGUL CHOSEONG KAPYEOUNSSANGPIEUP : "ᄳ" U1133 # HANGUL CHOSEONG SIOS-PIEUP-KIYEOK : "ᄴ" U1134 # HANGUL CHOSEONG SIOS-SSANGSIOS : "ᅫ" U116b # HANGUL JUNGSEONG WAE : "ᅰ" U1170 # HANGUL JUNGSEONG WE : "ᆋ" U118b # HANGUL JUNGSEONG U-EO-EU : "ᇄ" U11c4 # HANGUL JONGSEONG KIYEOK-SIOS-KIYEOK : "ᇌ" U11cc # HANGUL JONGSEONG RIEUL-KIYEOK-SIOS : "ᇑ" U11d1 # HANGUL JONGSEONG RIEUL-MIEUM-KIYEOK : "ᇒ" U11d2 # HANGUL JONGSEONG RIEUL-MIEUM-SIOS : "ᇓ" U11d3 # HANGUL JONGSEONG RIEUL-PIEUP-SIOS : "ᇔ" U11d4 # HANGUL JONGSEONG RIEUL-PIEUP-HIEUH : "ᇕ" U11d5 # HANGUL JONGSEONG RIEUL-KAPYEOUNPIEUP : "ᇖ" U11d6 # HANGUL JONGSEONG RIEUL-SSANGSIOS : "ᇞ" U11de # HANGUL JONGSEONG MIEUM-SSANGSIOS : "ᇭ" U11ed # HANGUL JONGSEONG IEUNG-SSANGKIYEOK # Part 3 : "¬" notsign # NOT SIGN : "¬" notsign # NOT SIGN : "ª" ordfeminine # FEMININE ORDINAL INDICATOR : "ª" ordfeminine # FEMININE ORDINAL INDICATOR <2> : "²" twosuperior # SUPERSCRIPT TWO <2> : "²" twosuperior # SUPERSCRIPT TWO : "²" twosuperior # SUPERSCRIPT TWO : "²" twosuperior # SUPERSCRIPT TWO : "²" twosuperior # SUPERSCRIPT TWO : "²" twosuperior # SUPERSCRIPT TWO <2> : "²" twosuperior # SUPERSCRIPT TWO <3> : "³" threesuperior # SUPERSCRIPT THREE <3> : "³" threesuperior # SUPERSCRIPT THREE : "³" threesuperior # SUPERSCRIPT THREE : "³" threesuperior # SUPERSCRIPT THREE <3> : "³" threesuperior # SUPERSCRIPT THREE : "µ" mu # MICRO SIGN : "µ" mu # MICRO SIGN : "µ" mu # MICRO SIGN <1> : "¹" onesuperior # SUPERSCRIPT ONE <1> : "¹" onesuperior # SUPERSCRIPT ONE : "¹" onesuperior # SUPERSCRIPT ONE : "¹" onesuperior # SUPERSCRIPT ONE <1> : "¹" onesuperior # SUPERSCRIPT ONE : "º" masculine # MASCULINE ORDINAL INDICATOR : "º" ordmasculine # MASCULINE ORDINAL INDICATOR <1> <4> : "¼" onequarter # VULGAR FRACTION ONE QUARTER <1> <2> : "½" onehalf # VULGAR FRACTION ONE HALF <3> <4> : "¾" threequarters # VULGAR FRACTION THREE QUARTERS : "À" Agrave # LATIN CAPITAL LETTER A WITH GRAVE : "À" Agrave # LATIN CAPITAL LETTER A WITH GRAVE : "À" Agrave # LATIN CAPITAL LETTER A WITH GRAVE : "Á" Aacute # LATIN CAPITAL LETTER A WITH ACUTE : "Á" Aacute # LATIN CAPITAL LETTER A WITH ACUTE : "Á" Aacute # LATIN CAPITAL LETTER A WITH ACUTE : "Á" Aacute # LATIN CAPITAL LETTER A WITH ACUTE : "Á" Aacute # LATIN CAPITAL LETTER A WITH ACUTE : "Â" Acircumflex # LATIN CAPITAL LETTER A WITH CIRCUMFLEX : "Â" Acircumflex # LATIN CAPITAL LETTER A WITH CIRCUMFLEX : "Â" Acircumflex # LATIN CAPITAL LETTER A WITH CIRCUMFLEX : "Â" Acircumflex # LATIN CAPITAL LETTER A WITH CIRCUMFLEX : "Â" Acircumflex # LATIN CAPITAL LETTER A WITH CIRCUMFLEX : "Ã" Atilde # LATIN CAPITAL LETTER A WITH TILDE : "Ã" Atilde # LATIN CAPITAL LETTER A WITH TILDE : "Ã" Atilde # LATIN CAPITAL LETTER A WITH TILDE : "Ä" Adiaeresis # LATIN CAPITAL LETTER A WITH DIAERESIS : "Ä" Adiaeresis # LATIN CAPITAL LETTER A WITH DIAERESIS : "Ä" Adiaeresis # LATIN CAPITAL LETTER A WITH DIAERESIS : "Ä" Adiaeresis # LATIN CAPITAL LETTER A WITH DIAERESIS : "Ä" Adiaeresis # LATIN CAPITAL LETTER A WITH DIAERESIS : "Å" Aring # LATIN CAPITAL LETTER A WITH RING ABOVE : "Å" Aring # LATIN CAPITAL LETTER A WITH RING ABOVE : "Å" Aring # LATIN CAPITAL LETTER A WITH RING ABOVE : "Å" Aring # LATIN CAPITAL LETTER A WITH RING ABOVE : "Å" Aring # LATIN CAPITAL LETTER A WITH RING ABOVE : "Ç" Ccedilla # LATIN CAPITAL LETTER C WITH CEDILLA : "Ç" Ccedilla # LATIN CAPITAL LETTER C WITH CEDILLA : "Ç" Ccedilla # LATIN CAPITAL LETTER C WITH CEDILLA : "Ç" Ccedilla # LATIN CAPITAL LETTER C WITH CEDILLA : "È" Egrave # LATIN CAPITAL LETTER E WITH GRAVE : "È" Egrave # LATIN CAPITAL LETTER E WITH GRAVE : "È" Egrave # LATIN CAPITAL LETTER E WITH GRAVE : "É" Eacute # LATIN CAPITAL LETTER E WITH ACUTE : "É" Eacute # LATIN CAPITAL LETTER E WITH ACUTE : "É" Eacute # LATIN CAPITAL LETTER E WITH ACUTE : "É" Eacute # LATIN CAPITAL LETTER E WITH ACUTE : "É" Eacute # LATIN CAPITAL LETTER E WITH ACUTE : "Ê" Ecircumflex # LATIN CAPITAL LETTER E WITH CIRCUMFLEX : "Ê" Ecircumflex # LATIN CAPITAL LETTER E WITH CIRCUMFLEX : "Ê" Ecircumflex # LATIN CAPITAL LETTER E WITH CIRCUMFLEX : "Ê" Ecircumflex # LATIN CAPITAL LETTER E WITH CIRCUMFLEX : "Ê" Ecircumflex # LATIN CAPITAL LETTER E WITH CIRCUMFLEX : "Ë" Ediaeresis # LATIN CAPITAL LETTER E WITH DIAERESIS : "Ë" Ediaeresis # LATIN CAPITAL LETTER E WITH DIAERESIS : "Ë" Ediaeresis # LATIN CAPITAL LETTER E WITH DIAERESIS : "Ë" Ediaeresis # LATIN CAPITAL LETTER E WITH DIAERESIS : "Ë" Ediaeresis # LATIN CAPITAL LETTER E WITH DIAERESIS : "Ì" Igrave # LATIN CAPITAL LETTER I WITH GRAVE : "Ì" Igrave # LATIN CAPITAL LETTER I WITH GRAVE : "Ì" Igrave # LATIN CAPITAL LETTER I WITH GRAVE : "Í" Iacute # LATIN CAPITAL LETTER I WITH ACUTE : "Í" Iacute # LATIN CAPITAL LETTER I WITH ACUTE : "Í" Iacute # LATIN CAPITAL LETTER I WITH ACUTE : "Í" Iacute # LATIN CAPITAL LETTER I WITH ACUTE : "Í" Iacute # LATIN CAPITAL LETTER I WITH ACUTE : "Î" Icircumflex # LATIN CAPITAL LETTER I WITH CIRCUMFLEX : "Î" Icircumflex # LATIN CAPITAL LETTER I WITH CIRCUMFLEX : "Î" Icircumflex # LATIN CAPITAL LETTER I WITH CIRCUMFLEX : "Î" Icircumflex # LATIN CAPITAL LETTER I WITH CIRCUMFLEX : "Î" Icircumflex # LATIN CAPITAL LETTER I WITH CIRCUMFLEX : "Ï" Idiaeresis # LATIN CAPITAL LETTER I WITH DIAERESIS : "Ï" Idiaeresis # LATIN CAPITAL LETTER I WITH DIAERESIS : "Ï" Idiaeresis # LATIN CAPITAL LETTER I WITH DIAERESIS : "Ï" Idiaeresis # LATIN CAPITAL LETTER I WITH DIAERESIS : "Ï" Idiaeresis # LATIN CAPITAL LETTER I WITH DIAERESIS : "J́" # LATIN CAPITAL LETTER J U004A with COMBINING ACUTE ACCENT U0301 : "J́" # LATIN CAPITAL LETTER J U004A with COMBINING ACUTE ACCENT U0301 : "J́" # LATIN CAPITAL LETTER J U004A with COMBINING ACUTE ACCENT U0301 : "J́" # LATIN CAPITAL LETTER J U004A with COMBINING ACUTE ACCENT U0301 : "J́" # LATIN CAPITAL LETTER J U004A with COMBINING ACUTE ACCENT U0301 : "Ð" ETH # LATIN CAPITAL LETTER ETH : "Ñ" Ntilde # LATIN CAPITAL LETTER N WITH TILDE : "Ñ" Ntilde # LATIN CAPITAL LETTER N WITH TILDE : "Ñ" Ntilde # LATIN CAPITAL LETTER N WITH TILDE : "Ò" Ograve # LATIN CAPITAL LETTER O WITH GRAVE : "Ò" Ograve # LATIN CAPITAL LETTER O WITH GRAVE : "Ò" Ograve # LATIN CAPITAL LETTER O WITH GRAVE : "Ó" Oacute # LATIN CAPITAL LETTER O WITH ACUTE : "Ó" Oacute # LATIN CAPITAL LETTER O WITH ACUTE : "Ó" Oacute # LATIN CAPITAL LETTER O WITH ACUTE : "Ó" Oacute # LATIN CAPITAL LETTER O WITH ACUTE : "Ó" Oacute # LATIN CAPITAL LETTER O WITH ACUTE : "Ô" Ocircumflex # LATIN CAPITAL LETTER O WITH CIRCUMFLEX : "Ô" Ocircumflex # LATIN CAPITAL LETTER O WITH CIRCUMFLEX : "Ô" Ocircumflex # LATIN CAPITAL LETTER O WITH CIRCUMFLEX : "Ô" Ocircumflex # LATIN CAPITAL LETTER O WITH CIRCUMFLEX : "Ô" Ocircumflex # LATIN CAPITAL LETTER O WITH CIRCUMFLEX : "Õ" Otilde # LATIN CAPITAL LETTER O WITH TILDE : "Õ" Otilde # LATIN CAPITAL LETTER O WITH TILDE : "Õ" Otilde # LATIN CAPITAL LETTER O WITH TILDE : "Ö" Odiaeresis # LATIN CAPITAL LETTER O WITH DIAERESIS : "Ö" Odiaeresis # LATIN CAPITAL LETTER O WITH DIAERESIS : "Ö" Odiaeresis # LATIN CAPITAL LETTER O WITH DIAERESIS : "Ö" Odiaeresis # LATIN CAPITAL LETTER O WITH DIAERESIS : "Ö" Odiaeresis # LATIN CAPITAL LETTER O WITH DIAERESIS : "×" multiply # MULTIPLICATION SIGN : "Ø" Oslash # LATIN CAPITAL LETTER O WITH STROKE : "Ø" Oslash # LATIN CAPITAL LETTER O WITH STROKE : "Ø" Oslash # LATIN CAPITAL LETTER O WITH STROKE : "Ø" Oslash # LATIN CAPITAL LETTER O WITH STROKE : "Ù" Ugrave # LATIN CAPITAL LETTER U WITH GRAVE : "Ù" Ugrave # LATIN CAPITAL LETTER U WITH GRAVE : "Ù" Ugrave # LATIN CAPITAL LETTER U WITH GRAVE : "Ú" Uacute # LATIN CAPITAL LETTER U WITH ACUTE : "Ú" Uacute # LATIN CAPITAL LETTER U WITH ACUTE : "Ú" Uacute # LATIN CAPITAL LETTER U WITH ACUTE : "Ú" Uacute # LATIN CAPITAL LETTER U WITH ACUTE : "Ú" Uacute # LATIN CAPITAL LETTER U WITH ACUTE : "Û" Ucircumflex # LATIN CAPITAL LETTER U WITH CIRCUMFLEX : "Û" Ucircumflex # LATIN CAPITAL LETTER U WITH CIRCUMFLEX : "Û" Ucircumflex # LATIN CAPITAL LETTER U WITH CIRCUMFLEX : "Û" Ucircumflex # LATIN CAPITAL LETTER U WITH CIRCUMFLEX : "Û" Ucircumflex # LATIN CAPITAL LETTER U WITH CIRCUMFLEX : "Ü" Udiaeresis # LATIN CAPITAL LETTER U WITH DIAERESIS : "Ü" Udiaeresis # LATIN CAPITAL LETTER U WITH DIAERESIS : "Ü" Udiaeresis # LATIN CAPITAL LETTER U WITH DIAERESIS : "Ü" Udiaeresis # LATIN CAPITAL LETTER U WITH DIAERESIS : "Ü" Udiaeresis # LATIN CAPITAL LETTER U WITH DIAERESIS : "Ý" Yacute # LATIN CAPITAL LETTER Y WITH ACUTE : "Ý" Yacute # LATIN CAPITAL LETTER Y WITH ACUTE : "Ý" Yacute # LATIN CAPITAL LETTER Y WITH ACUTE : "Ý" Yacute # LATIN CAPITAL LETTER Y WITH ACUTE : "Ý" Yacute # LATIN CAPITAL LETTER Y WITH ACUTE : "Þ" THORN # LATIN CAPITAL LETTER THORN : "à" agrave # LATIN SMALL LETTER A WITH GRAVE : "à" agrave # LATIN SMALL LETTER A WITH GRAVE : "à" agrave # LATIN SMALL LETTER A WITH GRAVE : "á" aacute # LATIN SMALL LETTER A WITH ACUTE : "á" aacute # LATIN SMALL LETTER A WITH ACUTE : "á" aacute # LATIN SMALL LETTER A WITH ACUTE : "á" aacute # LATIN SMALL LETTER A WITH ACUTE : "á" aacute # LATIN SMALL LETTER A WITH ACUTE : "â" acircumflex # LATIN SMALL LETTER A WITH CIRCUMFLEX : "â" acircumflex # LATIN SMALL LETTER A WITH CIRCUMFLEX : "â" acircumflex # LATIN SMALL LETTER A WITH CIRCUMFLEX : "â" acircumflex # LATIN SMALL LETTER A WITH CIRCUMFLEX : "â" acircumflex # LATIN SMALL LETTER A WITH CIRCUMFLEX : "ã" atilde # LATIN SMALL LETTER A WITH TILDE : "ã" atilde # LATIN SMALL LETTER A WITH TILDE : "ã" atilde # LATIN SMALL LETTER A WITH TILDE : "ä" adiaeresis # LATIN SMALL LETTER A WITH DIAERESIS : "ä" adiaeresis # LATIN SMALL LETTER A WITH DIAERESIS : "ä" adiaeresis # LATIN SMALL LETTER A WITH DIAERESIS : "ä" adiaeresis # LATIN SMALL LETTER A WITH DIAERESIS : "ä" adiaeresis # LATIN SMALL LETTER A WITH DIAERESIS : "å" aring # LATIN SMALL LETTER A WITH RING ABOVE : "å" aring # LATIN SMALL LETTER A WITH RING ABOVE : "å" aring # LATIN SMALL LETTER A WITH RING ABOVE : "å" aring # LATIN SMALL LETTER A WITH RING ABOVE : "å" aring # LATIN SMALL LETTER A WITH RING ABOVE : "ç" ccedilla # LATIN SMALL LETTER C WITH CEDILLA : "ç" ccedilla # LATIN SMALL LETTER C WITH CEDILLA : "ç" ccedilla # LATIN SMALL LETTER C WITH CEDILLA : "ç" ccedilla # LATIN SMALL LETTER C WITH CEDILLA : "è" egrave # LATIN SMALL LETTER E WITH GRAVE : "è" egrave # LATIN SMALL LETTER E WITH GRAVE : "è" egrave # LATIN SMALL LETTER E WITH GRAVE : "é" eacute # LATIN SMALL LETTER E WITH ACUTE : "é" eacute # LATIN SMALL LETTER E WITH ACUTE : "é" eacute # LATIN SMALL LETTER E WITH ACUTE : "é" eacute # LATIN SMALL LETTER E WITH ACUTE : "é" eacute # LATIN SMALL LETTER E WITH ACUTE : "ê" ecircumflex # LATIN SMALL LETTER E WITH CIRCUMFLEX : "ê" ecircumflex # LATIN SMALL LETTER E WITH CIRCUMFLEX : "ê" ecircumflex # LATIN SMALL LETTER E WITH CIRCUMFLEX : "ê" ecircumflex # LATIN SMALL LETTER E WITH CIRCUMFLEX : "ê" ecircumflex # LATIN SMALL LETTER E WITH CIRCUMFLEX : "ë" ediaeresis # LATIN SMALL LETTER E WITH DIAERESIS : "ë" ediaeresis # LATIN SMALL LETTER E WITH DIAERESIS : "ë" ediaeresis # LATIN SMALL LETTER E WITH DIAERESIS : "ë" ediaeresis # LATIN SMALL LETTER E WITH DIAERESIS : "ë" ediaeresis # LATIN SMALL LETTER E WITH DIAERESIS : "ì" igrave # LATIN SMALL LETTER I WITH GRAVE : "ì" igrave # LATIN SMALL LETTER I WITH GRAVE : "ì" igrave # LATIN SMALL LETTER I WITH GRAVE : "í" iacute # LATIN SMALL LETTER I WITH ACUTE : "í" iacute # LATIN SMALL LETTER I WITH ACUTE : "í" iacute # LATIN SMALL LETTER I WITH ACUTE : "í" iacute # LATIN SMALL LETTER I WITH ACUTE : "í" iacute # LATIN SMALL LETTER I WITH ACUTE : "î" icircumflex # LATIN SMALL LETTER I WITH CIRCUMFLEX : "î" icircumflex # LATIN SMALL LETTER I WITH CIRCUMFLEX : "î" icircumflex # LATIN SMALL LETTER I WITH CIRCUMFLEX : "î" icircumflex # LATIN SMALL LETTER I WITH CIRCUMFLEX : "î" icircumflex # LATIN SMALL LETTER I WITH CIRCUMFLEX : "ï" idiaeresis # LATIN SMALL LETTER I WITH DIAERESIS : "ï" idiaeresis # LATIN SMALL LETTER I WITH DIAERESIS : "ï" idiaeresis # LATIN SMALL LETTER I WITH DIAERESIS : "ï" idiaeresis # LATIN SMALL LETTER I WITH DIAERESIS : "ï" idiaeresis # LATIN SMALL LETTER I WITH DIAERESIS : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 : "j́" # LATIN SMALL LETTER J U006A with COMBINING ACUTE ACCENT U0301 : "ð" eth # LATIN SMALL LETTER ETH : "ñ" ntilde # LATIN SMALL LETTER N WITH TILDE : "ñ" ntilde # LATIN SMALL LETTER N WITH TILDE : "ñ" ntilde # LATIN SMALL LETTER N WITH TILDE : "ò" ograve # LATIN SMALL LETTER O WITH GRAVE : "ò" ograve # LATIN SMALL LETTER O WITH GRAVE : "ò" ograve # LATIN SMALL LETTER O WITH GRAVE : "ó" oacute # LATIN SMALL LETTER O WITH ACUTE : "ó" oacute # LATIN SMALL LETTER O WITH ACUTE : "ó" oacute # LATIN SMALL LETTER O WITH ACUTE : "ó" oacute # LATIN SMALL LETTER O WITH ACUTE : "ó" oacute # LATIN SMALL LETTER O WITH ACUTE : "ô" ocircumflex # LATIN SMALL LETTER O WITH CIRCUMFLEX : "ô" ocircumflex # LATIN SMALL LETTER O WITH CIRCUMFLEX : "ô" ocircumflex # LATIN SMALL LETTER O WITH CIRCUMFLEX : "ô" ocircumflex # LATIN SMALL LETTER O WITH CIRCUMFLEX : "ô" ocircumflex # LATIN SMALL LETTER O WITH CIRCUMFLEX : "õ" otilde # LATIN SMALL LETTER O WITH TILDE : "õ" otilde # LATIN SMALL LETTER O WITH TILDE : "õ" otilde # LATIN SMALL LETTER O WITH TILDE : "ö" odiaeresis # LATIN SMALL LETTER O WITH DIAERESIS : "ö" odiaeresis # LATIN SMALL LETTER O WITH DIAERESIS : "ö" odiaeresis # LATIN SMALL LETTER O WITH DIAERESIS : "ö" odiaeresis # LATIN SMALL LETTER O WITH DIAERESIS : "ö" odiaeresis # LATIN SMALL LETTER O WITH DIAERESIS : "÷" division # DIVISION SIGN : "÷" division # DIVISION SIGN : "ø" oslash # LATIN SMALL LETTER O WITH STROKE : "ø" oslash # LATIN SMALL LETTER O WITH STROKE : "ø" oslash # LATIN SMALL LETTER O WITH STROKE : "ø" oslash # LATIN SMALL LETTER O WITH STROKE : "ù" ugrave # LATIN SMALL LETTER U WITH GRAVE : "ù" ugrave # LATIN SMALL LETTER U WITH GRAVE : "ù" ugrave # LATIN SMALL LETTER U WITH GRAVE : "ú" uacute # LATIN SMALL LETTER U WITH ACUTE : "ú" uacute # LATIN SMALL LETTER U WITH ACUTE : "ú" uacute # LATIN SMALL LETTER U WITH ACUTE : "ú" uacute # LATIN SMALL LETTER U WITH ACUTE : "ú" uacute # LATIN SMALL LETTER U WITH ACUTE : "û" ucircumflex # LATIN SMALL LETTER U WITH CIRCUMFLEX : "û" ucircumflex # LATIN SMALL LETTER U WITH CIRCUMFLEX : "û" ucircumflex # LATIN SMALL LETTER U WITH CIRCUMFLEX : "û" ucircumflex # LATIN SMALL LETTER U WITH CIRCUMFLEX : "û" ucircumflex # LATIN SMALL LETTER U WITH CIRCUMFLEX : "ü" udiaeresis # LATIN SMALL LETTER U WITH DIAERESIS : "ü" udiaeresis # LATIN SMALL LETTER U WITH DIAERESIS : "ü" udiaeresis # LATIN SMALL LETTER U WITH DIAERESIS : "ü" udiaeresis # LATIN SMALL LETTER U WITH DIAERESIS : "ü" udiaeresis # LATIN SMALL LETTER U WITH DIAERESIS : "ý" yacute # LATIN SMALL LETTER Y WITH ACUTE : "ý" yacute # LATIN SMALL LETTER Y WITH ACUTE : "ý" yacute # LATIN SMALL LETTER Y WITH ACUTE : "ý" yacute # LATIN SMALL LETTER Y WITH ACUTE : "ý" yacute # LATIN SMALL LETTER Y WITH ACUTE : "þ" thorn # LATIN SMALL LETTER THORN : "ÿ" ydiaeresis # LATIN SMALL LETTER Y WITH DIAERESIS : "ÿ" ydiaeresis # LATIN SMALL LETTER Y WITH DIAERESIS : "ÿ" ydiaeresis # LATIN SMALL LETTER Y WITH DIAERESIS : "ÿ" ydiaeresis # LATIN SMALL LETTER Y WITH DIAERESIS : "ÿ" ydiaeresis # LATIN SMALL LETTER Y WITH DIAERESIS : "Ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON : "Ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON : "Ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON : "Ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON : "Ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON : "Ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON : "ā" U0101 # LATIN SMALL LETTER A WITH MACRON : "ā" U0101 # LATIN SMALL LETTER A WITH MACRON : "ā" U0101 # LATIN SMALL LETTER A WITH MACRON : "ā" U0101 # LATIN SMALL LETTER A WITH MACRON : "ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON : "ā" U0100 # LATIN CAPITAL LETTER A WITH MACRON : "Ă" U0102 # LATIN CAPITAL LETTER A WITH BREVE : "Ă" U0102 # LATIN CAPITAL LETTER A WITH BREVE : "Ă" U0102 # LATIN CAPITAL LETTER A WITH BREVE : "Ă" U0102 # LATIN CAPITAL LETTER A WITH BREVE : "ă" U0103 # LATIN SMALL LETTER A WITH BREVE : "ă" U0103 # LATIN SMALL LETTER A WITH BREVE : "ă" U0103 # LATIN SMALL LETTER A WITH BREVE : "ă" U0103 # LATIN SMALL LETTER A WITH BREVE : "Ą" U0104 # LATIN CAPITAL LETTER A WITH OGONEK : "Ą" U0104 # LATIN CAPITAL LETTER A WITH OGONEK : "Ą" U0104 # LATIN CAPITAL LETTER A WITH OGONEK : "Ą" U0104 # LATIN CAPITAL LETTER A WITH OGONEK : "ą" U0105 # LATIN SMALL LETTER A WITH OGONEK : "ą" U0105 # LATIN SMALL LETTER A WITH OGONEK : "ą" U0105 # LATIN SMALL LETTER A WITH OGONEK : "ą" U0105 # LATIN SMALL LETTER A WITH OGONEK : "Ć" U0106 # LATIN CAPITAL LETTER C WITH ACUTE : "Ć" U0106 # LATIN CAPITAL LETTER C WITH ACUTE : "Ć" U0106 # LATIN CAPITAL LETTER C WITH ACUTE : "Ć" U0106 # LATIN CAPITAL LETTER C WITH ACUTE : "ć" U0107 # LATIN SMALL LETTER C WITH ACUTE : "ć" U0107 # LATIN SMALL LETTER C WITH ACUTE : "ć" U0107 # LATIN SMALL LETTER C WITH ACUTE : "ć" U0107 # LATIN SMALL LETTER C WITH ACUTE : "Ĉ" U0108 # LATIN CAPITAL LETTER C WITH CIRCUMFLEX : "Ĉ" U0108 # LATIN CAPITAL LETTER C WITH CIRCUMFLEX : "ĉ" U0109 # LATIN SMALL LETTER C WITH CIRCUMFLEX : "ĉ" U0109 # LATIN SMALL LETTER C WITH CIRCUMFLEX : "Ċ" U010A # LATIN CAPITAL LETTER C WITH DOT ABOVE : "Ċ" U010A # LATIN CAPITAL LETTER C WITH DOT ABOVE : "Ċ" U010A # LATIN CAPITAL LETTER C WITH DOT ABOVE : "ċ" U010B # LATIN SMALL LETTER C WITH DOT ABOVE : "ċ" U010B # LATIN SMALL LETTER C WITH DOT ABOVE : "ċ" U010B # LATIN SMALL LETTER C WITH DOT ABOVE : "Č" U010C # LATIN CAPITAL LETTER C WITH CARON : "Č" U010C # LATIN CAPITAL LETTER C WITH CARON : "Č" U010C # LATIN CAPITAL LETTER C WITH CARON : "Č" U010C # LATIN CAPITAL LETTER C WITH CARON : "č" U010D # LATIN SMALL LETTER C WITH CARON : "č" U010D # LATIN SMALL LETTER C WITH CARON : "č" U010D # LATIN SMALL LETTER C WITH CARON : "č" U010D # LATIN SMALL LETTER C WITH CARON : "Ď" U010E # LATIN CAPITAL LETTER D WITH CARON : "Ď" U010E # LATIN CAPITAL LETTER D WITH CARON : "Ď" U010E # LATIN CAPITAL LETTER D WITH CARON : "Ď" U010E # LATIN CAPITAL LETTER D WITH CARON : "ď" U010F # LATIN SMALL LETTER D WITH CARON : "ď" U010F # LATIN SMALL LETTER D WITH CARON : "ď" U010F # LATIN SMALL LETTER D WITH CARON : "ď" U010F # LATIN SMALL LETTER D WITH CARON : "Đ" Dstroke # LATIN CAPITAL LETTER D WITH STROKE : "Đ" Dstroke # LATIN CAPITAL LETTER D WITH STROKE : "Đ" Dstroke # LATIN CAPITAL LETTER D WITH STROKE : "Đ" Dstroke # LATIN CAPITAL LETTER D WITH STROKE : "đ" dstroke # LATIN SMALL LETTER D WITH STROKE : "đ" dstroke # LATIN SMALL LETTER D WITH STROKE : "đ" dstroke # LATIN SMALL LETTER D WITH STROKE : "đ" dstroke # LATIN SMALL LETTER D WITH STROKE : "Ē" U0112 # LATIN CAPITAL LETTER E WITH MACRON : "Ē" U0112 # LATIN CAPITAL LETTER E WITH MACRON : "Ē" U0112 # LATIN CAPITAL LETTER E WITH MACRON : "Ē" U0112 # LATIN CAPITAL LETTER E WITH MACRON : "Ē" U0112 # LATIN CAPITAL LETTER E WITH MACRON : "Ē" U0112 # LATIN CAPITAL LETTER E WITH MACRON : "ē" U0113 # LATIN SMALL LETTER E WITH MACRON : "ē" U0113 # LATIN SMALL LETTER E WITH MACRON : "ē" U0113 # LATIN SMALL LETTER E WITH MACRON : "ē" U0113 # LATIN SMALL LETTER E WITH MACRON : "ē" U0113 # LATIN SMALL LETTER E WITH MACRON : "ē" U0113 # LATIN SMALL LETTER E WITH MACRON : "Ĕ" U0114 # LATIN CAPITAL LETTER E WITH BREVE : "Ĕ" U0114 # LATIN CAPITAL LETTER E WITH BREVE : "Ĕ" U0114 # LATIN CAPITAL LETTER E WITH BREVE : "ĕ" U0115 # LATIN SMALL LETTER E WITH BREVE : "ĕ" U0115 # LATIN SMALL LETTER E WITH BREVE : "ĕ" U0115 # LATIN SMALL LETTER E WITH BREVE : "Ė" U0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE : "Ė" U0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE : "Ė" U0116 # LATIN CAPITAL LETTER E WITH DOT ABOVE : "ė" U0117 # LATIN SMALL LETTER E WITH DOT ABOVE : "ė" U0117 # LATIN SMALL LETTER E WITH DOT ABOVE : "ė" U0117 # LATIN SMALL LETTER E WITH DOT ABOVE : "Ę" U0118 # LATIN CAPITAL LETTER E WITH OGONEK : "Ę" U0118 # LATIN CAPITAL LETTER E WITH OGONEK : "Ę" U0118 # LATIN CAPITAL LETTER E WITH OGONEK : "Ę" U0118 # LATIN CAPITAL LETTER E WITH OGONEK : "ę" U0119 # LATIN SMALL LETTER E WITH OGONEK : "ę" U0119 # LATIN SMALL LETTER E WITH OGONEK : "ę" U0119 # LATIN SMALL LETTER E WITH OGONEK : "ę" U0119 # LATIN SMALL LETTER E WITH OGONEK : "Ě" U011A # LATIN CAPITAL LETTER E WITH CARON : "Ě" U011A # LATIN CAPITAL LETTER E WITH CARON : "Ě" U011A # LATIN CAPITAL LETTER E WITH CARON : "Ě" U011A # LATIN CAPITAL LETTER E WITH CARON : "ě" U011B # LATIN SMALL LETTER E WITH CARON : "ě" U011B # LATIN SMALL LETTER E WITH CARON : "ě" U011B # LATIN SMALL LETTER E WITH CARON : "ě" U011B # LATIN SMALL LETTER E WITH CARON : "Ĝ" U011C # LATIN CAPITAL LETTER G WITH CIRCUMFLEX : "Ĝ" U011C # LATIN CAPITAL LETTER G WITH CIRCUMFLEX : "ĝ" U011D # LATIN SMALL LETTER G WITH CIRCUMFLEX : "ĝ" U011D # LATIN SMALL LETTER G WITH CIRCUMFLEX : "Ğ" U011E # LATIN CAPITAL LETTER G WITH BREVE : "Ğ" U011E # LATIN CAPITAL LETTER G WITH BREVE : "Ğ" U011E # LATIN CAPITAL LETTER G WITH BREVE : "Ğ" U011E # LATIN CAPITAL LETTER G WITH BREVE : "Ğ" U011E # LATIN CAPITAL LETTER G WITH BREVE : "Ğ" U011E # LATIN CAPITAL LETTER G WITH BREVE : "Ğ" U011E # LATIN CAPITAL LETTER G WITH BREVE : "ğ" U011F # LATIN SMALL LETTER G WITH BREVE : "ğ" U011F # LATIN SMALL LETTER G WITH BREVE : "ğ" U011F # LATIN SMALL LETTER G WITH BREVE : "ğ" U011F # LATIN SMALL LETTER G WITH BREVE : "ğ" U011F # LATIN SMALL LETTER G WITH BREVE : "ğ" U011F # LATIN SMALL LETTER G WITH BREVE : "ğ" U011F # LATIN SMALL LETTER G WITH BREVE : "Ġ" U0120 # LATIN CAPITAL LETTER G WITH DOT ABOVE : "Ġ" U0120 # LATIN CAPITAL LETTER G WITH DOT ABOVE : "Ġ" U0120 # LATIN CAPITAL LETTER G WITH DOT ABOVE : "ġ" U0121 # LATIN SMALL LETTER G WITH DOT ABOVE : "ġ" U0121 # LATIN SMALL LETTER G WITH DOT ABOVE : "ġ" U0121 # LATIN SMALL LETTER G WITH DOT ABOVE : "Ģ" U0122 # LATIN CAPITAL LETTER G WITH CEDILLA : "Ģ" U0122 # LATIN CAPITAL LETTER G WITH CEDILLA : "Ģ" U0122 # LATIN CAPITAL LETTER G WITH CEDILLA : "Ģ" U0122 # LATIN CAPITAL LETTER G WITH CEDILLA : "ģ" U0123 # LATIN SMALL LETTER G WITH CEDILLA : "ģ" U0123 # LATIN SMALL LETTER G WITH CEDILLA : "ģ" U0123 # LATIN SMALL LETTER G WITH CEDILLA : "ģ" U0123 # LATIN SMALL LETTER G WITH CEDILLA : "Ĥ" U0124 # LATIN CAPITAL LETTER H WITH CIRCUMFLEX : "Ĥ" U0124 # LATIN CAPITAL LETTER H WITH CIRCUMFLEX : "ĥ" U0125 # LATIN SMALL LETTER H WITH CIRCUMFLEX : "ĥ" U0125 # LATIN SMALL LETTER H WITH CIRCUMFLEX : "Ħ" U0126 # LATIN CAPITAL LETTER H WITH STROKE : "Ħ" U0126 # LATIN CAPITAL LETTER H WITH STROKE : "Ħ" U0126 # LATIN CAPITAL LETTER H WITH STROKE : "ħ" U0127 # LATIN SMALL LETTER H WITH STROKE : "ħ" U0127 # LATIN SMALL LETTER H WITH STROKE : "ħ" U0127 # LATIN SMALL LETTER H WITH STROKE : "Ĩ" U0128 # LATIN CAPITAL LETTER I WITH TILDE : "Ĩ" U0128 # LATIN CAPITAL LETTER I WITH TILDE : "Ĩ" U0128 # LATIN CAPITAL LETTER I WITH TILDE : "ĩ" U0129 # LATIN SMALL LETTER I WITH TILDE : "ĩ" U0129 # LATIN SMALL LETTER I WITH TILDE : "ĩ" U0129 # LATIN SMALL LETTER I WITH TILDE : "Ī" U012A # LATIN CAPITAL LETTER I WITH MACRON : "Ī" U012A # LATIN CAPITAL LETTER I WITH MACRON : "Ī" U012A # LATIN CAPITAL LETTER I WITH MACRON : "Ī" U012A # LATIN CAPITAL LETTER I WITH MACRON : "Ī" U012A # LATIN CAPITAL LETTER I WITH MACRON : "Ī" U012A # LATIN CAPITAL LETTER I WITH MACRON : "ī" U012B # LATIN SMALL LETTER I WITH MACRON : "ī" U012B # LATIN SMALL LETTER I WITH MACRON : "ī" U012B # LATIN SMALL LETTER I WITH MACRON : "ī" U012B # LATIN SMALL LETTER I WITH MACRON : "ī" U012B # LATIN SMALL LETTER I WITH MACRON : "ī" U012B # LATIN SMALL LETTER I WITH MACRON : "Ĭ" U012C # LATIN CAPITAL LETTER I WITH BREVE : "Ĭ" U012C # LATIN CAPITAL LETTER I WITH BREVE : "Ĭ" U012C # LATIN CAPITAL LETTER I WITH BREVE : "ĭ" U012D # LATIN SMALL LETTER I WITH BREVE : "ĭ" U012D # LATIN SMALL LETTER I WITH BREVE : "ĭ" U012D # LATIN SMALL LETTER I WITH BREVE : "Į" U012E # LATIN CAPITAL LETTER I WITH OGONEK : "Į" U012E # LATIN CAPITAL LETTER I WITH OGONEK : "Į" U012E # LATIN CAPITAL LETTER I WITH OGONEK : "Į" U012E # LATIN CAPITAL LETTER I WITH OGONEK : "į" U012F # LATIN SMALL LETTER I WITH OGONEK : "į" U012F # LATIN SMALL LETTER I WITH OGONEK : "į" U012F # LATIN SMALL LETTER I WITH OGONEK : "į" U012F # LATIN SMALL LETTER I WITH OGONEK : "į" U012F # LATIN SMALL LETTER I WITH OGONEK : "İ" U0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE : "İ" U0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE : "İ" U0130 # LATIN CAPITAL LETTER I WITH DOT ABOVE : "ı" U0131 # LATIN SMALL LETTER DOTLESS I : "ı" U0131 # LATIN SMALL LETTER DOTLESS I : "ı" U0131 # LATIN SMALL LETTER DOTLESS I : "Ĵ" U0134 # LATIN CAPITAL LETTER J WITH CIRCUMFLEX : "Ĵ" U0134 # LATIN CAPITAL LETTER J WITH CIRCUMFLEX : "ĵ" U0135 # LATIN SMALL LETTER J WITH CIRCUMFLEX : "ĵ" U0135 # LATIN SMALL LETTER J WITH CIRCUMFLEX : "Ķ" U0136 # LATIN CAPITAL LETTER K WITH CEDILLA : "Ķ" U0136 # LATIN CAPITAL LETTER K WITH CEDILLA : "Ķ" U0136 # LATIN CAPITAL LETTER K WITH CEDILLA : "Ķ" U0136 # LATIN CAPITAL LETTER K WITH CEDILLA : "ķ" U0137 # LATIN SMALL LETTER K WITH CEDILLA : "ķ" U0137 # LATIN SMALL LETTER K WITH CEDILLA : "ķ" U0137 # LATIN SMALL LETTER K WITH CEDILLA : "ķ" U0137 # LATIN SMALL LETTER K WITH CEDILLA : "ĸ" U0138 # LATIN SMALL LETTER KRA : "Ĺ" U0139 # LATIN CAPITAL LETTER L WITH ACUTE : "Ĺ" U0139 # LATIN CAPITAL LETTER L WITH ACUTE : "Ĺ" U0139 # LATIN CAPITAL LETTER L WITH ACUTE : "Ĺ" U0139 # LATIN CAPITAL LETTER L WITH ACUTE : "ĺ" U013A # LATIN SMALL LETTER L WITH ACUTE : "ĺ" U013A # LATIN SMALL LETTER L WITH ACUTE : "ĺ" U013A # LATIN SMALL LETTER L WITH ACUTE : "ĺ" U013A # LATIN SMALL LETTER L WITH ACUTE : "Ļ" U013B # LATIN CAPITAL LETTER L WITH CEDILLA : "Ļ" U013B # LATIN CAPITAL LETTER L WITH CEDILLA : "Ļ" U013B # LATIN CAPITAL LETTER L WITH CEDILLA : "Ļ" U013B # LATIN CAPITAL LETTER L WITH CEDILLA : "ļ" U013C # LATIN SMALL LETTER L WITH CEDILLA : "ļ" U013C # LATIN SMALL LETTER L WITH CEDILLA : "ļ" U013C # LATIN SMALL LETTER L WITH CEDILLA : "ļ" U013C # LATIN SMALL LETTER L WITH CEDILLA : "Ľ" U013D # LATIN CAPITAL LETTER L WITH CARON : "Ľ" U013D # LATIN CAPITAL LETTER L WITH CARON : "Ľ" U013D # LATIN CAPITAL LETTER L WITH CARON : "Ľ" U013D # LATIN CAPITAL LETTER L WITH CARON : "ľ" U013E # LATIN SMALL LETTER L WITH CARON : "ľ" U013E # LATIN SMALL LETTER L WITH CARON : "ľ" U013E # LATIN SMALL LETTER L WITH CARON : "ľ" U013E # LATIN SMALL LETTER L WITH CARON : "Ł" U0141 # LATIN CAPITAL LETTER L WITH STROKE : "Ł" U0141 # LATIN CAPITAL LETTER L WITH STROKE : "Ł" U0141 # LATIN CAPITAL LETTER L WITH STROKE : "Ł" U0141 # LATIN CAPITAL LETTER L WITH STROKE : "ł" U0142 # LATIN SMALL LETTER L WITH STROKE : "ł" U0142 # LATIN SMALL LETTER L WITH STROKE : "ł" U0142 # LATIN SMALL LETTER L WITH STROKE : "ł" U0142 # LATIN SMALL LETTER L WITH STROKE : "Ń" U0143 # LATIN CAPITAL LETTER N WITH ACUTE : "Ń" U0143 # LATIN CAPITAL LETTER N WITH ACUTE : "Ń" U0143 # LATIN CAPITAL LETTER N WITH ACUTE : "Ń" U0143 # LATIN CAPITAL LETTER N WITH ACUTE : "ń" U0144 # LATIN SMALL LETTER N WITH ACUTE : "ń" U0144 # LATIN SMALL LETTER N WITH ACUTE : "ń" U0144 # LATIN SMALL LETTER N WITH ACUTE : "ń" U0144 # LATIN SMALL LETTER N WITH ACUTE : "Ņ" U0145 # LATIN CAPITAL LETTER N WITH CEDILLA : "Ņ" U0145 # LATIN CAPITAL LETTER N WITH CEDILLA : "Ņ" U0145 # LATIN CAPITAL LETTER N WITH CEDILLA : "Ņ" U0145 # LATIN CAPITAL LETTER N WITH CEDILLA : "ņ" U0146 # LATIN SMALL LETTER N WITH CEDILLA : "ņ" U0146 # LATIN SMALL LETTER N WITH CEDILLA : "ņ" U0146 # LATIN SMALL LETTER N WITH CEDILLA : "ņ" U0146 # LATIN SMALL LETTER N WITH CEDILLA : "Ň" U0147 # LATIN CAPITAL LETTER N WITH CARON : "Ň" U0147 # LATIN CAPITAL LETTER N WITH CARON : "Ň" U0147 # LATIN CAPITAL LETTER N WITH CARON : "Ň" U0147 # LATIN CAPITAL LETTER N WITH CARON : "ň" U0148 # LATIN SMALL LETTER N WITH CARON : "ň" U0148 # LATIN SMALL LETTER N WITH CARON : "ň" U0148 # LATIN SMALL LETTER N WITH CARON : "ň" U0148 # LATIN SMALL LETTER N WITH CARON : "Ŋ" U014A # LATIN CAPITAL LETTER ENG : "ŋ" U014B # LATIN SMALL LETTER ENG : "Ō" U014C # LATIN CAPITAL LETTER O WITH MACRON : "Ō" U014C # LATIN CAPITAL LETTER O WITH MACRON : "Ō" U014C # LATIN CAPITAL LETTER O WITH MACRON : "Ō" U014C # LATIN CAPITAL LETTER O WITH MACRON : "Ō" U014C # LATIN CAPITAL LETTER O WITH MACRON : "Ō" U014C # LATIN CAPITAL LETTER O WITH MACRON : "ō" U014D # LATIN SMALL LETTER O WITH MACRON : "ō" U014D # LATIN SMALL LETTER O WITH MACRON : "ō" U014D # LATIN SMALL LETTER O WITH MACRON : "ō" U014D # LATIN SMALL LETTER O WITH MACRON : "ō" U014D # LATIN SMALL LETTER O WITH MACRON : "ō" U014D # LATIN SMALL LETTER O WITH MACRON : "Ŏ" U014E # LATIN CAPITAL LETTER O WITH BREVE : "Ŏ" U014E # LATIN CAPITAL LETTER O WITH BREVE : "Ŏ" U014E # LATIN CAPITAL LETTER O WITH BREVE : "ŏ" U014F # LATIN SMALL LETTER O WITH BREVE : "ŏ" U014F # LATIN SMALL LETTER O WITH BREVE : "ŏ" U014F # LATIN SMALL LETTER O WITH BREVE : "Ő" U0150 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE : "Ő" U0150 # LATIN CAPITAL LETTER O WITH DOUBLE ACUTE : "ő" U0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE : "ő" U0151 # LATIN SMALL LETTER O WITH DOUBLE ACUTE : "Ŕ" U0154 # LATIN CAPITAL LETTER R WITH ACUTE : "Ŕ" U0154 # LATIN CAPITAL LETTER R WITH ACUTE : "Ŕ" U0154 # LATIN CAPITAL LETTER R WITH ACUTE : "Ŕ" U0154 # LATIN CAPITAL LETTER R WITH ACUTE : "ŕ" U0155 # LATIN SMALL LETTER R WITH ACUTE : "ŕ" U0155 # LATIN SMALL LETTER R WITH ACUTE : "ŕ" U0155 # LATIN SMALL LETTER R WITH ACUTE : "ŕ" U0155 # LATIN SMALL LETTER R WITH ACUTE : "Ŗ" U0156 # LATIN CAPITAL LETTER R WITH CEDILLA : "Ŗ" U0156 # LATIN CAPITAL LETTER R WITH CEDILLA : "Ŗ" U0156 # LATIN CAPITAL LETTER R WITH CEDILLA : "Ŗ" U0156 # LATIN CAPITAL LETTER R WITH CEDILLA : "ŗ" U0157 # LATIN SMALL LETTER R WITH CEDILLA : "ŗ" U0157 # LATIN SMALL LETTER R WITH CEDILLA : "ŗ" U0157 # LATIN SMALL LETTER R WITH CEDILLA : "ŗ" U0157 # LATIN SMALL LETTER R WITH CEDILLA : "Ř" U0158 # LATIN CAPITAL LETTER R WITH CARON : "Ř" U0158 # LATIN CAPITAL LETTER R WITH CARON : "Ř" U0158 # LATIN CAPITAL LETTER R WITH CARON : "Ř" U0158 # LATIN CAPITAL LETTER R WITH CARON : "ř" U0159 # LATIN SMALL LETTER R WITH CARON : "ř" U0159 # LATIN SMALL LETTER R WITH CARON : "ř" U0159 # LATIN SMALL LETTER R WITH CARON : "ř" U0159 # LATIN SMALL LETTER R WITH CARON : "Ś" U015A # LATIN CAPITAL LETTER S WITH ACUTE : "Ś" U015A # LATIN CAPITAL LETTER S WITH ACUTE : "Ś" U015A # LATIN CAPITAL LETTER S WITH ACUTE : "Ś" U015A # LATIN CAPITAL LETTER S WITH ACUTE : "ś" U015B # LATIN SMALL LETTER S WITH ACUTE : "ś" U015B # LATIN SMALL LETTER S WITH ACUTE : "ś" U015B # LATIN SMALL LETTER S WITH ACUTE : "ś" U015B # LATIN SMALL LETTER S WITH ACUTE : "Ŝ" U015C # LATIN CAPITAL LETTER S WITH CIRCUMFLEX : "Ŝ" U015C # LATIN CAPITAL LETTER S WITH CIRCUMFLEX : "ŝ" U015D # LATIN SMALL LETTER S WITH CIRCUMFLEX : "ŝ" U015D # LATIN SMALL LETTER S WITH CIRCUMFLEX : "Ş" U015E # LATIN CAPITAL LETTER S WITH CEDILLA : "Ş" U015E # LATIN CAPITAL LETTER S WITH CEDILLA : "Ş" U015E # LATIN CAPITAL LETTER S WITH CEDILLA : "Ş" U015E # LATIN CAPITAL LETTER S WITH CEDILLA : "ş" U015F # LATIN SMALL LETTER S WITH CEDILLA : "ş" U015F # LATIN SMALL LETTER S WITH CEDILLA : "ş" U015F # LATIN SMALL LETTER S WITH CEDILLA : "ş" U015F # LATIN SMALL LETTER S WITH CEDILLA : "ş" U015F # LATIN SMALL LETTER S WITH CEDILLA : "Š" U0160 # LATIN CAPITAL LETTER S WITH CARON : "Š" U0160 # LATIN CAPITAL LETTER S WITH CARON : "Š" U0160 # LATIN CAPITAL LETTER S WITH CARON : "Š" U0160 # LATIN CAPITAL LETTER S WITH CARON : "š" U0161 # LATIN SMALL LETTER S WITH CARON : "š" U0161 # LATIN SMALL LETTER S WITH CARON : "š" U0161 # LATIN SMALL LETTER S WITH CARON : "š" U0161 # LATIN SMALL LETTER S WITH CARON : "Ţ" U0162 # LATIN CAPITAL LETTER T WITH CEDILLA : "Ţ" U0162 # LATIN CAPITAL LETTER T WITH CEDILLA : "Ţ" U0162 # LATIN CAPITAL LETTER T WITH CEDILLA : "Ţ" U0162 # LATIN CAPITAL LETTER T WITH CEDILLA : "ţ" U0163 # LATIN SMALL LETTER T WITH CEDILLA : "ţ" U0163 # LATIN SMALL LETTER T WITH CEDILLA : "ţ" U0163 # LATIN SMALL LETTER T WITH CEDILLA : "ţ" U0163 # LATIN SMALL LETTER T WITH CEDILLA : "Ť" U0164 # LATIN CAPITAL LETTER T WITH CARON : "Ť" U0164 # LATIN CAPITAL LETTER T WITH CARON : "Ť" U0164 # LATIN CAPITAL LETTER T WITH CARON : "Ť" U0164 # LATIN CAPITAL LETTER T WITH CARON : "ť" U0165 # LATIN SMALL LETTER T WITH CARON : "ť" U0165 # LATIN SMALL LETTER T WITH CARON : "ť" U0165 # LATIN SMALL LETTER T WITH CARON : "ť" U0165 # LATIN SMALL LETTER T WITH CARON : "Ŧ" U0166 # LATIN CAPITAL LETTER T WITH STROKE : "Ŧ" U0166 # LATIN CAPITAL LETTER T WITH STROKE : "Ŧ" U0166 # LATIN CAPITAL LETTER T WITH STROKE : "Ŧ" U0166 # LATIN CAPITAL LETTER T WITH STROKE : "Ŧ" U0166 # LATIN CAPITAL LETTER T WITH STROKE : "ŧ" U0167 # LATIN SMALL LETTER T WITH STROKE : "ŧ" U0167 # LATIN SMALL LETTER T WITH STROKE : "ŧ" U0167 # LATIN SMALL LETTER T WITH STROKE : "ŧ" U0167 # LATIN SMALL LETTER T WITH STROKE : "ŧ" U0167 # LATIN SMALL LETTER T WITH STROKE : "Ũ" U0168 # LATIN CAPITAL LETTER U WITH TILDE : "Ũ" U0168 # LATIN CAPITAL LETTER U WITH TILDE : "Ũ" U0168 # LATIN CAPITAL LETTER U WITH TILDE : "ũ" U0169 # LATIN SMALL LETTER U WITH TILDE : "ũ" U0169 # LATIN SMALL LETTER U WITH TILDE : "ũ" U0169 # LATIN SMALL LETTER U WITH TILDE : "Ū" U016A # LATIN CAPITAL LETTER U WITH MACRON : "Ū" U016A # LATIN CAPITAL LETTER U WITH MACRON : "Ū" U016A # LATIN CAPITAL LETTER U WITH MACRON : "Ū" U016A # LATIN CAPITAL LETTER U WITH MACRON : "Ū" U016A # LATIN CAPITAL LETTER U WITH MACRON : "Ū" U016A # LATIN CAPITAL LETTER U WITH MACRON : "ū" U016B # LATIN SMALL LETTER U WITH MACRON : "ū" U016B # LATIN SMALL LETTER U WITH MACRON : "ū" U016B # LATIN SMALL LETTER U WITH MACRON : "ū" U016B # LATIN SMALL LETTER U WITH MACRON : "ū" U016B # LATIN SMALL LETTER U WITH MACRON : "ū" U016B # LATIN SMALL LETTER U WITH MACRON : "Ŭ" U016C # LATIN CAPITAL LETTER U WITH BREVE : "Ŭ" U016C # LATIN CAPITAL LETTER U WITH BREVE : "Ŭ" U016C # LATIN CAPITAL LETTER U WITH BREVE : "ŭ" U016D # LATIN SMALL LETTER U WITH BREVE : "ŭ" U016D # LATIN SMALL LETTER U WITH BREVE : "ŭ" U016D # LATIN SMALL LETTER U WITH BREVE : "ŭ" U016D # LATIN SMALL LETTER U WITH BREVE : "Ů" U016E # LATIN CAPITAL LETTER U WITH RING ABOVE : "Ů" U016E # LATIN CAPITAL LETTER U WITH RING ABOVE : "Ů" U016E # LATIN CAPITAL LETTER U WITH RING ABOVE : "Ů" U016E # LATIN CAPITAL LETTER U WITH RING ABOVE : "ů" U016F # LATIN SMALL LETTER U WITH RING ABOVE : "ů" U016F # LATIN SMALL LETTER U WITH RING ABOVE : "ů" U016F # LATIN SMALL LETTER U WITH RING ABOVE : "ů" U016F # LATIN SMALL LETTER U WITH RING ABOVE : "Ű" U0170 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE : "Ű" U0170 # LATIN CAPITAL LETTER U WITH DOUBLE ACUTE : "ű" U0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE : "ű" U0171 # LATIN SMALL LETTER U WITH DOUBLE ACUTE : "Ų" U0172 # LATIN CAPITAL LETTER U WITH OGONEK : "Ų" U0172 # LATIN CAPITAL LETTER U WITH OGONEK : "Ų" U0172 # LATIN CAPITAL LETTER U WITH OGONEK : "Ų" U0172 # LATIN CAPITAL LETTER U WITH OGONEK : "ų" U0173 # LATIN SMALL LETTER U WITH OGONEK : "ų" U0173 # LATIN SMALL LETTER U WITH OGONEK : "ų" U0173 # LATIN SMALL LETTER U WITH OGONEK : "ų" U0173 # LATIN SMALL LETTER U WITH OGONEK : "Ŵ" U0174 # LATIN CAPITAL LETTER W WITH CIRCUMFLEX : "Ŵ" U0174 # LATIN CAPITAL LETTER W WITH CIRCUMFLEX : "Ŵ" U0174 # LATIN CAPITAL LETTER W WITH CIRCUMFLEX : "ŵ" U0175 # LATIN SMALL LETTER W WITH CIRCUMFLEX : "ŵ" U0175 # LATIN SMALL LETTER W WITH CIRCUMFLEX : "ŵ" U0175 # LATIN SMALL LETTER W WITH CIRCUMFLEX : "Ŷ" U0176 # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX : "Ŷ" U0176 # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX : "Ŷ" U0176 # LATIN CAPITAL LETTER Y WITH CIRCUMFLEX : "ŷ" U0177 # LATIN SMALL LETTER Y WITH CIRCUMFLEX : "ŷ" U0177 # LATIN SMALL LETTER Y WITH CIRCUMFLEX : "ŷ" U0177 # LATIN SMALL LETTER Y WITH CIRCUMFLEX : "Ÿ" U0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS : "Ÿ" U0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS : "Ÿ" U0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS : "Ÿ" U0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS : "Ÿ" U0178 # LATIN CAPITAL LETTER Y WITH DIAERESIS : "Ź" U0179 # LATIN CAPITAL LETTER Z WITH ACUTE : "Ź" U0179 # LATIN CAPITAL LETTER Z WITH ACUTE : "Ź" U0179 # LATIN CAPITAL LETTER Z WITH ACUTE : "Ź" U0179 # LATIN CAPITAL LETTER Z WITH ACUTE : "ź" U017A # LATIN SMALL LETTER Z WITH ACUTE : "ź" U017A # LATIN SMALL LETTER Z WITH ACUTE : "ź" U017A # LATIN SMALL LETTER Z WITH ACUTE : "ź" U017A # LATIN SMALL LETTER Z WITH ACUTE : "Ż" U017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE : "Ż" U017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE : "Ż" U017B # LATIN CAPITAL LETTER Z WITH DOT ABOVE : "ż" U017C # LATIN SMALL LETTER Z WITH DOT ABOVE : "ż" U017C # LATIN SMALL LETTER Z WITH DOT ABOVE : "ż" U017C # LATIN SMALL LETTER Z WITH DOT ABOVE : "Ž" U017D # LATIN CAPITAL LETTER Z WITH CARON : "Ž" U017D # LATIN CAPITAL LETTER Z WITH CARON : "Ž" U017D # LATIN CAPITAL LETTER Z WITH CARON : "Ž" U017D # LATIN CAPITAL LETTER Z WITH CARON : "Ž" U017D # LATIN CAPITAL LETTER Z WITH CARON : "ž" U017E # LATIN SMALL LETTER Z WITH CARON : "ž" U017E # LATIN SMALL LETTER Z WITH CARON : "ž" U017E # LATIN SMALL LETTER Z WITH CARON : "ž" U017E # LATIN SMALL LETTER Z WITH CARON : "ž" U017E # LATIN SMALL LETTER Z WITH CARON : "ƀ" U0180 # LATIN SMALL LETTER B WITH STROKE : "ƀ" U0180 # LATIN SMALL LETTER B WITH STROKE : "ƀ" U0180 # LATIN SMALL LETTER B WITH STROKE : "Ɨ" U0197 # LATIN CAPITAL LETTER I WITH STROKE : "Ɨ" U0197 # LATIN CAPITAL LETTER I WITH STROKE : "Ɨ" U0197 # LATIN CAPITAL LETTER I WITH STROKE : "Ơ" U01A0 # LATIN CAPITAL LETTER O WITH HORN : "Ơ" U01A0 # LATIN CAPITAL LETTER O WITH HORN : "ơ" U01A1 # LATIN SMALL LETTER O WITH HORN : "ơ" U01A1 # LATIN SMALL LETTER O WITH HORN : "Ư" U01AF # LATIN CAPITAL LETTER U WITH HORN : "Ư" U01AF # LATIN CAPITAL LETTER U WITH HORN : "ư" U01B0 # LATIN SMALL LETTER U WITH HORN : "ư" U01B0 # LATIN SMALL LETTER U WITH HORN : "Ƶ" U01B5 # LATIN CAPITAL LETTER Z WITH STROKE : "Ƶ" U01B5 # LATIN CAPITAL LETTER Z WITH STROKE : "Ƶ" U01B5 # LATIN CAPITAL LETTER Z WITH STROKE : "ƶ" U01B6 # LATIN SMALL LETTER Z WITH STROKE : "ƶ" U01B6 # LATIN SMALL LETTER Z WITH STROKE : "ƶ" U01B6 # LATIN SMALL LETTER Z WITH STROKE : "Ǎ" U01CD # LATIN CAPITAL LETTER A WITH CARON : "Ǎ" U01CD # LATIN CAPITAL LETTER A WITH CARON : "ǎ" U01CE # LATIN SMALL LETTER A WITH CARON : "ǎ" U01CE # LATIN SMALL LETTER A WITH CARON : "Ǐ" U01CF # LATIN CAPITAL LETTER I WITH CARON : "Ǐ" U01CF # LATIN CAPITAL LETTER I WITH CARON : "ǐ" U01D0 # LATIN SMALL LETTER I WITH CARON : "ǐ" U01D0 # LATIN SMALL LETTER I WITH CARON : "Ǒ" U01D1 # LATIN CAPITAL LETTER O WITH CARON : "Ǒ" U01D1 # LATIN CAPITAL LETTER O WITH CARON : "ǒ" U01D2 # LATIN SMALL LETTER O WITH CARON : "ǒ" U01D2 # LATIN SMALL LETTER O WITH CARON : "Ǔ" U01D3 # LATIN CAPITAL LETTER U WITH CARON : "Ǔ" U01D3 # LATIN CAPITAL LETTER U WITH CARON : "ǔ" U01D4 # LATIN SMALL LETTER U WITH CARON : "ǔ" U01D4 # LATIN SMALL LETTER U WITH CARON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "Ǣ" U01E2 # LATIN CAPITAL LETTER AE WITH MACRON : "Ǣ" U01E2 # LATIN CAPITAL LETTER AE WITH MACRON : "Ǣ" U01E2 # LATIN CAPITAL LETTER AE WITH MACRON : "ǣ" U01E3 # LATIN SMALL LETTER AE WITH MACRON : "ǣ" U01E3 # LATIN SMALL LETTER AE WITH MACRON : "ǣ" U01E3 # LATIN SMALL LETTER AE WITH MACRON : "Ǥ" U01E4 # LATIN CAPITAL LETTER G WITH STROKE : "Ǥ" U01E4 # LATIN CAPITAL LETTER G WITH STROKE : "Ǥ" U01E4 # LATIN CAPITAL LETTER G WITH STROKE : "ǥ" U01E5 # LATIN SMALL LETTER G WITH STROKE : "ǥ" U01E5 # LATIN SMALL LETTER G WITH STROKE : "ǥ" U01E5 # LATIN SMALL LETTER G WITH STROKE : "Ǧ" U01E6 # LATIN CAPITAL LETTER G WITH CARON : "Ǧ" U01E6 # LATIN CAPITAL LETTER G WITH CARON : "ǧ" U01E7 # LATIN SMALL LETTER G WITH CARON : "ǧ" U01E7 # LATIN SMALL LETTER G WITH CARON : "Ǩ" U01E8 # LATIN CAPITAL LETTER K WITH CARON : "Ǩ" U01E8 # LATIN CAPITAL LETTER K WITH CARON : "ǩ" U01E9 # LATIN SMALL LETTER K WITH CARON : "ǩ" U01E9 # LATIN SMALL LETTER K WITH CARON : "Ǫ" U01EA # LATIN CAPITAL LETTER O WITH OGONEK : "Ǫ" U01EA # LATIN CAPITAL LETTER O WITH OGONEK : "ǫ" U01EB # LATIN SMALL LETTER O WITH OGONEK : "ǫ" U01EB # LATIN SMALL LETTER O WITH OGONEK : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "Ǯ" U01EE # LATIN CAPITAL LETTER EZH WITH CARON : "Ǯ" U01EE # LATIN CAPITAL LETTER EZH WITH CARON : "ǯ" U01EF # LATIN SMALL LETTER EZH WITH CARON : "ǯ" U01EF # LATIN SMALL LETTER EZH WITH CARON : "ǰ" U01F0 # LATIN SMALL LETTER J WITH CARON : "ǰ" U01F0 # LATIN SMALL LETTER J WITH CARON : "Ǵ" U01F4 # LATIN CAPITAL LETTER G WITH ACUTE : "Ǵ" U01F4 # LATIN CAPITAL LETTER G WITH ACUTE : "Ǵ" U01F4 # LATIN CAPITAL LETTER G WITH ACUTE : "ǵ" U01F5 # LATIN SMALL LETTER G WITH ACUTE : "ǵ" U01F5 # LATIN SMALL LETTER G WITH ACUTE : "ǵ" U01F5 # LATIN SMALL LETTER G WITH ACUTE : "Ǹ" U01F8 # LATIN CAPITAL LETTER N WITH GRAVE : "Ǹ" U01F8 # LATIN CAPITAL LETTER N WITH GRAVE : "ǹ" U01F9 # LATIN SMALL LETTER N WITH GRAVE : "ǹ" U01F9 # LATIN SMALL LETTER N WITH GRAVE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "Ǽ" U01FC # LATIN CAPITAL LETTER AE WITH ACUTE : "Ǽ" U01FC # LATIN CAPITAL LETTER AE WITH ACUTE : "Ǽ" U01FC # LATIN CAPITAL LETTER AE WITH ACUTE : "ǽ" U01FD # LATIN SMALL LETTER AE WITH ACUTE : "ǽ" U01FD # LATIN SMALL LETTER AE WITH ACUTE : "ǽ" U01FD # LATIN SMALL LETTER AE WITH ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE : "Ȁ" U0200 # LATIN CAPITAL LETTER A WITH DOUBLE GRAVE : "ȁ" U0201 # LATIN SMALL LETTER A WITH DOUBLE GRAVE : "Ȃ" U0202 # LATIN CAPITAL LETTER A WITH INVERTED BREVE : "ȃ" U0203 # LATIN SMALL LETTER A WITH INVERTED BREVE : "Ȅ" U0204 # LATIN CAPITAL LETTER E WITH DOUBLE GRAVE : "ȅ" U0205 # LATIN SMALL LETTER E WITH DOUBLE GRAVE : "Ȇ" U0206 # LATIN CAPITAL LETTER E WITH INVERTED BREVE : "ȇ" U0207 # LATIN SMALL LETTER E WITH INVERTED BREVE : "Ȉ" U0208 # LATIN CAPITAL LETTER I WITH DOUBLE GRAVE : "ȉ" U0209 # LATIN SMALL LETTER I WITH DOUBLE GRAVE : "Ȋ" U020A # LATIN CAPITAL LETTER I WITH INVERTED BREVE : "ȋ" U020B # LATIN SMALL LETTER I WITH INVERTED BREVE : "Ȍ" U020C # LATIN CAPITAL LETTER O WITH DOUBLE GRAVE : "ȍ" U020D # LATIN SMALL LETTER O WITH DOUBLE GRAVE : "Ȏ" U020E # LATIN CAPITAL LETTER O WITH INVERTED BREVE : "ȏ" U020F # LATIN SMALL LETTER O WITH INVERTED BREVE : "Ȑ" U0210 # LATIN CAPITAL LETTER R WITH DOUBLE GRAVE : "ȑ" U0211 # LATIN SMALL LETTER R WITH DOUBLE GRAVE : "Ȓ" U0212 # LATIN CAPITAL LETTER R WITH INVERTED BREVE : "ȓ" U0213 # LATIN SMALL LETTER R WITH INVERTED BREVE : "Ȕ" U0214 # LATIN CAPITAL LETTER U WITH DOUBLE GRAVE : "ȕ" U0215 # LATIN SMALL LETTER U WITH DOUBLE GRAVE : "Ȗ" U0216 # LATIN CAPITAL LETTER U WITH INVERTED BREVE : "ȗ" U0217 # LATIN SMALL LETTER U WITH INVERTED BREVE : "Ȟ" U021E # LATIN CAPITAL LETTER H WITH CARON : "Ȟ" U021E # LATIN CAPITAL LETTER H WITH CARON : "ȟ" U021F # LATIN SMALL LETTER H WITH CARON : "ȟ" U021F # LATIN SMALL LETTER H WITH CARON : "Ȧ" U0226 # LATIN CAPITAL LETTER A WITH DOT ABOVE : "Ȧ" U0226 # LATIN CAPITAL LETTER A WITH DOT ABOVE : "ȧ" U0227 # LATIN SMALL LETTER A WITH DOT ABOVE : "ȧ" U0227 # LATIN SMALL LETTER A WITH DOT ABOVE : "Ȩ" U0228 # LATIN CAPITAL LETTER E WITH CEDILLA : "Ȩ" U0228 # LATIN CAPITAL LETTER E WITH CEDILLA : "ȩ" U0229 # LATIN SMALL LETTER E WITH CEDILLA : "ȩ" U0229 # LATIN SMALL LETTER E WITH CEDILLA : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "Ȯ" U022E # LATIN CAPITAL LETTER O WITH DOT ABOVE : "Ȯ" U022E # LATIN CAPITAL LETTER O WITH DOT ABOVE : "ȯ" U022F # LATIN SMALL LETTER O WITH DOT ABOVE : "ȯ" U022F # LATIN SMALL LETTER O WITH DOT ABOVE : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "Ȳ" U0232 # LATIN CAPITAL LETTER Y WITH MACRON : "Ȳ" U0232 # LATIN CAPITAL LETTER Y WITH MACRON : "Ȳ" U0232 # LATIN CAPITAL LETTER Y WITH MACRON : "ȳ" U0233 # LATIN SMALL LETTER Y WITH MACRON : "ȳ" U0233 # LATIN SMALL LETTER Y WITH MACRON : "ȳ" U0233 # LATIN SMALL LETTER Y WITH MACRON : "ə" U0259 # LATIN SMALL LETTER SCHWA : "ɨ" U0268 # LATIN SMALL LETTER I WITH STROKE : "ɨ" U0268 # LATIN SMALL LETTER I WITH STROKE : "ɨ" U0268 # LATIN SMALL LETTER I WITH STROKE : "ʡ" U02A1 # LATIN LETTER GLOTTAL STOP WITH STROKE : "ʡ" U02A1 # LATIN LETTER GLOTTAL STOP WITH STROKE : "ʰ" U02B0 # MODIFIER LETTER SMALL H : "ʰ" U02B0 # MODIFIER LETTER SMALL H : "ʱ" U02B1 # MODIFIER LETTER SMALL H WITH HOOK : "ʱ" U02B1 # MODIFIER LETTER SMALL H WITH HOOK : "ʲ" U02B2 # MODIFIER LETTER SMALL J : "ʲ" U02B2 # MODIFIER LETTER SMALL J : "ʳ" U02B3 # MODIFIER LETTER SMALL R : "ʳ" U02B3 # MODIFIER LETTER SMALL R : "ʴ" U02B4 # MODIFIER LETTER SMALL TURNED R : "ʴ" U02B4 # MODIFIER LETTER SMALL TURNED R : "ʵ" U02B5 # MODIFIER LETTER SMALL TURNED R WITH HOOK : "ʵ" U02B5 # MODIFIER LETTER SMALL TURNED R WITH HOOK : "ʶ" U02B6 # MODIFIER LETTER SMALL CAPITAL INVERTED R : "ʶ" U02B6 # MODIFIER LETTER SMALL CAPITAL INVERTED R : "ʷ" U02B7 # MODIFIER LETTER SMALL W : "ʷ" U02B7 # MODIFIER LETTER SMALL W : "ʸ" U02B8 # MODIFIER LETTER SMALL Y : "ʸ" U02B8 # MODIFIER LETTER SMALL Y : "ˠ" U02E0 # MODIFIER LETTER SMALL GAMMA : "ˠ" U02E0 # MODIFIER LETTER SMALL GAMMA : "ˡ" U02E1 # MODIFIER LETTER SMALL L : "ˡ" U02E1 # MODIFIER LETTER SMALL L : "ˢ" U02E2 # MODIFIER LETTER SMALL S : "ˢ" U02E2 # MODIFIER LETTER SMALL S : "ˣ" U02E3 # MODIFIER LETTER SMALL X : "ˣ" U02E3 # MODIFIER LETTER SMALL X : "ˤ" U02E4 # MODIFIER LETTER SMALL REVERSED GLOTTAL STOP : "ˤ" U02E4 # MODIFIER LETTER SMALL REVERSED GLOTTAL STOP : "̈́" U0344 # COMBINING GREEK DIALYTIKA TONOS : "̈́" U0344 # COMBINING GREEK DIALYTIKA TONOS : "̈́" U0344 # COMBINING GREEK DIALYTIKA TONOS : "̈́" U0344 # COMBINING GREEK DIALYTIKA TONOS : "̈́" U0344 # COMBINING GREEK DIALYTIKA TONOS : "΅" U0385 # GREEK DIALYTIKA TONOS : "΅" U0385 # GREEK DIALYTIKA TONOS : "΅" U0385 # GREEK DIALYTIKA TONOS : "΅" U0385 # GREEK DIALYTIKA TONOS : "΅" U0385 # GREEK DIALYTIKA TONOS : "΅" U0385 # GREEK DIALYTIKA TONOS : "Ά" U0386 # GREEK CAPITAL LETTER ALPHA WITH TONOS : "Ά" U0386 # GREEK CAPITAL LETTER ALPHA WITH TONOS : "Ά" U0386 # GREEK CAPITAL LETTER ALPHA WITH TONOS : "Ά" U0386 # GREEK CAPITAL LETTER ALPHA WITH TONOS : "Έ" U0388 # GREEK CAPITAL LETTER EPSILON WITH TONOS : "Έ" U0388 # GREEK CAPITAL LETTER EPSILON WITH TONOS : "Έ" U0388 # GREEK CAPITAL LETTER EPSILON WITH TONOS : "Έ" U0388 # GREEK CAPITAL LETTER EPSILON WITH TONOS : "Ή" U0389 # GREEK CAPITAL LETTER ETA WITH TONOS : "Ή" U0389 # GREEK CAPITAL LETTER ETA WITH TONOS : "Ή" U0389 # GREEK CAPITAL LETTER ETA WITH TONOS : "Ή" U0389 # GREEK CAPITAL LETTER ETA WITH TONOS : "Ί" U038A # GREEK CAPITAL LETTER IOTA WITH TONOS : "Ί" U038A # GREEK CAPITAL LETTER IOTA WITH TONOS : "Ί" U038A # GREEK CAPITAL LETTER IOTA WITH TONOS : "Ί" U038A # GREEK CAPITAL LETTER IOTA WITH TONOS : "Ό" U038C # GREEK CAPITAL LETTER OMICRON WITH TONOS : "Ό" U038C # GREEK CAPITAL LETTER OMICRON WITH TONOS : "Ό" U038C # GREEK CAPITAL LETTER OMICRON WITH TONOS : "Ό" U038C # GREEK CAPITAL LETTER OMICRON WITH TONOS : "Ύ" U038E # GREEK CAPITAL LETTER UPSILON WITH TONOS : "Ύ" U038E # GREEK CAPITAL LETTER UPSILON WITH TONOS : "Ύ" U038E # GREEK CAPITAL LETTER UPSILON WITH TONOS : "Ύ" U038E # GREEK CAPITAL LETTER UPSILON WITH TONOS : "Ώ" U038F # GREEK CAPITAL LETTER OMEGA WITH TONOS : "Ώ" U038F # GREEK CAPITAL LETTER OMEGA WITH TONOS : "Ώ" U038F # GREEK CAPITAL LETTER OMEGA WITH TONOS : "Ώ" U038F # GREEK CAPITAL LETTER OMEGA WITH TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "ΐ" U0390 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS : "Ϊ" U03AA # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA : "Ϊ" U03AA # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA : "Ϊ" U03AA # GREEK CAPITAL LETTER IOTA WITH DIALYTIKA : "Ϋ" U03AB # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA : "Ϋ" U03AB # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA : "Ϋ" U03AB # GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA : "ά" U03AC # GREEK SMALL LETTER ALPHA WITH TONOS : "ά" U03AC # GREEK SMALL LETTER ALPHA WITH TONOS : "ά" U03AC # GREEK SMALL LETTER ALPHA WITH TONOS : "ά" U03AC # GREEK SMALL LETTER ALPHA WITH TONOS : "έ" U03AD # GREEK SMALL LETTER EPSILON WITH TONOS : "έ" U03AD # GREEK SMALL LETTER EPSILON WITH TONOS : "έ" U03AD # GREEK SMALL LETTER EPSILON WITH TONOS : "έ" U03AD # GREEK SMALL LETTER EPSILON WITH TONOS : "ή" U03AE # GREEK SMALL LETTER ETA WITH TONOS : "ή" U03AE # GREEK SMALL LETTER ETA WITH TONOS : "ή" U03AE # GREEK SMALL LETTER ETA WITH TONOS : "ή" U03AE # GREEK SMALL LETTER ETA WITH TONOS : "ί" U03AF # GREEK SMALL LETTER IOTA WITH TONOS : "ί" U03AF # GREEK SMALL LETTER IOTA WITH TONOS : "ί" U03AF # GREEK SMALL LETTER IOTA WITH TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ΰ" U03B0 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS : "ϊ" U03CA # GREEK SMALL LETTER IOTA WITH DIALYTIKA : "ϊ" U03CA # GREEK SMALL LETTER IOTA WITH DIALYTIKA : "ϊ" U03CA # GREEK SMALL LETTER IOTA WITH DIALYTIKA : "ϋ" U03CB # GREEK SMALL LETTER UPSILON WITH DIALYTIKA : "ϋ" U03CB # GREEK SMALL LETTER UPSILON WITH DIALYTIKA : "ϋ" U03CB # GREEK SMALL LETTER UPSILON WITH DIALYTIKA : "ό" U03CC # GREEK SMALL LETTER OMICRON WITH TONOS : "ό" U03CC # GREEK SMALL LETTER OMICRON WITH TONOS : "ό" U03CC # GREEK SMALL LETTER OMICRON WITH TONOS : "ό" U03CC # GREEK SMALL LETTER OMICRON WITH TONOS : "ύ" U03CD # GREEK SMALL LETTER UPSILON WITH TONOS : "ύ" U03CD # GREEK SMALL LETTER UPSILON WITH TONOS : "ύ" U03CD # GREEK SMALL LETTER UPSILON WITH TONOS : "ύ" U03CD # GREEK SMALL LETTER UPSILON WITH TONOS : "ώ" U03CE # GREEK SMALL LETTER OMEGA WITH TONOS : "ώ" U03CE # GREEK SMALL LETTER OMEGA WITH TONOS : "ώ" U03CE # GREEK SMALL LETTER OMEGA WITH TONOS : "ώ" U03CE # GREEK SMALL LETTER OMEGA WITH TONOS : "ϔ" U03D4 # GREEK UPSILON WITH DIAERESIS AND HOOK SYMBOL : "Ѐ" U0400 # CYRILLIC CAPITAL LETTER IE WITH GRAVE : "Ѐ" U0400 # CYRILLIC CAPITAL LETTER IE WITH GRAVE : "Ё" U0401 # CYRILLIC CAPITAL LETTER IO : "Ё" U0401 # CYRILLIC CAPITAL LETTER IO : "Ѓ" U0403 # CYRILLIC CAPITAL LETTER GJE : "Ѓ" U0403 # CYRILLIC CAPITAL LETTER GJE : "Ѓ" U0403 # CYRILLIC CAPITAL LETTER GJE : "Ї" U0407 # CYRILLIC CAPITAL LETTER YI : "Ї" U0407 # CYRILLIC CAPITAL LETTER YI : "Ќ" U040C # CYRILLIC CAPITAL LETTER KJE : "Ќ" U040C # CYRILLIC CAPITAL LETTER KJE : "Ќ" U040C # CYRILLIC CAPITAL LETTER KJE : "Ѝ" U040D # CYRILLIC CAPITAL LETTER I WITH GRAVE : "Ѝ" U040D # CYRILLIC CAPITAL LETTER I WITH GRAVE : "Ў" U040E # CYRILLIC CAPITAL LETTER SHORT U : "Ў" U040E # CYRILLIC CAPITAL LETTER SHORT U : "Ў" U040E # CYRILLIC CAPITAL LETTER SHORT U : "Й" U0419 # CYRILLIC CAPITAL LETTER SHORT I : "Й" U0419 # CYRILLIC CAPITAL LETTER SHORT I : "Й" U0419 # CYRILLIC CAPITAL LETTER SHORT I : "й" U0439 # CYRILLIC SMALL LETTER SHORT I : "й" U0439 # CYRILLIC SMALL LETTER SHORT I : "й" U0439 # CYRILLIC SMALL LETTER SHORT I : "ѐ" U0450 # CYRILLIC SMALL LETTER IE WITH GRAVE : "ѐ" U0450 # CYRILLIC SMALL LETTER IE WITH GRAVE : "ё" U0451 # CYRILLIC SMALL LETTER IO : "ё" U0451 # CYRILLIC SMALL LETTER IO : "ѓ" U0453 # CYRILLIC SMALL LETTER GJE : "ѓ" U0453 # CYRILLIC SMALL LETTER GJE : "ѓ" U0453 # CYRILLIC SMALL LETTER GJE : "ї" U0457 # CYRILLIC SMALL LETTER YI : "ї" U0457 # CYRILLIC SMALL LETTER YI : "ќ" U045C # CYRILLIC SMALL LETTER KJE : "ќ" U045C # CYRILLIC SMALL LETTER KJE : "ќ" U045C # CYRILLIC SMALL LETTER KJE : "ѝ" U045D # CYRILLIC SMALL LETTER I WITH GRAVE : "ѝ" U045D # CYRILLIC SMALL LETTER I WITH GRAVE : "ў" U045E # CYRILLIC SMALL LETTER SHORT U : "ў" U045E # CYRILLIC SMALL LETTER SHORT U : "ў" U045E # CYRILLIC SMALL LETTER SHORT U : "Ѷ" U0476 # CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT : "ѷ" U0477 # CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT : "Ғ" U0492 # CYRILLIC CAPITAL LETTER GHE WITH STROKE : "Ғ" U0492 # CYRILLIC CAPITAL LETTER GHE WITH STROKE : "ғ" U0493 # CYRILLIC SMALL LETTER GHE WITH STROKE : "ғ" U0493 # CYRILLIC SMALL LETTER GHE WITH STROKE : "Ҟ" U049E # CYRILLIC CAPITAL LETTER KA WITH STROKE : "Ҟ" U049E # CYRILLIC CAPITAL LETTER KA WITH STROKE : "ҟ" U049F # CYRILLIC SMALL LETTER KA WITH STROKE : "ҟ" U049F # CYRILLIC SMALL LETTER KA WITH STROKE : "Ұ" U04B0 # CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE : "Ұ" U04B0 # CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE : "ұ" U04B1 # CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE : "ұ" U04B1 # CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE : "Ӂ" U04C1 # CYRILLIC CAPITAL LETTER ZHE WITH BREVE : "Ӂ" U04C1 # CYRILLIC CAPITAL LETTER ZHE WITH BREVE : "Ӂ" U04C1 # CYRILLIC CAPITAL LETTER ZHE WITH BREVE : "ӂ" U04C2 # CYRILLIC SMALL LETTER ZHE WITH BREVE : "ӂ" U04C2 # CYRILLIC SMALL LETTER ZHE WITH BREVE : "ӂ" U04C2 # CYRILLIC SMALL LETTER ZHE WITH BREVE : "Ӑ" U04D0 # CYRILLIC CAPITAL LETTER A WITH BREVE : "Ӑ" U04D0 # CYRILLIC CAPITAL LETTER A WITH BREVE : "Ӑ" U04D0 # CYRILLIC CAPITAL LETTER A WITH BREVE : "ӑ" U04D1 # CYRILLIC SMALL LETTER A WITH BREVE : "ӑ" U04D1 # CYRILLIC SMALL LETTER A WITH BREVE : "ӑ" U04D1 # CYRILLIC SMALL LETTER A WITH BREVE : "Ӓ" U04D2 # CYRILLIC CAPITAL LETTER A WITH DIAERESIS : "Ӓ" U04D2 # CYRILLIC CAPITAL LETTER A WITH DIAERESIS : "ӓ" U04D3 # CYRILLIC SMALL LETTER A WITH DIAERESIS : "ӓ" U04D3 # CYRILLIC SMALL LETTER A WITH DIAERESIS : "Ӗ" U04D6 # CYRILLIC CAPITAL LETTER IE WITH BREVE : "Ӗ" U04D6 # CYRILLIC CAPITAL LETTER IE WITH BREVE : "Ӗ" U04D6 # CYRILLIC CAPITAL LETTER IE WITH BREVE : "ӗ" U04D7 # CYRILLIC SMALL LETTER IE WITH BREVE : "ӗ" U04D7 # CYRILLIC SMALL LETTER IE WITH BREVE : "ӗ" U04D7 # CYRILLIC SMALL LETTER IE WITH BREVE : "Ӛ" U04DA # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS : "Ӛ" U04DA # CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS : "ӛ" U04DB # CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS : "ӛ" U04DB # CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS : "Ӝ" U04DC # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS : "Ӝ" U04DC # CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS : "ӝ" U04DD # CYRILLIC SMALL LETTER ZHE WITH DIAERESIS : "ӝ" U04DD # CYRILLIC SMALL LETTER ZHE WITH DIAERESIS : "Ӟ" U04DE # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS : "Ӟ" U04DE # CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS : "ӟ" U04DF # CYRILLIC SMALL LETTER ZE WITH DIAERESIS : "ӟ" U04DF # CYRILLIC SMALL LETTER ZE WITH DIAERESIS : "Ӣ" U04E2 # CYRILLIC CAPITAL LETTER I WITH MACRON : "Ӣ" U04E2 # CYRILLIC CAPITAL LETTER I WITH MACRON : "Ӣ" U04E2 # CYRILLIC CAPITAL LETTER I WITH MACRON : "ӣ" U04E3 # CYRILLIC SMALL LETTER I WITH MACRON : "ӣ" U04E3 # CYRILLIC SMALL LETTER I WITH MACRON : "ӣ" U04E3 # CYRILLIC SMALL LETTER I WITH MACRON : "Ӥ" U04E4 # CYRILLIC CAPITAL LETTER I WITH DIAERESIS : "Ӥ" U04E4 # CYRILLIC CAPITAL LETTER I WITH DIAERESIS : "ӥ" U04E5 # CYRILLIC SMALL LETTER I WITH DIAERESIS : "ӥ" U04E5 # CYRILLIC SMALL LETTER I WITH DIAERESIS : "Ӧ" U04E6 # CYRILLIC CAPITAL LETTER O WITH DIAERESIS : "Ӧ" U04E6 # CYRILLIC CAPITAL LETTER O WITH DIAERESIS : "ӧ" U04E7 # CYRILLIC SMALL LETTER O WITH DIAERESIS : "ӧ" U04E7 # CYRILLIC SMALL LETTER O WITH DIAERESIS : "Ӫ" U04EA # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS : "Ӫ" U04EA # CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS : "ӫ" U04EB # CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS : "ӫ" U04EB # CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS : "Ӭ" U04EC # CYRILLIC CAPITAL LETTER E WITH DIAERESIS : "Ӭ" U04EC # CYRILLIC CAPITAL LETTER E WITH DIAERESIS : "ӭ" U04ED # CYRILLIC SMALL LETTER E WITH DIAERESIS : "ӭ" U04ED # CYRILLIC SMALL LETTER E WITH DIAERESIS : "Ӯ" U04EE # CYRILLIC CAPITAL LETTER U WITH MACRON : "Ӯ" U04EE # CYRILLIC CAPITAL LETTER U WITH MACRON : "Ӯ" U04EE # CYRILLIC CAPITAL LETTER U WITH MACRON : "ӯ" U04EF # CYRILLIC SMALL LETTER U WITH MACRON : "ӯ" U04EF # CYRILLIC SMALL LETTER U WITH MACRON : "ӯ" U04EF # CYRILLIC SMALL LETTER U WITH MACRON : "Ӱ" U04F0 # CYRILLIC CAPITAL LETTER U WITH DIAERESIS : "Ӱ" U04F0 # CYRILLIC CAPITAL LETTER U WITH DIAERESIS : "ӱ" U04F1 # CYRILLIC SMALL LETTER U WITH DIAERESIS : "ӱ" U04F1 # CYRILLIC SMALL LETTER U WITH DIAERESIS : "Ӳ" U04F2 # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE : "Ӳ" U04F2 # CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE : "ӳ" U04F3 # CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE : "ӳ" U04F3 # CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE : "Ӵ" U04F4 # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS : "Ӵ" U04F4 # CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS : "ӵ" U04F5 # CYRILLIC SMALL LETTER CHE WITH DIAERESIS : "ӵ" U04F5 # CYRILLIC SMALL LETTER CHE WITH DIAERESIS : "Ӹ" U04F8 # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS : "Ӹ" U04F8 # CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS : "ӹ" U04F9 # CYRILLIC SMALL LETTER YERU WITH DIAERESIS : "ӹ" U04F9 # CYRILLIC SMALL LETTER YERU WITH DIAERESIS : "آ" U0622 # ARABIC LETTER ALEF WITH MADDA ABOVE : "أ" U0623 # ARABIC LETTER ALEF WITH HAMZA ABOVE : "ؤ" U0624 # ARABIC LETTER WAW WITH HAMZA ABOVE : "إ" U0625 # ARABIC LETTER ALEF WITH HAMZA BELOW : "ئ" U0626 # ARABIC LETTER YEH WITH HAMZA ABOVE : "ۀ" U06C0 # ARABIC LETTER HEH WITH YEH ABOVE : "ۂ" U06C2 # ARABIC LETTER HEH GOAL WITH HAMZA ABOVE : "ۓ" U06D3 # ARABIC LETTER YEH BARREE WITH HAMZA ABOVE : "ऩ" U0929 # DEVANAGARI LETTER NNNA : "ऱ" U0931 # DEVANAGARI LETTER RRA : "ऴ" U0934 # DEVANAGARI LETTER LLLA : "क़" U0958 # DEVANAGARI LETTER QA : "ख़" U0959 # DEVANAGARI LETTER KHHA : "ग़" U095A # DEVANAGARI LETTER GHHA : "ज़" U095B # DEVANAGARI LETTER ZA : "ड़" U095C # DEVANAGARI LETTER DDDHA : "ढ़" U095D # DEVANAGARI LETTER RHA : "फ़" U095E # DEVANAGARI LETTER FA : "य़" U095F # DEVANAGARI LETTER YYA : "ো" U09CB # BENGALI VOWEL SIGN O : "ৌ" U09CC # BENGALI VOWEL SIGN AU : "ড়" U09DC # BENGALI LETTER RRA : "ঢ়" U09DD # BENGALI LETTER RHA : "য়" U09DF # BENGALI LETTER YYA : "ਲ਼" U0A33 # GURMUKHI LETTER LLA : "ਸ਼" U0A36 # GURMUKHI LETTER SHA : "ਖ਼" U0A59 # GURMUKHI LETTER KHHA : "ਗ਼" U0A5A # GURMUKHI LETTER GHHA : "ਜ਼" U0A5B # GURMUKHI LETTER ZA : "ਫ਼" U0A5E # GURMUKHI LETTER FA : "ୈ" U0B48 # ORIYA VOWEL SIGN AI : "ୋ" U0B4B # ORIYA VOWEL SIGN O : "ୌ" U0B4C # ORIYA VOWEL SIGN AU : "ଡ଼" U0B5C # ORIYA LETTER RRA : "ଢ଼" U0B5D # ORIYA LETTER RHA : "ஔ" U0B94 # TAMIL LETTER AU : "ொ" U0BCA # TAMIL VOWEL SIGN O : "ோ" U0BCB # TAMIL VOWEL SIGN OO : "ௌ" U0BCC # TAMIL VOWEL SIGN AU : "ై" U0C48 # TELUGU VOWEL SIGN AI : "ೀ" U0CC0 # KANNADA VOWEL SIGN II : "ೇ" U0CC7 # KANNADA VOWEL SIGN EE : "ೈ" U0CC8 # KANNADA VOWEL SIGN AI : "ೊ" U0CCA # KANNADA VOWEL SIGN O : "ೋ" U0CCB # KANNADA VOWEL SIGN OO : "ൊ" U0D4A # MALAYALAM VOWEL SIGN O : "ോ" U0D4B # MALAYALAM VOWEL SIGN OO : "ൌ" U0D4C # MALAYALAM VOWEL SIGN AU : "ේ" U0DDA # SINHALA VOWEL SIGN DIGA KOMBUVA : "ො" U0DDC # SINHALA VOWEL SIGN KOMBUVA HAA AELA-PILLA : "ෝ" U0DDD # SINHALA VOWEL SIGN KOMBUVA HAA DIGA AELA-PILLA : "ෞ" U0DDE # SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA : "གྷ" U0F43 # TIBETAN LETTER GHA : "ཌྷ" U0F4D # TIBETAN LETTER DDHA : "དྷ" U0F52 # TIBETAN LETTER DHA : "བྷ" U0F57 # TIBETAN LETTER BHA : "ཛྷ" U0F5C # TIBETAN LETTER DZHA : "ཀྵ" U0F69 # TIBETAN LETTER KSSA : "ཱི" U0F73 # TIBETAN VOWEL SIGN II : "ཱུ" U0F75 # TIBETAN VOWEL SIGN UU : "ྲྀ" U0F76 # TIBETAN VOWEL SIGN VOCALIC R : "ླྀ" U0F78 # TIBETAN VOWEL SIGN VOCALIC L : "ཱྀ" U0F81 # TIBETAN VOWEL SIGN REVERSED II : "ྒྷ" U0F93 # TIBETAN SUBJOINED LETTER GHA : "ྜྷ" U0F9D # TIBETAN SUBJOINED LETTER DDHA : "ྡྷ" U0FA2 # TIBETAN SUBJOINED LETTER DHA : "ྦྷ" U0FA7 # TIBETAN SUBJOINED LETTER BHA : "ྫྷ" U0FAC # TIBETAN SUBJOINED LETTER DZHA : "ྐྵ" U0FB9 # TIBETAN SUBJOINED LETTER KSSA : "ဦ" U1026 # MYANMAR LETTER UU : "Ḁ" U1E00 # LATIN CAPITAL LETTER A WITH RING BELOW : "ḁ" U1E01 # LATIN SMALL LETTER A WITH RING BELOW : "Ḃ" U1E02 # LATIN CAPITAL LETTER B WITH DOT ABOVE : "Ḃ" U1E02 # LATIN CAPITAL LETTER B WITH DOT ABOVE : "Ḃ" U1E02 # LATIN CAPITAL LETTER B WITH DOT ABOVE : "ḃ" U1E03 # LATIN SMALL LETTER B WITH DOT ABOVE : "ḃ" U1E03 # LATIN SMALL LETTER B WITH DOT ABOVE : "ḃ" U1E03 # LATIN SMALL LETTER B WITH DOT ABOVE : "Ḅ" U1E04 # LATIN CAPITAL LETTER B WITH DOT BELOW : "Ḅ" U1E04 # LATIN CAPITAL LETTER B WITH DOT BELOW : "ḅ" U1E05 # LATIN SMALL LETTER B WITH DOT BELOW : "ḅ" U1E05 # LATIN SMALL LETTER B WITH DOT BELOW : "Ḇ" U1E06 # LATIN CAPITAL LETTER B WITH LINE BELOW : "ḇ" U1E07 # LATIN SMALL LETTER B WITH LINE BELOW : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "Ḋ" U1E0A # LATIN CAPITAL LETTER D WITH DOT ABOVE : "Ḋ" U1E0A # LATIN CAPITAL LETTER D WITH DOT ABOVE : "Ḋ" U1E0A # LATIN CAPITAL LETTER D WITH DOT ABOVE : "ḋ" U1E0B # LATIN SMALL LETTER D WITH DOT ABOVE : "ḋ" U1E0B # LATIN SMALL LETTER D WITH DOT ABOVE : "ḋ" U1E0B # LATIN SMALL LETTER D WITH DOT ABOVE : "Ḍ" U1E0C # LATIN CAPITAL LETTER D WITH DOT BELOW : "Ḍ" U1E0C # LATIN CAPITAL LETTER D WITH DOT BELOW : "ḍ" U1E0D # LATIN SMALL LETTER D WITH DOT BELOW : "ḍ" U1E0D # LATIN SMALL LETTER D WITH DOT BELOW : "Ḏ" U1E0E # LATIN CAPITAL LETTER D WITH LINE BELOW : "ḏ" U1E0F # LATIN SMALL LETTER D WITH LINE BELOW : "Ḑ" U1E10 # LATIN CAPITAL LETTER D WITH CEDILLA : "Ḑ" U1E10 # LATIN CAPITAL LETTER D WITH CEDILLA : "Ḑ" U1E10 # LATIN CAPITAL LETTER D WITH CEDILLA : "Ḑ" U1E10 # LATIN CAPITAL LETTER D WITH CEDILLA : "ḑ" U1E11 # LATIN SMALL LETTER D WITH CEDILLA : "ḑ" U1E11 # LATIN SMALL LETTER D WITH CEDILLA : "ḑ" U1E11 # LATIN SMALL LETTER D WITH CEDILLA : "ḑ" U1E11 # LATIN SMALL LETTER D WITH CEDILLA : "Ḓ" U1E12 # LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW : "ḓ" U1E13 # LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "Ḙ" U1E18 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW : "ḙ" U1E19 # LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW : "Ḛ" U1E1A # LATIN CAPITAL LETTER E WITH TILDE BELOW : "ḛ" U1E1B # LATIN SMALL LETTER E WITH TILDE BELOW : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "Ḟ" U1E1E # LATIN CAPITAL LETTER F WITH DOT ABOVE : "Ḟ" U1E1E # LATIN CAPITAL LETTER F WITH DOT ABOVE : "Ḟ" U1E1E # LATIN CAPITAL LETTER F WITH DOT ABOVE : "ḟ" U1E1F # LATIN SMALL LETTER F WITH DOT ABOVE : "ḟ" U1E1F # LATIN SMALL LETTER F WITH DOT ABOVE : "ḟ" U1E1F # LATIN SMALL LETTER F WITH DOT ABOVE : "Ḡ" U1E20 # LATIN CAPITAL LETTER G WITH MACRON : "Ḡ" U1E20 # LATIN CAPITAL LETTER G WITH MACRON : "Ḡ" U1E20 # LATIN CAPITAL LETTER G WITH MACRON : "ḡ" U1E21 # LATIN SMALL LETTER G WITH MACRON : "ḡ" U1E21 # LATIN SMALL LETTER G WITH MACRON : "ḡ" U1E21 # LATIN SMALL LETTER G WITH MACRON : "Ḣ" U1E22 # LATIN CAPITAL LETTER H WITH DOT ABOVE : "Ḣ" U1E22 # LATIN CAPITAL LETTER H WITH DOT ABOVE : "ḣ" U1E23 # LATIN SMALL LETTER H WITH DOT ABOVE : "ḣ" U1E23 # LATIN SMALL LETTER H WITH DOT ABOVE : "Ḥ" U1E24 # LATIN CAPITAL LETTER H WITH DOT BELOW : "Ḥ" U1E24 # LATIN CAPITAL LETTER H WITH DOT BELOW : "ḥ" U1E25 # LATIN SMALL LETTER H WITH DOT BELOW : "ḥ" U1E25 # LATIN SMALL LETTER H WITH DOT BELOW : "Ḧ" U1E26 # LATIN CAPITAL LETTER H WITH DIAERESIS : "Ḧ" U1E26 # LATIN CAPITAL LETTER H WITH DIAERESIS : "ḧ" U1E27 # LATIN SMALL LETTER H WITH DIAERESIS : "ḧ" U1E27 # LATIN SMALL LETTER H WITH DIAERESIS : "Ḩ" U1E28 # LATIN CAPITAL LETTER H WITH CEDILLA : "Ḩ" U1E28 # LATIN CAPITAL LETTER H WITH CEDILLA : "Ḩ" U1E28 # LATIN CAPITAL LETTER H WITH CEDILLA : "Ḩ" U1E28 # LATIN CAPITAL LETTER H WITH CEDILLA : "ḩ" U1E29 # LATIN SMALL LETTER H WITH CEDILLA : "ḩ" U1E29 # LATIN SMALL LETTER H WITH CEDILLA : "ḩ" U1E29 # LATIN SMALL LETTER H WITH CEDILLA : "ḩ" U1E29 # LATIN SMALL LETTER H WITH CEDILLA : "Ḫ" U1E2A # LATIN CAPITAL LETTER H WITH BREVE BELOW : "ḫ" U1E2B # LATIN SMALL LETTER H WITH BREVE BELOW : "Ḭ" U1E2C # LATIN CAPITAL LETTER I WITH TILDE BELOW : "ḭ" U1E2D # LATIN SMALL LETTER I WITH TILDE BELOW : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "Ḱ" U1E30 # LATIN CAPITAL LETTER K WITH ACUTE : "Ḱ" U1E30 # LATIN CAPITAL LETTER K WITH ACUTE : "Ḱ" U1E30 # LATIN CAPITAL LETTER K WITH ACUTE : "ḱ" U1E31 # LATIN SMALL LETTER K WITH ACUTE : "ḱ" U1E31 # LATIN SMALL LETTER K WITH ACUTE : "ḱ" U1E31 # LATIN SMALL LETTER K WITH ACUTE : "Ḳ" U1E32 # LATIN CAPITAL LETTER K WITH DOT BELOW : "Ḳ" U1E32 # LATIN CAPITAL LETTER K WITH DOT BELOW : "ḳ" U1E33 # LATIN SMALL LETTER K WITH DOT BELOW : "ḳ" U1E33 # LATIN SMALL LETTER K WITH DOT BELOW : "Ḵ" U1E34 # LATIN CAPITAL LETTER K WITH LINE BELOW : "ḵ" U1E35 # LATIN SMALL LETTER K WITH LINE BELOW : "Ḷ" U1E36 # LATIN CAPITAL LETTER L WITH DOT BELOW : "Ḷ" U1E36 # LATIN CAPITAL LETTER L WITH DOT BELOW : "ḷ" U1E37 # LATIN SMALL LETTER L WITH DOT BELOW : "ḷ" U1E37 # LATIN SMALL LETTER L WITH DOT BELOW : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "Ḻ" U1E3A # LATIN CAPITAL LETTER L WITH LINE BELOW : "ḻ" U1E3B # LATIN SMALL LETTER L WITH LINE BELOW : "Ḽ" U1E3C # LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW : "ḽ" U1E3D # LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW : "Ḿ" U1E3E # LATIN CAPITAL LETTER M WITH ACUTE : "Ḿ" U1E3E # LATIN CAPITAL LETTER M WITH ACUTE : "Ḿ" U1E3E # LATIN CAPITAL LETTER M WITH ACUTE : "ḿ" U1E3F # LATIN SMALL LETTER M WITH ACUTE : "ḿ" U1E3F # LATIN SMALL LETTER M WITH ACUTE : "ḿ" U1E3F # LATIN SMALL LETTER M WITH ACUTE : "Ṁ" U1E40 # LATIN CAPITAL LETTER M WITH DOT ABOVE : "Ṁ" U1E40 # LATIN CAPITAL LETTER M WITH DOT ABOVE : "Ṁ" U1E40 # LATIN CAPITAL LETTER M WITH DOT ABOVE : "ṁ" U1E41 # LATIN SMALL LETTER M WITH DOT ABOVE : "ṁ" U1E41 # LATIN SMALL LETTER M WITH DOT ABOVE : "ṁ" U1E41 # LATIN SMALL LETTER M WITH DOT ABOVE : "Ṃ" U1E42 # LATIN CAPITAL LETTER M WITH DOT BELOW : "Ṃ" U1E42 # LATIN CAPITAL LETTER M WITH DOT BELOW : "ṃ" U1E43 # LATIN SMALL LETTER M WITH DOT BELOW : "ṃ" U1E43 # LATIN SMALL LETTER M WITH DOT BELOW : "Ṅ" U1E44 # LATIN CAPITAL LETTER N WITH DOT ABOVE : "Ṅ" U1E44 # LATIN CAPITAL LETTER N WITH DOT ABOVE : "ṅ" U1E45 # LATIN SMALL LETTER N WITH DOT ABOVE : "ṅ" U1E45 # LATIN SMALL LETTER N WITH DOT ABOVE : "Ṇ" U1E46 # LATIN CAPITAL LETTER N WITH DOT BELOW : "Ṇ" U1E46 # LATIN CAPITAL LETTER N WITH DOT BELOW : "ṇ" U1E47 # LATIN SMALL LETTER N WITH DOT BELOW : "ṇ" U1E47 # LATIN SMALL LETTER N WITH DOT BELOW : "Ṉ" U1E48 # LATIN CAPITAL LETTER N WITH LINE BELOW : "ṉ" U1E49 # LATIN SMALL LETTER N WITH LINE BELOW : "Ṋ" U1E4A # LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW : "ṋ" U1E4B # LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "Ṏ" U1E4E # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS : "Ṏ" U1E4E # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS : "Ṏ" U1E4E # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS : "Ṏ" U1E4E # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS : "Ṏ" U1E4E # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS : "Ṏ" U1E4E # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS : "ṏ" U1E4F # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS : "ṏ" U1E4F # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS : "ṏ" U1E4F # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS : "ṏ" U1E4F # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS : "ṏ" U1E4F # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS : "ṏ" U1E4F # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE

: "Ṕ" U1E54 # LATIN CAPITAL LETTER P WITH ACUTE

: "Ṕ" U1E54 # LATIN CAPITAL LETTER P WITH ACUTE

: "Ṕ" U1E54 # LATIN CAPITAL LETTER P WITH ACUTE

: "ṕ" U1E55 # LATIN SMALL LETTER P WITH ACUTE

: "ṕ" U1E55 # LATIN SMALL LETTER P WITH ACUTE

: "ṕ" U1E55 # LATIN SMALL LETTER P WITH ACUTE

: "Ṗ" U1E56 # LATIN CAPITAL LETTER P WITH DOT ABOVE

: "Ṗ" U1E56 # LATIN CAPITAL LETTER P WITH DOT ABOVE

: "Ṗ" U1E56 # LATIN CAPITAL LETTER P WITH DOT ABOVE

: "ṗ" U1E57 # LATIN SMALL LETTER P WITH DOT ABOVE

: "ṗ" U1E57 # LATIN SMALL LETTER P WITH DOT ABOVE

: "ṗ" U1E57 # LATIN SMALL LETTER P WITH DOT ABOVE : "Ṙ" U1E58 # LATIN CAPITAL LETTER R WITH DOT ABOVE : "Ṙ" U1E58 # LATIN CAPITAL LETTER R WITH DOT ABOVE : "ṙ" U1E59 # LATIN SMALL LETTER R WITH DOT ABOVE : "ṙ" U1E59 # LATIN SMALL LETTER R WITH DOT ABOVE : "Ṛ" U1E5A # LATIN CAPITAL LETTER R WITH DOT BELOW : "Ṛ" U1E5A # LATIN CAPITAL LETTER R WITH DOT BELOW : "ṛ" U1E5B # LATIN SMALL LETTER R WITH DOT BELOW : "ṛ" U1E5B # LATIN SMALL LETTER R WITH DOT BELOW : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "Ṟ" U1E5E # LATIN CAPITAL LETTER R WITH LINE BELOW : "ṟ" U1E5F # LATIN SMALL LETTER R WITH LINE BELOW : "Ṡ" U1E60 # LATIN CAPITAL LETTER S WITH DOT ABOVE : "Ṡ" U1E60 # LATIN CAPITAL LETTER S WITH DOT ABOVE : "Ṡ" U1E60 # LATIN CAPITAL LETTER S WITH DOT ABOVE : "ṡ" U1E61 # LATIN SMALL LETTER S WITH DOT ABOVE : "ṡ" U1E61 # LATIN SMALL LETTER S WITH DOT ABOVE : "ṡ" U1E61 # LATIN SMALL LETTER S WITH DOT ABOVE : "Ṣ" U1E62 # LATIN CAPITAL LETTER S WITH DOT BELOW : "Ṣ" U1E62 # LATIN CAPITAL LETTER S WITH DOT BELOW : "ṣ" U1E63 # LATIN SMALL LETTER S WITH DOT BELOW : "ṣ" U1E63 # LATIN SMALL LETTER S WITH DOT BELOW : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "Ṧ" U1E66 # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE : "Ṧ" U1E66 # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE : "Ṧ" U1E66 # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE : "Ṧ" U1E66 # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE : "Ṧ" U1E66 # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE : "ṧ" U1E67 # LATIN SMALL LETTER S WITH CARON AND DOT ABOVE : "ṧ" U1E67 # LATIN SMALL LETTER S WITH CARON AND DOT ABOVE : "ṧ" U1E67 # LATIN SMALL LETTER S WITH CARON AND DOT ABOVE : "ṧ" U1E67 # LATIN SMALL LETTER S WITH CARON AND DOT ABOVE : "ṧ" U1E67 # LATIN SMALL LETTER S WITH CARON AND DOT ABOVE : "Ṩ" U1E68 # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE : "Ṩ" U1E68 # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE : "Ṩ" U1E68 # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE : "Ṩ" U1E68 # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE : "Ṩ" U1E68 # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE : "Ṩ" U1E68 # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE : "ṩ" U1E69 # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE : "ṩ" U1E69 # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE : "ṩ" U1E69 # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE : "ṩ" U1E69 # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE : "ṩ" U1E69 # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE : "ṩ" U1E69 # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE : "Ṫ" U1E6A # LATIN CAPITAL LETTER T WITH DOT ABOVE : "Ṫ" U1E6A # LATIN CAPITAL LETTER T WITH DOT ABOVE : "Ṫ" U1E6A # LATIN CAPITAL LETTER T WITH DOT ABOVE : "ṫ" U1E6B # LATIN SMALL LETTER T WITH DOT ABOVE : "ṫ" U1E6B # LATIN SMALL LETTER T WITH DOT ABOVE : "ṫ" U1E6B # LATIN SMALL LETTER T WITH DOT ABOVE : "Ṭ" U1E6C # LATIN CAPITAL LETTER T WITH DOT BELOW : "Ṭ" U1E6C # LATIN CAPITAL LETTER T WITH DOT BELOW : "ṭ" U1E6D # LATIN SMALL LETTER T WITH DOT BELOW : "ṭ" U1E6D # LATIN SMALL LETTER T WITH DOT BELOW : "Ṯ" U1E6E # LATIN CAPITAL LETTER T WITH LINE BELOW : "ṯ" U1E6F # LATIN SMALL LETTER T WITH LINE BELOW : "Ṱ" U1E70 # LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW : "ṱ" U1E71 # LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW : "Ṳ" U1E72 # LATIN CAPITAL LETTER U WITH DIAERESIS BELOW : "ṳ" U1E73 # LATIN SMALL LETTER U WITH DIAERESIS BELOW : "Ṵ" U1E74 # LATIN CAPITAL LETTER U WITH TILDE BELOW : "ṵ" U1E75 # LATIN SMALL LETTER U WITH TILDE BELOW : "Ṷ" U1E76 # LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW : "ṷ" U1E77 # LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "Ṻ" U1E7A # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS : "Ṻ" U1E7A # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS : "Ṻ" U1E7A # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS : "Ṻ" U1E7A # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS : "Ṻ" U1E7A # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS : "Ṻ" U1E7A # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS : "Ṻ" U1E7A # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS : "Ṻ" U1E7A # LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS : "ṻ" U1E7B # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS : "ṻ" U1E7B # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS : "ṻ" U1E7B # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS : "ṻ" U1E7B # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS : "ṻ" U1E7B # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS : "ṻ" U1E7B # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS : "ṻ" U1E7B # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS : "ṻ" U1E7B # LATIN SMALL LETTER U WITH MACRON AND DIAERESIS : "Ṽ" U1E7C # LATIN CAPITAL LETTER V WITH TILDE : "Ṽ" U1E7C # LATIN CAPITAL LETTER V WITH TILDE : "ṽ" U1E7D # LATIN SMALL LETTER V WITH TILDE : "ṽ" U1E7D # LATIN SMALL LETTER V WITH TILDE : "Ṿ" U1E7E # LATIN CAPITAL LETTER V WITH DOT BELOW : "Ṿ" U1E7E # LATIN CAPITAL LETTER V WITH DOT BELOW : "ṿ" U1E7F # LATIN SMALL LETTER V WITH DOT BELOW : "ṿ" U1E7F # LATIN SMALL LETTER V WITH DOT BELOW : "Ẁ" U1E80 # LATIN CAPITAL LETTER W WITH GRAVE : "Ẁ" U1E80 # LATIN CAPITAL LETTER W WITH GRAVE : "ẁ" U1E81 # LATIN SMALL LETTER W WITH GRAVE : "ẁ" U1E81 # LATIN SMALL LETTER W WITH GRAVE : "Ẃ" U1E82 # LATIN CAPITAL LETTER W WITH ACUTE : "Ẃ" U1E82 # LATIN CAPITAL LETTER W WITH ACUTE : "Ẃ" U1E82 # LATIN CAPITAL LETTER W WITH ACUTE : "ẃ" U1E83 # LATIN SMALL LETTER W WITH ACUTE : "ẃ" U1E83 # LATIN SMALL LETTER W WITH ACUTE : "ẃ" U1E83 # LATIN SMALL LETTER W WITH ACUTE : "Ẅ" U1E84 # LATIN CAPITAL LETTER W WITH DIAERESIS : "Ẅ" U1E84 # LATIN CAPITAL LETTER W WITH DIAERESIS : "ẅ" U1E85 # LATIN SMALL LETTER W WITH DIAERESIS : "ẅ" U1E85 # LATIN SMALL LETTER W WITH DIAERESIS : "Ẇ" U1E86 # LATIN CAPITAL LETTER W WITH DOT ABOVE : "Ẇ" U1E86 # LATIN CAPITAL LETTER W WITH DOT ABOVE : "ẇ" U1E87 # LATIN SMALL LETTER W WITH DOT ABOVE : "ẇ" U1E87 # LATIN SMALL LETTER W WITH DOT ABOVE : "Ẉ" U1E88 # LATIN CAPITAL LETTER W WITH DOT BELOW : "Ẉ" U1E88 # LATIN CAPITAL LETTER W WITH DOT BELOW : "ẉ" U1E89 # LATIN SMALL LETTER W WITH DOT BELOW : "ẉ" U1E89 # LATIN SMALL LETTER W WITH DOT BELOW : "Ẋ" U1E8A # LATIN CAPITAL LETTER X WITH DOT ABOVE : "Ẋ" U1E8A # LATIN CAPITAL LETTER X WITH DOT ABOVE : "ẋ" U1E8B # LATIN SMALL LETTER X WITH DOT ABOVE : "ẋ" U1E8B # LATIN SMALL LETTER X WITH DOT ABOVE : "Ẍ" U1E8C # LATIN CAPITAL LETTER X WITH DIAERESIS : "Ẍ" U1E8C # LATIN CAPITAL LETTER X WITH DIAERESIS : "ẍ" U1E8D # LATIN SMALL LETTER X WITH DIAERESIS : "ẍ" U1E8D # LATIN SMALL LETTER X WITH DIAERESIS : "Ẏ" U1E8E # LATIN CAPITAL LETTER Y WITH DOT ABOVE : "Ẏ" U1E8E # LATIN CAPITAL LETTER Y WITH DOT ABOVE : "ẏ" U1E8F # LATIN SMALL LETTER Y WITH DOT ABOVE : "ẏ" U1E8F # LATIN SMALL LETTER Y WITH DOT ABOVE : "Ẑ" U1E90 # LATIN CAPITAL LETTER Z WITH CIRCUMFLEX : "Ẑ" U1E90 # LATIN CAPITAL LETTER Z WITH CIRCUMFLEX : "ẑ" U1E91 # LATIN SMALL LETTER Z WITH CIRCUMFLEX : "ẑ" U1E91 # LATIN SMALL LETTER Z WITH CIRCUMFLEX : "Ẓ" U1E92 # LATIN CAPITAL LETTER Z WITH DOT BELOW : "Ẓ" U1E92 # LATIN CAPITAL LETTER Z WITH DOT BELOW : "ẓ" U1E93 # LATIN SMALL LETTER Z WITH DOT BELOW : "ẓ" U1E93 # LATIN SMALL LETTER Z WITH DOT BELOW : "Ẕ" U1E94 # LATIN CAPITAL LETTER Z WITH LINE BELOW : "ẕ" U1E95 # LATIN SMALL LETTER Z WITH LINE BELOW : "ẖ" U1E96 # LATIN SMALL LETTER H WITH LINE BELOW : "ẗ" U1E97 # LATIN SMALL LETTER T WITH DIAERESIS : "ẗ" U1E97 # LATIN SMALL LETTER T WITH DIAERESIS : "ẘ" U1E98 # LATIN SMALL LETTER W WITH RING ABOVE : "ẘ" U1E98 # LATIN SMALL LETTER W WITH RING ABOVE : "ẙ" U1E99 # LATIN SMALL LETTER Y WITH RING ABOVE : "ẙ" U1E99 # LATIN SMALL LETTER Y WITH RING ABOVE : "ẛ" U1E9B # LATIN SMALL LETTER LONG S WITH DOT ABOVE : "ẛ" U1E9B # LATIN SMALL LETTER LONG S WITH DOT ABOVE : "Ạ" U1EA0 # LATIN CAPITAL LETTER A WITH DOT BELOW : "Ạ" U1EA0 # LATIN CAPITAL LETTER A WITH DOT BELOW : "ạ" U1EA1 # LATIN SMALL LETTER A WITH DOT BELOW : "ạ" U1EA1 # LATIN SMALL LETTER A WITH DOT BELOW : "Ả" U1EA2 # LATIN CAPITAL LETTER A WITH HOOK ABOVE : "Ả" U1EA2 # LATIN CAPITAL LETTER A WITH HOOK ABOVE : "ả" U1EA3 # LATIN SMALL LETTER A WITH HOOK ABOVE : "ả" U1EA3 # LATIN SMALL LETTER A WITH HOOK ABOVE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ấ" U1EA4 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" U1EA5 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ầ" U1EA6 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE : "Ầ" U1EA6 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE : "Ầ" U1EA6 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE : "Ầ" U1EA6 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE : "Ầ" U1EA6 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE : "Ầ" U1EA6 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE : "ầ" U1EA7 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE : "ầ" U1EA7 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE : "ầ" U1EA7 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE : "ầ" U1EA7 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE : "ầ" U1EA7 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE : "ầ" U1EA7 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE : "Ẩ" U1EA8 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "Ẩ" U1EA8 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "Ẩ" U1EA8 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "Ẩ" U1EA8 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "Ẩ" U1EA8 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "Ẩ" U1EA8 # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "ẩ" U1EA9 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "ẩ" U1EA9 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "ẩ" U1EA9 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "ẩ" U1EA9 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "ẩ" U1EA9 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "ẩ" U1EA9 # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "Ẫ" U1EAA # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE : "Ẫ" U1EAA # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE : "Ẫ" U1EAA # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE : "Ẫ" U1EAA # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE : "Ẫ" U1EAA # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE : "Ẫ" U1EAA # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE : "ẫ" U1EAB # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE : "ẫ" U1EAB # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE : "ẫ" U1EAB # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE : "ẫ" U1EAB # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE : "ẫ" U1EAB # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE : "ẫ" U1EAB # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE : "Ậ" U1EAC # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "Ậ" U1EAC # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "Ậ" U1EAC # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "Ậ" U1EAC # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "Ậ" U1EAC # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "Ậ" U1EAC # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "Ậ" U1EAC # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "ậ" U1EAD # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "ậ" U1EAD # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "ậ" U1EAD # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "ậ" U1EAD # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "ậ" U1EAD # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "ậ" U1EAD # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "ậ" U1EAD # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ắ" U1EAE # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ắ" U1EAF # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "Ằ" U1EB0 # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "Ằ" U1EB0 # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "Ằ" U1EB0 # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "Ằ" U1EB0 # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "Ằ" U1EB0 # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "Ằ" U1EB0 # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "Ằ" U1EB0 # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "ằ" U1EB1 # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "ằ" U1EB1 # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "ằ" U1EB1 # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "ằ" U1EB1 # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "ằ" U1EB1 # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "ằ" U1EB1 # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "ằ" U1EB1 # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "Ẳ" U1EB2 # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "Ẳ" U1EB2 # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "Ẳ" U1EB2 # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "Ẳ" U1EB2 # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "Ẳ" U1EB2 # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "Ẳ" U1EB2 # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "Ẳ" U1EB2 # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "ẳ" U1EB3 # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "ẳ" U1EB3 # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "ẳ" U1EB3 # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "ẳ" U1EB3 # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "ẳ" U1EB3 # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "ẳ" U1EB3 # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "ẳ" U1EB3 # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "Ẵ" U1EB4 # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "Ẵ" U1EB4 # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "Ẵ" U1EB4 # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "Ẵ" U1EB4 # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "Ẵ" U1EB4 # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "Ẵ" U1EB4 # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "Ẵ" U1EB4 # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "ẵ" U1EB5 # LATIN SMALL LETTER A WITH BREVE AND TILDE : "ẵ" U1EB5 # LATIN SMALL LETTER A WITH BREVE AND TILDE : "ẵ" U1EB5 # LATIN SMALL LETTER A WITH BREVE AND TILDE : "ẵ" U1EB5 # LATIN SMALL LETTER A WITH BREVE AND TILDE : "ẵ" U1EB5 # LATIN SMALL LETTER A WITH BREVE AND TILDE : "ẵ" U1EB5 # LATIN SMALL LETTER A WITH BREVE AND TILDE : "ẵ" U1EB5 # LATIN SMALL LETTER A WITH BREVE AND TILDE : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "Ặ" U1EB6 # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "ặ" U1EB7 # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "Ẹ" U1EB8 # LATIN CAPITAL LETTER E WITH DOT BELOW : "Ẹ" U1EB8 # LATIN CAPITAL LETTER E WITH DOT BELOW : "ẹ" U1EB9 # LATIN SMALL LETTER E WITH DOT BELOW : "ẹ" U1EB9 # LATIN SMALL LETTER E WITH DOT BELOW : "Ẻ" U1EBA # LATIN CAPITAL LETTER E WITH HOOK ABOVE : "Ẻ" U1EBA # LATIN CAPITAL LETTER E WITH HOOK ABOVE : "ẻ" U1EBB # LATIN SMALL LETTER E WITH HOOK ABOVE : "ẻ" U1EBB # LATIN SMALL LETTER E WITH HOOK ABOVE : "Ẽ" U1EBC # LATIN CAPITAL LETTER E WITH TILDE : "Ẽ" U1EBC # LATIN CAPITAL LETTER E WITH TILDE : "ẽ" U1EBD # LATIN SMALL LETTER E WITH TILDE : "ẽ" U1EBD # LATIN SMALL LETTER E WITH TILDE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ế" U1EBE # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" U1EBF # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ề" U1EC0 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE : "Ề" U1EC0 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE : "Ề" U1EC0 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE : "Ề" U1EC0 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE : "Ề" U1EC0 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE : "Ề" U1EC0 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE : "ề" U1EC1 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE : "ề" U1EC1 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE : "ề" U1EC1 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE : "ề" U1EC1 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE : "ề" U1EC1 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE : "ề" U1EC1 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE : "Ể" U1EC2 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "Ể" U1EC2 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "Ể" U1EC2 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "Ể" U1EC2 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "Ể" U1EC2 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "Ể" U1EC2 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "ể" U1EC3 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "ể" U1EC3 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "ể" U1EC3 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "ể" U1EC3 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "ể" U1EC3 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "ể" U1EC3 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "Ễ" U1EC4 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE : "Ễ" U1EC4 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE : "Ễ" U1EC4 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE : "Ễ" U1EC4 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE : "Ễ" U1EC4 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE : "Ễ" U1EC4 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE : "ễ" U1EC5 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE : "ễ" U1EC5 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE : "ễ" U1EC5 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE : "ễ" U1EC5 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE : "ễ" U1EC5 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE : "ễ" U1EC5 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE : "Ệ" U1EC6 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "Ệ" U1EC6 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "Ệ" U1EC6 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "Ệ" U1EC6 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "Ệ" U1EC6 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "Ệ" U1EC6 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "Ệ" U1EC6 # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "ệ" U1EC7 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "ệ" U1EC7 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "ệ" U1EC7 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "ệ" U1EC7 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "ệ" U1EC7 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "ệ" U1EC7 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "ệ" U1EC7 # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "Ỉ" U1EC8 # LATIN CAPITAL LETTER I WITH HOOK ABOVE : "Ỉ" U1EC8 # LATIN CAPITAL LETTER I WITH HOOK ABOVE : "ỉ" U1EC9 # LATIN SMALL LETTER I WITH HOOK ABOVE : "ỉ" U1EC9 # LATIN SMALL LETTER I WITH HOOK ABOVE : "Ị" U1ECA # LATIN CAPITAL LETTER I WITH DOT BELOW : "Ị" U1ECA # LATIN CAPITAL LETTER I WITH DOT BELOW : "ị" U1ECB # LATIN SMALL LETTER I WITH DOT BELOW : "ị" U1ECB # LATIN SMALL LETTER I WITH DOT BELOW : "Ọ" U1ECC # LATIN CAPITAL LETTER O WITH DOT BELOW : "Ọ" U1ECC # LATIN CAPITAL LETTER O WITH DOT BELOW : "ọ" U1ECD # LATIN SMALL LETTER O WITH DOT BELOW : "ọ" U1ECD # LATIN SMALL LETTER O WITH DOT BELOW : "Ỏ" U1ECE # LATIN CAPITAL LETTER O WITH HOOK ABOVE : "Ỏ" U1ECE # LATIN CAPITAL LETTER O WITH HOOK ABOVE : "ỏ" U1ECF # LATIN SMALL LETTER O WITH HOOK ABOVE : "ỏ" U1ECF # LATIN SMALL LETTER O WITH HOOK ABOVE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ố" U1ED0 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" U1ED1 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ồ" U1ED2 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE : "Ồ" U1ED2 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE : "Ồ" U1ED2 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE : "Ồ" U1ED2 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE : "Ồ" U1ED2 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE : "Ồ" U1ED2 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE : "ồ" U1ED3 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE : "ồ" U1ED3 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE : "ồ" U1ED3 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE : "ồ" U1ED3 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE : "ồ" U1ED3 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE : "ồ" U1ED3 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE : "Ổ" U1ED4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "Ổ" U1ED4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "Ổ" U1ED4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "Ổ" U1ED4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "Ổ" U1ED4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "Ổ" U1ED4 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "ổ" U1ED5 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "ổ" U1ED5 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "ổ" U1ED5 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "ổ" U1ED5 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "ổ" U1ED5 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "ổ" U1ED5 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "Ỗ" U1ED6 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE : "Ỗ" U1ED6 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE : "Ỗ" U1ED6 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE : "Ỗ" U1ED6 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE : "Ỗ" U1ED6 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE : "Ỗ" U1ED6 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE : "ỗ" U1ED7 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE : "ỗ" U1ED7 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE : "ỗ" U1ED7 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE : "ỗ" U1ED7 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE : "ỗ" U1ED7 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE : "ỗ" U1ED7 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE : "Ộ" U1ED8 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "Ộ" U1ED8 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "Ộ" U1ED8 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "Ộ" U1ED8 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "Ộ" U1ED8 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "Ộ" U1ED8 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "Ộ" U1ED8 # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "ộ" U1ED9 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "ộ" U1ED9 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "ộ" U1ED9 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "ộ" U1ED9 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "ộ" U1ED9 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "ộ" U1ED9 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "ộ" U1ED9 # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ớ" U1EDA # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ớ" U1EDB # LATIN SMALL LETTER O WITH HORN AND ACUTE : "Ờ" U1EDC # LATIN CAPITAL LETTER O WITH HORN AND GRAVE : "Ờ" U1EDC # LATIN CAPITAL LETTER O WITH HORN AND GRAVE : "Ờ" U1EDC # LATIN CAPITAL LETTER O WITH HORN AND GRAVE : "Ờ" U1EDC # LATIN CAPITAL LETTER O WITH HORN AND GRAVE : "Ờ" U1EDC # LATIN CAPITAL LETTER O WITH HORN AND GRAVE : "Ờ" U1EDC # LATIN CAPITAL LETTER O WITH HORN AND GRAVE : "ờ" U1EDD # LATIN SMALL LETTER O WITH HORN AND GRAVE : "ờ" U1EDD # LATIN SMALL LETTER O WITH HORN AND GRAVE : "ờ" U1EDD # LATIN SMALL LETTER O WITH HORN AND GRAVE : "ờ" U1EDD # LATIN SMALL LETTER O WITH HORN AND GRAVE : "ờ" U1EDD # LATIN SMALL LETTER O WITH HORN AND GRAVE : "ờ" U1EDD # LATIN SMALL LETTER O WITH HORN AND GRAVE : "Ở" U1EDE # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE : "Ở" U1EDE # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE : "Ở" U1EDE # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE : "Ở" U1EDE # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE : "Ở" U1EDE # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE : "Ở" U1EDE # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE : "ở" U1EDF # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE : "ở" U1EDF # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE : "ở" U1EDF # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE : "ở" U1EDF # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE : "ở" U1EDF # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE : "ở" U1EDF # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE : "Ỡ" U1EE0 # LATIN CAPITAL LETTER O WITH HORN AND TILDE : "Ỡ" U1EE0 # LATIN CAPITAL LETTER O WITH HORN AND TILDE : "Ỡ" U1EE0 # LATIN CAPITAL LETTER O WITH HORN AND TILDE : "Ỡ" U1EE0 # LATIN CAPITAL LETTER O WITH HORN AND TILDE : "Ỡ" U1EE0 # LATIN CAPITAL LETTER O WITH HORN AND TILDE : "Ỡ" U1EE0 # LATIN CAPITAL LETTER O WITH HORN AND TILDE : "ỡ" U1EE1 # LATIN SMALL LETTER O WITH HORN AND TILDE : "ỡ" U1EE1 # LATIN SMALL LETTER O WITH HORN AND TILDE : "ỡ" U1EE1 # LATIN SMALL LETTER O WITH HORN AND TILDE : "ỡ" U1EE1 # LATIN SMALL LETTER O WITH HORN AND TILDE : "ỡ" U1EE1 # LATIN SMALL LETTER O WITH HORN AND TILDE : "ỡ" U1EE1 # LATIN SMALL LETTER O WITH HORN AND TILDE : "Ợ" U1EE2 # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW : "Ợ" U1EE2 # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW : "Ợ" U1EE2 # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW : "Ợ" U1EE2 # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW : "Ợ" U1EE2 # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW : "Ợ" U1EE2 # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW : "ợ" U1EE3 # LATIN SMALL LETTER O WITH HORN AND DOT BELOW : "ợ" U1EE3 # LATIN SMALL LETTER O WITH HORN AND DOT BELOW : "ợ" U1EE3 # LATIN SMALL LETTER O WITH HORN AND DOT BELOW : "ợ" U1EE3 # LATIN SMALL LETTER O WITH HORN AND DOT BELOW : "ợ" U1EE3 # LATIN SMALL LETTER O WITH HORN AND DOT BELOW : "ợ" U1EE3 # LATIN SMALL LETTER O WITH HORN AND DOT BELOW : "Ụ" U1EE4 # LATIN CAPITAL LETTER U WITH DOT BELOW : "Ụ" U1EE4 # LATIN CAPITAL LETTER U WITH DOT BELOW : "ụ" U1EE5 # LATIN SMALL LETTER U WITH DOT BELOW : "ụ" U1EE5 # LATIN SMALL LETTER U WITH DOT BELOW : "Ủ" U1EE6 # LATIN CAPITAL LETTER U WITH HOOK ABOVE : "Ủ" U1EE6 # LATIN CAPITAL LETTER U WITH HOOK ABOVE : "ủ" U1EE7 # LATIN SMALL LETTER U WITH HOOK ABOVE : "ủ" U1EE7 # LATIN SMALL LETTER U WITH HOOK ABOVE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ứ" U1EE8 # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ứ" U1EE9 # LATIN SMALL LETTER U WITH HORN AND ACUTE : "Ừ" U1EEA # LATIN CAPITAL LETTER U WITH HORN AND GRAVE : "Ừ" U1EEA # LATIN CAPITAL LETTER U WITH HORN AND GRAVE : "Ừ" U1EEA # LATIN CAPITAL LETTER U WITH HORN AND GRAVE : "Ừ" U1EEA # LATIN CAPITAL LETTER U WITH HORN AND GRAVE : "Ừ" U1EEA # LATIN CAPITAL LETTER U WITH HORN AND GRAVE : "Ừ" U1EEA # LATIN CAPITAL LETTER U WITH HORN AND GRAVE : "ừ" U1EEB # LATIN SMALL LETTER U WITH HORN AND GRAVE : "ừ" U1EEB # LATIN SMALL LETTER U WITH HORN AND GRAVE : "ừ" U1EEB # LATIN SMALL LETTER U WITH HORN AND GRAVE : "ừ" U1EEB # LATIN SMALL LETTER U WITH HORN AND GRAVE : "ừ" U1EEB # LATIN SMALL LETTER U WITH HORN AND GRAVE : "ừ" U1EEB # LATIN SMALL LETTER U WITH HORN AND GRAVE : "Ử" U1EEC # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE : "Ử" U1EEC # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE : "Ử" U1EEC # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE : "Ử" U1EEC # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE : "Ử" U1EEC # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE : "Ử" U1EEC # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE : "ử" U1EED # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE : "ử" U1EED # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE : "ử" U1EED # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE : "ử" U1EED # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE : "ử" U1EED # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE : "ử" U1EED # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE : "Ữ" U1EEE # LATIN CAPITAL LETTER U WITH HORN AND TILDE : "Ữ" U1EEE # LATIN CAPITAL LETTER U WITH HORN AND TILDE : "Ữ" U1EEE # LATIN CAPITAL LETTER U WITH HORN AND TILDE : "Ữ" U1EEE # LATIN CAPITAL LETTER U WITH HORN AND TILDE : "Ữ" U1EEE # LATIN CAPITAL LETTER U WITH HORN AND TILDE : "Ữ" U1EEE # LATIN CAPITAL LETTER U WITH HORN AND TILDE : "ữ" U1EEF # LATIN SMALL LETTER U WITH HORN AND TILDE : "ữ" U1EEF # LATIN SMALL LETTER U WITH HORN AND TILDE : "ữ" U1EEF # LATIN SMALL LETTER U WITH HORN AND TILDE : "ữ" U1EEF # LATIN SMALL LETTER U WITH HORN AND TILDE : "ữ" U1EEF # LATIN SMALL LETTER U WITH HORN AND TILDE : "ữ" U1EEF # LATIN SMALL LETTER U WITH HORN AND TILDE : "Ự" U1EF0 # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW : "Ự" U1EF0 # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW : "Ự" U1EF0 # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW : "Ự" U1EF0 # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW : "Ự" U1EF0 # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW : "Ự" U1EF0 # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW : "ự" U1EF1 # LATIN SMALL LETTER U WITH HORN AND DOT BELOW : "ự" U1EF1 # LATIN SMALL LETTER U WITH HORN AND DOT BELOW : "ự" U1EF1 # LATIN SMALL LETTER U WITH HORN AND DOT BELOW : "ự" U1EF1 # LATIN SMALL LETTER U WITH HORN AND DOT BELOW : "ự" U1EF1 # LATIN SMALL LETTER U WITH HORN AND DOT BELOW : "ự" U1EF1 # LATIN SMALL LETTER U WITH HORN AND DOT BELOW : "Ỳ" U1EF2 # LATIN CAPITAL LETTER Y WITH GRAVE : "Ỳ" U1EF2 # LATIN CAPITAL LETTER Y WITH GRAVE : "ỳ" U1EF3 # LATIN SMALL LETTER Y WITH GRAVE : "ỳ" U1EF3 # LATIN SMALL LETTER Y WITH GRAVE : "Ỵ" U1EF4 # LATIN CAPITAL LETTER Y WITH DOT BELOW : "Ỵ" U1EF4 # LATIN CAPITAL LETTER Y WITH DOT BELOW : "ỵ" U1EF5 # LATIN SMALL LETTER Y WITH DOT BELOW : "ỵ" U1EF5 # LATIN SMALL LETTER Y WITH DOT BELOW : "Ỷ" U1EF6 # LATIN CAPITAL LETTER Y WITH HOOK ABOVE : "Ỷ" U1EF6 # LATIN CAPITAL LETTER Y WITH HOOK ABOVE : "ỷ" U1EF7 # LATIN SMALL LETTER Y WITH HOOK ABOVE : "ỷ" U1EF7 # LATIN SMALL LETTER Y WITH HOOK ABOVE : "Ỹ" U1EF8 # LATIN CAPITAL LETTER Y WITH TILDE : "Ỹ" U1EF8 # LATIN CAPITAL LETTER Y WITH TILDE : "ỹ" U1EF9 # LATIN SMALL LETTER Y WITH TILDE : "ỹ" U1EF9 # LATIN SMALL LETTER Y WITH TILDE : "ἀ" U1F00 # GREEK SMALL LETTER ALPHA WITH PSILI : "ἀ" U1F00 # GREEK SMALL LETTER ALPHA WITH PSILI : "ἁ" U1F01 # GREEK SMALL LETTER ALPHA WITH DASIA : "ἁ" U1F01 # GREEK SMALL LETTER ALPHA WITH DASIA : "ἂ" U1F02 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA : "ἂ" U1F02 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA : "ἂ" U1F02 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA : "ἂ" U1F02 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA : "ἂ" U1F02 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA : "ἂ" U1F02 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA : "ἃ" U1F03 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA : "ἃ" U1F03 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA : "ἃ" U1F03 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA : "ἃ" U1F03 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA : "ἃ" U1F03 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA : "ἃ" U1F03 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἄ" U1F04 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἅ" U1F05 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA : "ἆ" U1F06 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI : "ἆ" U1F06 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI : "ἆ" U1F06 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI : "ἆ" U1F06 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI : "ἆ" U1F06 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI : "ἆ" U1F06 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI : "ἇ" U1F07 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI : "ἇ" U1F07 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI : "ἇ" U1F07 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI : "ἇ" U1F07 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI : "ἇ" U1F07 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI : "ἇ" U1F07 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI : "Ἀ" U1F08 # GREEK CAPITAL LETTER ALPHA WITH PSILI : "Ἀ" U1F08 # GREEK CAPITAL LETTER ALPHA WITH PSILI : "Ἁ" U1F09 # GREEK CAPITAL LETTER ALPHA WITH DASIA : "Ἁ" U1F09 # GREEK CAPITAL LETTER ALPHA WITH DASIA : "Ἂ" U1F0A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA : "Ἂ" U1F0A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA : "Ἂ" U1F0A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA : "Ἂ" U1F0A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA : "Ἂ" U1F0A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA : "Ἂ" U1F0A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA : "Ἃ" U1F0B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA : "Ἃ" U1F0B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA : "Ἃ" U1F0B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA : "Ἃ" U1F0B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA : "Ἃ" U1F0B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA : "Ἃ" U1F0B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἄ" U1F0C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἅ" U1F0D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA : "Ἆ" U1F0E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI : "Ἆ" U1F0E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI : "Ἆ" U1F0E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI : "Ἆ" U1F0E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI : "Ἆ" U1F0E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI : "Ἆ" U1F0E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI : "Ἇ" U1F0F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI : "Ἇ" U1F0F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI : "Ἇ" U1F0F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI : "Ἇ" U1F0F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI : "Ἇ" U1F0F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI : "Ἇ" U1F0F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI : "ἐ" U1F10 # GREEK SMALL LETTER EPSILON WITH PSILI : "ἐ" U1F10 # GREEK SMALL LETTER EPSILON WITH PSILI : "ἑ" U1F11 # GREEK SMALL LETTER EPSILON WITH DASIA : "ἑ" U1F11 # GREEK SMALL LETTER EPSILON WITH DASIA : "ἒ" U1F12 # GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA : "ἒ" U1F12 # GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA : "ἒ" U1F12 # GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA : "ἒ" U1F12 # GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA : "ἒ" U1F12 # GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA : "ἒ" U1F12 # GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA : "ἓ" U1F13 # GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA : "ἓ" U1F13 # GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA : "ἓ" U1F13 # GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA : "ἓ" U1F13 # GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA : "ἓ" U1F13 # GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA : "ἓ" U1F13 # GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἔ" U1F14 # GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "ἕ" U1F15 # GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA : "Ἐ" U1F18 # GREEK CAPITAL LETTER EPSILON WITH PSILI : "Ἐ" U1F18 # GREEK CAPITAL LETTER EPSILON WITH PSILI : "Ἑ" U1F19 # GREEK CAPITAL LETTER EPSILON WITH DASIA : "Ἑ" U1F19 # GREEK CAPITAL LETTER EPSILON WITH DASIA : "Ἒ" U1F1A # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA : "Ἒ" U1F1A # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA : "Ἒ" U1F1A # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA : "Ἒ" U1F1A # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA : "Ἒ" U1F1A # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA : "Ἒ" U1F1A # GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA : "Ἓ" U1F1B # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA : "Ἓ" U1F1B # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA : "Ἓ" U1F1B # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA : "Ἓ" U1F1B # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA : "Ἓ" U1F1B # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA : "Ἓ" U1F1B # GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἔ" U1F1C # GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "Ἕ" U1F1D # GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA : "ἠ" U1F20 # GREEK SMALL LETTER ETA WITH PSILI : "ἠ" U1F20 # GREEK SMALL LETTER ETA WITH PSILI : "ἡ" U1F21 # GREEK SMALL LETTER ETA WITH DASIA : "ἡ" U1F21 # GREEK SMALL LETTER ETA WITH DASIA : "ἢ" U1F22 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA : "ἢ" U1F22 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA : "ἢ" U1F22 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA : "ἢ" U1F22 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA : "ἢ" U1F22 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA : "ἢ" U1F22 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA : "ἣ" U1F23 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA : "ἣ" U1F23 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA : "ἣ" U1F23 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA : "ἣ" U1F23 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA : "ἣ" U1F23 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA : "ἣ" U1F23 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἤ" U1F24 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἥ" U1F25 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA : "ἦ" U1F26 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI : "ἦ" U1F26 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI : "ἦ" U1F26 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI : "ἦ" U1F26 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI : "ἦ" U1F26 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI : "ἦ" U1F26 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI : "ἧ" U1F27 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI : "ἧ" U1F27 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI : "ἧ" U1F27 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI : "ἧ" U1F27 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI : "ἧ" U1F27 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI : "ἧ" U1F27 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI : "Ἠ" U1F28 # GREEK CAPITAL LETTER ETA WITH PSILI : "Ἠ" U1F28 # GREEK CAPITAL LETTER ETA WITH PSILI : "Ἡ" U1F29 # GREEK CAPITAL LETTER ETA WITH DASIA : "Ἡ" U1F29 # GREEK CAPITAL LETTER ETA WITH DASIA : "Ἢ" U1F2A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA : "Ἢ" U1F2A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA : "Ἢ" U1F2A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA : "Ἢ" U1F2A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA : "Ἢ" U1F2A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA : "Ἢ" U1F2A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA : "Ἣ" U1F2B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA : "Ἣ" U1F2B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA : "Ἣ" U1F2B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA : "Ἣ" U1F2B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA : "Ἣ" U1F2B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA : "Ἣ" U1F2B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἤ" U1F2C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἥ" U1F2D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA : "Ἦ" U1F2E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI : "Ἦ" U1F2E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI : "Ἦ" U1F2E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI : "Ἦ" U1F2E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI : "Ἦ" U1F2E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI : "Ἦ" U1F2E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI : "Ἧ" U1F2F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI : "Ἧ" U1F2F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI : "Ἧ" U1F2F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI : "Ἧ" U1F2F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI : "Ἧ" U1F2F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI : "Ἧ" U1F2F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI : "ἰ" U1F30 # GREEK SMALL LETTER IOTA WITH PSILI : "ἰ" U1F30 # GREEK SMALL LETTER IOTA WITH PSILI : "ἱ" U1F31 # GREEK SMALL LETTER IOTA WITH DASIA : "ἱ" U1F31 # GREEK SMALL LETTER IOTA WITH DASIA : "ἲ" U1F32 # GREEK SMALL LETTER IOTA WITH PSILI AND VARIA : "ἲ" U1F32 # GREEK SMALL LETTER IOTA WITH PSILI AND VARIA : "ἲ" U1F32 # GREEK SMALL LETTER IOTA WITH PSILI AND VARIA : "ἲ" U1F32 # GREEK SMALL LETTER IOTA WITH PSILI AND VARIA : "ἲ" U1F32 # GREEK SMALL LETTER IOTA WITH PSILI AND VARIA : "ἲ" U1F32 # GREEK SMALL LETTER IOTA WITH PSILI AND VARIA : "ἳ" U1F33 # GREEK SMALL LETTER IOTA WITH DASIA AND VARIA : "ἳ" U1F33 # GREEK SMALL LETTER IOTA WITH DASIA AND VARIA : "ἳ" U1F33 # GREEK SMALL LETTER IOTA WITH DASIA AND VARIA : "ἳ" U1F33 # GREEK SMALL LETTER IOTA WITH DASIA AND VARIA : "ἳ" U1F33 # GREEK SMALL LETTER IOTA WITH DASIA AND VARIA : "ἳ" U1F33 # GREEK SMALL LETTER IOTA WITH DASIA AND VARIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἴ" U1F34 # GREEK SMALL LETTER IOTA WITH PSILI AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἵ" U1F35 # GREEK SMALL LETTER IOTA WITH DASIA AND OXIA : "ἶ" U1F36 # GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI : "ἶ" U1F36 # GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI : "ἶ" U1F36 # GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI : "ἶ" U1F36 # GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI : "ἶ" U1F36 # GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI : "ἶ" U1F36 # GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI : "ἷ" U1F37 # GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI : "ἷ" U1F37 # GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI : "ἷ" U1F37 # GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI : "ἷ" U1F37 # GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI : "ἷ" U1F37 # GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI : "ἷ" U1F37 # GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI : "Ἰ" U1F38 # GREEK CAPITAL LETTER IOTA WITH PSILI : "Ἰ" U1F38 # GREEK CAPITAL LETTER IOTA WITH PSILI : "Ἱ" U1F39 # GREEK CAPITAL LETTER IOTA WITH DASIA : "Ἱ" U1F39 # GREEK CAPITAL LETTER IOTA WITH DASIA : "Ἲ" U1F3A # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA : "Ἲ" U1F3A # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA : "Ἲ" U1F3A # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA : "Ἲ" U1F3A # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA : "Ἲ" U1F3A # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA : "Ἲ" U1F3A # GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA : "Ἳ" U1F3B # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA : "Ἳ" U1F3B # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA : "Ἳ" U1F3B # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA : "Ἳ" U1F3B # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA : "Ἳ" U1F3B # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA : "Ἳ" U1F3B # GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἴ" U1F3C # GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἵ" U1F3D # GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA : "Ἶ" U1F3E # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI : "Ἶ" U1F3E # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI : "Ἶ" U1F3E # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI : "Ἶ" U1F3E # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI : "Ἶ" U1F3E # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI : "Ἶ" U1F3E # GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI : "Ἷ" U1F3F # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI : "Ἷ" U1F3F # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI : "Ἷ" U1F3F # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI : "Ἷ" U1F3F # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI : "Ἷ" U1F3F # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI : "Ἷ" U1F3F # GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI : "ὀ" U1F40 # GREEK SMALL LETTER OMICRON WITH PSILI : "ὀ" U1F40 # GREEK SMALL LETTER OMICRON WITH PSILI : "ὁ" U1F41 # GREEK SMALL LETTER OMICRON WITH DASIA : "ὁ" U1F41 # GREEK SMALL LETTER OMICRON WITH DASIA : "ὂ" U1F42 # GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA : "ὂ" U1F42 # GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA : "ὂ" U1F42 # GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA : "ὂ" U1F42 # GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA : "ὂ" U1F42 # GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA : "ὂ" U1F42 # GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA : "ὃ" U1F43 # GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA : "ὃ" U1F43 # GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA : "ὃ" U1F43 # GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA : "ὃ" U1F43 # GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA : "ὃ" U1F43 # GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA : "ὃ" U1F43 # GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὄ" U1F44 # GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "ὅ" U1F45 # GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA : "Ὀ" U1F48 # GREEK CAPITAL LETTER OMICRON WITH PSILI : "Ὀ" U1F48 # GREEK CAPITAL LETTER OMICRON WITH PSILI : "Ὁ" U1F49 # GREEK CAPITAL LETTER OMICRON WITH DASIA : "Ὁ" U1F49 # GREEK CAPITAL LETTER OMICRON WITH DASIA : "Ὂ" U1F4A # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA : "Ὂ" U1F4A # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA : "Ὂ" U1F4A # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA : "Ὂ" U1F4A # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA : "Ὂ" U1F4A # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA : "Ὂ" U1F4A # GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA : "Ὃ" U1F4B # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA : "Ὃ" U1F4B # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA : "Ὃ" U1F4B # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA : "Ὃ" U1F4B # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA : "Ὃ" U1F4B # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA : "Ὃ" U1F4B # GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὄ" U1F4C # GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "Ὅ" U1F4D # GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA : "ὐ" U1F50 # GREEK SMALL LETTER UPSILON WITH PSILI : "ὐ" U1F50 # GREEK SMALL LETTER UPSILON WITH PSILI : "ὑ" U1F51 # GREEK SMALL LETTER UPSILON WITH DASIA : "ὑ" U1F51 # GREEK SMALL LETTER UPSILON WITH DASIA : "ὒ" U1F52 # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA : "ὒ" U1F52 # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA : "ὒ" U1F52 # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA : "ὒ" U1F52 # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA : "ὒ" U1F52 # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA : "ὒ" U1F52 # GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA : "ὓ" U1F53 # GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA : "ὓ" U1F53 # GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA : "ὓ" U1F53 # GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA : "ὓ" U1F53 # GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA : "ὓ" U1F53 # GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA : "ὓ" U1F53 # GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὔ" U1F54 # GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὕ" U1F55 # GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA : "ὖ" U1F56 # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI : "ὖ" U1F56 # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI : "ὖ" U1F56 # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI : "ὖ" U1F56 # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI : "ὖ" U1F56 # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI : "ὖ" U1F56 # GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI : "ὗ" U1F57 # GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI : "ὗ" U1F57 # GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI : "ὗ" U1F57 # GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI : "ὗ" U1F57 # GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI : "ὗ" U1F57 # GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI : "ὗ" U1F57 # GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI : "Ὑ" U1F59 # GREEK CAPITAL LETTER UPSILON WITH DASIA : "Ὑ" U1F59 # GREEK CAPITAL LETTER UPSILON WITH DASIA : "Ὓ" U1F5B # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA : "Ὓ" U1F5B # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA : "Ὓ" U1F5B # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA : "Ὓ" U1F5B # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA : "Ὓ" U1F5B # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA : "Ὓ" U1F5B # GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὕ" U1F5D # GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA : "Ὗ" U1F5F # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI : "Ὗ" U1F5F # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI : "Ὗ" U1F5F # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI : "Ὗ" U1F5F # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI : "Ὗ" U1F5F # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI : "Ὗ" U1F5F # GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI : "ὠ" U1F60 # GREEK SMALL LETTER OMEGA WITH PSILI : "ὠ" U1F60 # GREEK SMALL LETTER OMEGA WITH PSILI : "ὡ" U1F61 # GREEK SMALL LETTER OMEGA WITH DASIA : "ὡ" U1F61 # GREEK SMALL LETTER OMEGA WITH DASIA : "ὢ" U1F62 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA : "ὢ" U1F62 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA : "ὢ" U1F62 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA : "ὢ" U1F62 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA : "ὢ" U1F62 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA : "ὢ" U1F62 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA : "ὣ" U1F63 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA : "ὣ" U1F63 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA : "ὣ" U1F63 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA : "ὣ" U1F63 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA : "ὣ" U1F63 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA : "ὣ" U1F63 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὤ" U1F64 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὥ" U1F65 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA : "ὦ" U1F66 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI : "ὦ" U1F66 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI : "ὦ" U1F66 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI : "ὦ" U1F66 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI : "ὦ" U1F66 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI : "ὦ" U1F66 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI : "ὧ" U1F67 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI : "ὧ" U1F67 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI : "ὧ" U1F67 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI : "ὧ" U1F67 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI : "ὧ" U1F67 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI : "ὧ" U1F67 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI : "Ὠ" U1F68 # GREEK CAPITAL LETTER OMEGA WITH PSILI : "Ὠ" U1F68 # GREEK CAPITAL LETTER OMEGA WITH PSILI : "Ὡ" U1F69 # GREEK CAPITAL LETTER OMEGA WITH DASIA : "Ὡ" U1F69 # GREEK CAPITAL LETTER OMEGA WITH DASIA : "Ὢ" U1F6A # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA : "Ὢ" U1F6A # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA : "Ὢ" U1F6A # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA : "Ὢ" U1F6A # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA : "Ὢ" U1F6A # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA : "Ὢ" U1F6A # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA : "Ὣ" U1F6B # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA : "Ὣ" U1F6B # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA : "Ὣ" U1F6B # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA : "Ὣ" U1F6B # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA : "Ὣ" U1F6B # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA : "Ὣ" U1F6B # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὤ" U1F6C # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὥ" U1F6D # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA : "Ὦ" U1F6E # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI : "Ὦ" U1F6E # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI : "Ὦ" U1F6E # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI : "Ὦ" U1F6E # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI : "Ὦ" U1F6E # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI : "Ὦ" U1F6E # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI : "Ὧ" U1F6F # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI : "Ὧ" U1F6F # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI : "Ὧ" U1F6F # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI : "Ὧ" U1F6F # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI : "Ὧ" U1F6F # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI : "Ὧ" U1F6F # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI : "ὰ" U1F70 # GREEK SMALL LETTER ALPHA WITH VARIA : "ὰ" U1F70 # GREEK SMALL LETTER ALPHA WITH VARIA : "ὲ" U1F72 # GREEK SMALL LETTER EPSILON WITH VARIA : "ὲ" U1F72 # GREEK SMALL LETTER EPSILON WITH VARIA : "ὴ" U1F74 # GREEK SMALL LETTER ETA WITH VARIA : "ὴ" U1F74 # GREEK SMALL LETTER ETA WITH VARIA : "ὶ" U1F76 # GREEK SMALL LETTER IOTA WITH VARIA : "ὶ" U1F76 # GREEK SMALL LETTER IOTA WITH VARIA : "ὸ" U1F78 # GREEK SMALL LETTER OMICRON WITH VARIA : "ὸ" U1F78 # GREEK SMALL LETTER OMICRON WITH VARIA : "ὺ" U1F7A # GREEK SMALL LETTER UPSILON WITH VARIA : "ὺ" U1F7A # GREEK SMALL LETTER UPSILON WITH VARIA : "ὼ" U1F7C # GREEK SMALL LETTER OMEGA WITH VARIA : "ὼ" U1F7C # GREEK SMALL LETTER OMEGA WITH VARIA : "ᾀ" U1F80 # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI : "ᾀ" U1F80 # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI : "ᾀ" U1F80 # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI : "ᾀ" U1F80 # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI : "ᾀ" U1F80 # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI : "ᾀ" U1F80 # GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI : "ᾁ" U1F81 # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI : "ᾁ" U1F81 # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI : "ᾁ" U1F81 # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI : "ᾁ" U1F81 # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI : "ᾁ" U1F81 # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI : "ᾁ" U1F81 # GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾂ" U1F82 # GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾃ" U1F83 # GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾄ" U1F84 # GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾅ" U1F85 # GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾆ" U1F86 # GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾇ" U1F87 # GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾈ" U1F88 # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI : "ᾈ" U1F88 # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI : "ᾈ" U1F88 # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI : "ᾈ" U1F88 # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI : "ᾈ" U1F88 # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI : "ᾈ" U1F88 # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI : "ᾉ" U1F89 # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI : "ᾉ" U1F89 # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI : "ᾉ" U1F89 # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI : "ᾉ" U1F89 # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI : "ᾉ" U1F89 # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI : "ᾉ" U1F89 # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾊ" U1F8A # GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾋ" U1F8B # GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾌ" U1F8C # GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾍ" U1F8D # GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾎ" U1F8E # GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾏ" U1F8F # GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾐ" U1F90 # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI : "ᾐ" U1F90 # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI : "ᾐ" U1F90 # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI : "ᾐ" U1F90 # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI : "ᾐ" U1F90 # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI : "ᾐ" U1F90 # GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI : "ᾑ" U1F91 # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI : "ᾑ" U1F91 # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI : "ᾑ" U1F91 # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI : "ᾑ" U1F91 # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI : "ᾑ" U1F91 # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI : "ᾑ" U1F91 # GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾒ" U1F92 # GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾓ" U1F93 # GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾔ" U1F94 # GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾕ" U1F95 # GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾖ" U1F96 # GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾗ" U1F97 # GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾘ" U1F98 # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI : "ᾘ" U1F98 # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI : "ᾘ" U1F98 # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI : "ᾘ" U1F98 # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI : "ᾘ" U1F98 # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI : "ᾘ" U1F98 # GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI : "ᾙ" U1F99 # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI : "ᾙ" U1F99 # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI : "ᾙ" U1F99 # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI : "ᾙ" U1F99 # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI : "ᾙ" U1F99 # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI : "ᾙ" U1F99 # GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾚ" U1F9A # GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾛ" U1F9B # GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾜ" U1F9C # GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾝ" U1F9D # GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾞ" U1F9E # GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾟ" U1F9F # GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾠ" U1FA0 # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI : "ᾠ" U1FA0 # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI : "ᾠ" U1FA0 # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI : "ᾠ" U1FA0 # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI : "ᾠ" U1FA0 # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI : "ᾠ" U1FA0 # GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI : "ᾡ" U1FA1 # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI : "ᾡ" U1FA1 # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI : "ᾡ" U1FA1 # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI : "ᾡ" U1FA1 # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI : "ᾡ" U1FA1 # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI : "ᾡ" U1FA1 # GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾢ" U1FA2 # GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾣ" U1FA3 # GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾤ" U1FA4 # GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾥ" U1FA5 # GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾦ" U1FA6 # GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾧ" U1FA7 # GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI : "ᾨ" U1FA8 # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI : "ᾨ" U1FA8 # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI : "ᾨ" U1FA8 # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI : "ᾨ" U1FA8 # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI : "ᾨ" U1FA8 # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI : "ᾨ" U1FA8 # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI : "ᾩ" U1FA9 # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI : "ᾩ" U1FA9 # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI : "ᾩ" U1FA9 # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI : "ᾩ" U1FA9 # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI : "ᾩ" U1FA9 # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI : "ᾩ" U1FA9 # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾪ" U1FAA # GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾫ" U1FAB # GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾬ" U1FAC # GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾭ" U1FAD # GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾮ" U1FAE # GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾯ" U1FAF # GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI : "ᾰ" U1FB0 # GREEK SMALL LETTER ALPHA WITH VRACHY : "ᾰ" U1FB0 # GREEK SMALL LETTER ALPHA WITH VRACHY : "ᾰ" U1FB0 # GREEK SMALL LETTER ALPHA WITH VRACHY : "ᾱ" U1FB1 # GREEK SMALL LETTER ALPHA WITH MACRON : "ᾱ" U1FB1 # GREEK SMALL LETTER ALPHA WITH MACRON : "ᾱ" U1FB1 # GREEK SMALL LETTER ALPHA WITH MACRON : "ᾲ" U1FB2 # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI : "ᾲ" U1FB2 # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI : "ᾲ" U1FB2 # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI : "ᾲ" U1FB2 # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI : "ᾲ" U1FB2 # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI : "ᾲ" U1FB2 # GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI : "ᾳ" U1FB3 # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI : "ᾳ" U1FB3 # GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI : "ᾴ" U1FB4 # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI : "ᾴ" U1FB4 # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI : "ᾴ" U1FB4 # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI : "ᾴ" U1FB4 # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI : "ᾴ" U1FB4 # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI : "ᾴ" U1FB4 # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI : "ᾴ" U1FB4 # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI : "ᾴ" U1FB4 # GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI : "ᾶ" U1FB6 # GREEK SMALL LETTER ALPHA WITH PERISPOMENI : "ᾶ" U1FB6 # GREEK SMALL LETTER ALPHA WITH PERISPOMENI : "ᾷ" U1FB7 # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI : "ᾷ" U1FB7 # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI : "ᾷ" U1FB7 # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI : "ᾷ" U1FB7 # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI : "ᾷ" U1FB7 # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI : "ᾷ" U1FB7 # GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI : "Ᾰ" U1FB8 # GREEK CAPITAL LETTER ALPHA WITH VRACHY : "Ᾰ" U1FB8 # GREEK CAPITAL LETTER ALPHA WITH VRACHY : "Ᾰ" U1FB8 # GREEK CAPITAL LETTER ALPHA WITH VRACHY : "Ᾱ" U1FB9 # GREEK CAPITAL LETTER ALPHA WITH MACRON : "Ᾱ" U1FB9 # GREEK CAPITAL LETTER ALPHA WITH MACRON : "Ᾱ" U1FB9 # GREEK CAPITAL LETTER ALPHA WITH MACRON : "Ὰ" U1FBA # GREEK CAPITAL LETTER ALPHA WITH VARIA : "Ὰ" U1FBA # GREEK CAPITAL LETTER ALPHA WITH VARIA : "ᾼ" U1FBC # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI : "ᾼ" U1FBC # GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI : "῁" U1FC1 # GREEK DIALYTIKA AND PERISPOMENI : "῁" U1FC1 # GREEK DIALYTIKA AND PERISPOMENI : "ῂ" U1FC2 # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI : "ῂ" U1FC2 # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI : "ῂ" U1FC2 # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI : "ῂ" U1FC2 # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI : "ῂ" U1FC2 # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI : "ῂ" U1FC2 # GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI : "ῃ" U1FC3 # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI : "ῃ" U1FC3 # GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI : "ῄ" U1FC4 # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI : "ῄ" U1FC4 # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI : "ῄ" U1FC4 # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI : "ῄ" U1FC4 # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI : "ῄ" U1FC4 # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI : "ῄ" U1FC4 # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI : "ῄ" U1FC4 # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI : "ῄ" U1FC4 # GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI : "ῆ" U1FC6 # GREEK SMALL LETTER ETA WITH PERISPOMENI : "ῆ" U1FC6 # GREEK SMALL LETTER ETA WITH PERISPOMENI : "ῇ" U1FC7 # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῇ" U1FC7 # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῇ" U1FC7 # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῇ" U1FC7 # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῇ" U1FC7 # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῇ" U1FC7 # GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI : "Ὲ" U1FC8 # GREEK CAPITAL LETTER EPSILON WITH VARIA : "Ὲ" U1FC8 # GREEK CAPITAL LETTER EPSILON WITH VARIA : "Ὴ" U1FCA # GREEK CAPITAL LETTER ETA WITH VARIA : "Ὴ" U1FCA # GREEK CAPITAL LETTER ETA WITH VARIA : "ῌ" U1FCC # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI : "ῌ" U1FCC # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI : "῍" U1FCD # GREEK PSILI AND VARIA : "῍" U1FCD # GREEK PSILI AND VARIA : "῎" U1FCE # GREEK PSILI AND OXIA : "῎" U1FCE # GREEK PSILI AND OXIA : "῎" U1FCE # GREEK PSILI AND OXIA : "῏" U1FCF # GREEK PSILI AND PERISPOMENI : "῏" U1FCF # GREEK PSILI AND PERISPOMENI : "ῐ" U1FD0 # GREEK SMALL LETTER IOTA WITH VRACHY : "ῐ" U1FD0 # GREEK SMALL LETTER IOTA WITH VRACHY : "ῐ" U1FD0 # GREEK SMALL LETTER IOTA WITH VRACHY : "ῑ" U1FD1 # GREEK SMALL LETTER IOTA WITH MACRON : "ῑ" U1FD1 # GREEK SMALL LETTER IOTA WITH MACRON : "ῑ" U1FD1 # GREEK SMALL LETTER IOTA WITH MACRON : "ῒ" U1FD2 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA : "ῒ" U1FD2 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA : "ῒ" U1FD2 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA : "ῒ" U1FD2 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA : "ῒ" U1FD2 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA : "ῒ" U1FD2 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA : "ῖ" U1FD6 # GREEK SMALL LETTER IOTA WITH PERISPOMENI : "ῖ" U1FD6 # GREEK SMALL LETTER IOTA WITH PERISPOMENI : "ῗ" U1FD7 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI : "ῗ" U1FD7 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI : "ῗ" U1FD7 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI : "ῗ" U1FD7 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI : "ῗ" U1FD7 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI : "ῗ" U1FD7 # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI : "Ῐ" U1FD8 # GREEK CAPITAL LETTER IOTA WITH VRACHY : "Ῐ" U1FD8 # GREEK CAPITAL LETTER IOTA WITH VRACHY : "Ῐ" U1FD8 # GREEK CAPITAL LETTER IOTA WITH VRACHY : "Ῑ" U1FD9 # GREEK CAPITAL LETTER IOTA WITH MACRON : "Ῑ" U1FD9 # GREEK CAPITAL LETTER IOTA WITH MACRON : "Ῑ" U1FD9 # GREEK CAPITAL LETTER IOTA WITH MACRON : "Ὶ" U1FDA # GREEK CAPITAL LETTER IOTA WITH VARIA : "Ὶ" U1FDA # GREEK CAPITAL LETTER IOTA WITH VARIA : "῝" U1FDD # GREEK DASIA AND VARIA : "῝" U1FDD # GREEK DASIA AND VARIA : "῞" U1FDE # GREEK DASIA AND OXIA : "῞" U1FDE # GREEK DASIA AND OXIA : "῞" U1FDE # GREEK DASIA AND OXIA : "῟" U1FDF # GREEK DASIA AND PERISPOMENI : "῟" U1FDF # GREEK DASIA AND PERISPOMENI : "ῠ" U1FE0 # GREEK SMALL LETTER UPSILON WITH VRACHY : "ῠ" U1FE0 # GREEK SMALL LETTER UPSILON WITH VRACHY : "ῠ" U1FE0 # GREEK SMALL LETTER UPSILON WITH VRACHY : "ῡ" U1FE1 # GREEK SMALL LETTER UPSILON WITH MACRON : "ῡ" U1FE1 # GREEK SMALL LETTER UPSILON WITH MACRON : "ῡ" U1FE1 # GREEK SMALL LETTER UPSILON WITH MACRON : "ῢ" U1FE2 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA : "ῢ" U1FE2 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA : "ῢ" U1FE2 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA : "ῢ" U1FE2 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA : "ῢ" U1FE2 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA : "ῢ" U1FE2 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA : "ῤ" U1FE4 # GREEK SMALL LETTER RHO WITH PSILI : "ῤ" U1FE4 # GREEK SMALL LETTER RHO WITH PSILI : "ῥ" U1FE5 # GREEK SMALL LETTER RHO WITH DASIA : "ῥ" U1FE5 # GREEK SMALL LETTER RHO WITH DASIA : "ῦ" U1FE6 # GREEK SMALL LETTER UPSILON WITH PERISPOMENI : "ῦ" U1FE6 # GREEK SMALL LETTER UPSILON WITH PERISPOMENI : "ῧ" U1FE7 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI : "ῧ" U1FE7 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI : "ῧ" U1FE7 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI : "ῧ" U1FE7 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI : "ῧ" U1FE7 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI : "ῧ" U1FE7 # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI : "Ῠ" U1FE8 # GREEK CAPITAL LETTER UPSILON WITH VRACHY : "Ῠ" U1FE8 # GREEK CAPITAL LETTER UPSILON WITH VRACHY : "Ῠ" U1FE8 # GREEK CAPITAL LETTER UPSILON WITH VRACHY : "Ῡ" U1FE9 # GREEK CAPITAL LETTER UPSILON WITH MACRON : "Ῡ" U1FE9 # GREEK CAPITAL LETTER UPSILON WITH MACRON : "Ῡ" U1FE9 # GREEK CAPITAL LETTER UPSILON WITH MACRON : "Ὺ" U1FEA # GREEK CAPITAL LETTER UPSILON WITH VARIA : "Ὺ" U1FEA # GREEK CAPITAL LETTER UPSILON WITH VARIA : "Ῥ" U1FEC # GREEK CAPITAL LETTER RHO WITH DASIA : "Ῥ" U1FEC # GREEK CAPITAL LETTER RHO WITH DASIA : "῭" U1FED # GREEK DIALYTIKA AND VARIA : "῭" U1FED # GREEK DIALYTIKA AND VARIA : "ῲ" U1FF2 # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI : "ῲ" U1FF2 # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI : "ῲ" U1FF2 # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI : "ῲ" U1FF2 # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI : "ῲ" U1FF2 # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI : "ῲ" U1FF2 # GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI : "ῳ" U1FF3 # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI : "ῳ" U1FF3 # GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI : "ῴ" U1FF4 # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI : "ῴ" U1FF4 # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI : "ῴ" U1FF4 # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI : "ῴ" U1FF4 # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI : "ῴ" U1FF4 # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI : "ῴ" U1FF4 # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI : "ῴ" U1FF4 # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI : "ῴ" U1FF4 # GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI : "ῶ" U1FF6 # GREEK SMALL LETTER OMEGA WITH PERISPOMENI : "ῶ" U1FF6 # GREEK SMALL LETTER OMEGA WITH PERISPOMENI : "ῷ" U1FF7 # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῷ" U1FF7 # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῷ" U1FF7 # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῷ" U1FF7 # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῷ" U1FF7 # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI : "ῷ" U1FF7 # GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI : "Ὸ" U1FF8 # GREEK CAPITAL LETTER OMICRON WITH VARIA : "Ὸ" U1FF8 # GREEK CAPITAL LETTER OMICRON WITH VARIA : "Ὼ" U1FFA # GREEK CAPITAL LETTER OMEGA WITH VARIA : "Ὼ" U1FFA # GREEK CAPITAL LETTER OMEGA WITH VARIA : "ῼ" U1FFC # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI : "ῼ" U1FFC # GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI <0> : "⁰" U2070 # SUPERSCRIPT ZERO <0> : "⁰" U2070 # SUPERSCRIPT ZERO : "⁰" U2070 # SUPERSCRIPT ZERO : "⁰" U2070 # SUPERSCRIPT ZERO : "ⁱ" U2071 # SUPERSCRIPT LATIN SMALL LETTER I : "ⁱ" U2071 # SUPERSCRIPT LATIN SMALL LETTER I <4> : "⁴" U2074 # SUPERSCRIPT FOUR <4> : "⁴" U2074 # SUPERSCRIPT FOUR : "⁴" U2074 # SUPERSCRIPT FOUR : "⁴" U2074 # SUPERSCRIPT FOUR <5> : "⁵" U2075 # SUPERSCRIPT FIVE <5> : "⁵" U2075 # SUPERSCRIPT FIVE : "⁵" U2075 # SUPERSCRIPT FIVE : "⁵" U2075 # SUPERSCRIPT FIVE <6> : "⁶" U2076 # SUPERSCRIPT SIX <6> : "⁶" U2076 # SUPERSCRIPT SIX : "⁶" U2076 # SUPERSCRIPT SIX : "⁶" U2076 # SUPERSCRIPT SIX <7> : "⁷" U2077 # SUPERSCRIPT SEVEN <7> : "⁷" U2077 # SUPERSCRIPT SEVEN : "⁷" U2077 # SUPERSCRIPT SEVEN : "⁷" U2077 # SUPERSCRIPT SEVEN <8> : "⁸" U2078 # SUPERSCRIPT EIGHT <8> : "⁸" U2078 # SUPERSCRIPT EIGHT : "⁸" U2078 # SUPERSCRIPT EIGHT : "⁸" U2078 # SUPERSCRIPT EIGHT <9> : "⁹" U2079 # SUPERSCRIPT NINE <9> : "⁹" U2079 # SUPERSCRIPT NINE : "⁹" U2079 # SUPERSCRIPT NINE : "⁹" U2079 # SUPERSCRIPT NINE : "⁺" U207A # SUPERSCRIPT PLUS SIGN : "⁺" U207A # SUPERSCRIPT PLUS SIGN : "⁺" U207A # SUPERSCRIPT PLUS SIGN : "⁺" U207A # SUPERSCRIPT PLUS SIGN : "⁻" U207B # SUPERSCRIPT MINUS : "⁻" U207B # SUPERSCRIPT MINUS : "⁼" U207C # SUPERSCRIPT EQUALS SIGN : "⁼" U207C # SUPERSCRIPT EQUALS SIGN : "⁼" U207C # SUPERSCRIPT EQUALS SIGN : "⁼" U207C # SUPERSCRIPT EQUALS SIGN : "⁽" U207D # SUPERSCRIPT LEFT PARENTHESIS : "⁽" U207D # SUPERSCRIPT LEFT PARENTHESIS : "⁾" U207E # SUPERSCRIPT RIGHT PARENTHESIS : "⁾" U207E # SUPERSCRIPT RIGHT PARENTHESIS : "ⁿ" U207F # SUPERSCRIPT LATIN SMALL LETTER N : "ⁿ" U207F # SUPERSCRIPT LATIN SMALL LETTER N <0> : "₀" U2080 # SUBSCRIPT ZERO : "₀" U2080 # SUBSCRIPT ZERO <1> : "₁" U2081 # SUBSCRIPT ONE : "₁" U2081 # SUBSCRIPT ONE <2> : "₂" U2082 # SUBSCRIPT TWO : "₂" U2082 # SUBSCRIPT TWO : "₂" U2082 # SUBSCRIPT TWO <3> : "₃" U2083 # SUBSCRIPT THREE : "₃" U2083 # SUBSCRIPT THREE <4> : "₄" U2084 # SUBSCRIPT FOUR : "₄" U2084 # SUBSCRIPT FOUR <5> : "₅" U2085 # SUBSCRIPT FIVE : "₅" U2085 # SUBSCRIPT FIVE <6> : "₆" U2086 # SUBSCRIPT SIX : "₆" U2086 # SUBSCRIPT SIX <7> : "₇" U2087 # SUBSCRIPT SEVEN : "₇" U2087 # SUBSCRIPT SEVEN <8> : "₈" U2088 # SUBSCRIPT EIGHT : "₈" U2088 # SUBSCRIPT EIGHT <9> : "₉" U2089 # SUBSCRIPT NINE : "₉" U2089 # SUBSCRIPT NINE : "₊" U208A # SUBSCRIPT PLUS SIGN : "₊" U208A # SUBSCRIPT PLUS SIGN : "₋" U208B # SUBSCRIPT MINUS : "₌" U208C # SUBSCRIPT EQUALS SIGN : "₌" U208C # SUBSCRIPT EQUALS SIGN : "₍" U208D # SUBSCRIPT LEFT PARENTHESIS : "₎" U208E # SUBSCRIPT RIGHT PARENTHESIS : "℠" U2120 # SERVICE MARK : "℠" U2120 # SERVICE MARK : "℠" U2120 # SERVICE MARK : "℠" U2120 # SERVICE MARK : "℠" U2120 # SERVICE MARK : "℠" U2120 # SERVICE MARK : "℠" U2120 # SERVICE MARK : "℠" U2120 # SERVICE MARK : "™" U2122 # TRADE MARK SIGN : "™" U2122 # TRADE MARK SIGN : "™" U2122 # TRADE MARK SIGN : "™" U2122 # TRADE MARK SIGN : "™" U2122 # TRADE MARK SIGN : "™" U2122 # TRADE MARK SIGN : "™" U2122 # TRADE MARK SIGN : "™" U2122 # TRADE MARK SIGN <1> <7> : "⅐" U2150 # VULGAR FRACTION ONE SEVENTH <1> <9> : "⅑" U2151 # VULGAR FRACTION ONE NINTH <1> <1> <0> : "⅒" U2152 # VULGAR FRACTION ONE TENTH <1> <3> : "⅓" U2153 # VULGAR FRACTION ONE THIRD <2> <3> : "⅔" U2154 # VULGAR FRACTION TWO THIRDS <1> <5> : "⅕" U2155 # VULGAR FRACTION ONE FIFTH <2> <5> : "⅖" U2156 # VULGAR FRACTION TWO FIFTHS <3> <5> : "⅗" U2157 # VULGAR FRACTION THREE FIFTHS <4> <5> : "⅘" U2158 # VULGAR FRACTION FOUR FIFTHS <1> <6> : "⅙" U2159 # VULGAR FRACTION ONE SIXTH <5> <6> : "⅚" U215A # VULGAR FRACTION FIVE SIXTHS <1> <8> : "⅛" U215B # VULGAR FRACTION ONE EIGHTH <3> <8> : "⅜" U215C # VULGAR FRACTION THREE EIGHTHS <5> <8> : "⅝" U215D # VULGAR FRACTION FIVE EIGHTHS <7> <8> : "⅞" U215E # VULGAR FRACTION SEVEN EIGHTHS <0> <3> : "↉" U2189 # VULGAR FRACTION ZERO THIRDS : "↚" U219A # LEFTWARDS ARROW WITH STROKE : "↚" U219A # LEFTWARDS ARROW WITH STROKE : "↛" U219B # RIGHTWARDS ARROW WITH STROKE : "↛" U219B # RIGHTWARDS ARROW WITH STROKE : "↮" U21AE # LEFT RIGHT ARROW WITH STROKE : "↮" U21AE # LEFT RIGHT ARROW WITH STROKE : "←" U2190 # LEFTWARDS ARROW : "→" U2192 # RIGHTWARDS ARROW : "∄" U2204 # THERE DOES NOT EXIST : "∅" U2205 # EMPTY SET : "∉" U2209 # NOT AN ELEMENT OF : "∌" U220C # DOES NOT CONTAIN AS MEMBER : "∤" U2224 # DOES NOT DIVIDE : "∦" U2226 # NOT PARALLEL TO : "≁" U2241 # NOT TILDE : "≄" U2244 # NOT ASYMPTOTICALLY EQUAL TO : "≇" U2247 # NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO : "≉" U2249 # NOT ALMOST EQUAL TO : "≠" U2260 # NOT EQUAL TO : "≠" U2260 # NOT EQUAL TO : "≠" U2260 # NOT EQUAL TO : "≠" U2260 # NOT EQUAL TO : "≢" U2262 # NOT IDENTICAL TO : "≤" U2264 # LESS-THAN OR EQUAL TO : "≥" U2265 # GREATER-THAN OR EQUAL TO : "≭" U226D # NOT EQUIVALENT TO : "≮" U226E # NOT LESS-THAN : "≯" U226F # NOT GREATER-THAN : "≰" U2270 # NEITHER LESS-THAN NOR EQUAL TO : "≱" U2271 # NEITHER GREATER-THAN NOR EQUAL TO : "≴" U2274 # NEITHER LESS-THAN NOR EQUIVALENT TO : "≵" U2275 # NEITHER GREATER-THAN NOR EQUIVALENT TO : "≸" U2278 # NEITHER LESS-THAN NOR GREATER-THAN : "≹" U2279 # NEITHER GREATER-THAN NOR LESS-THAN : "⊀" U2280 # DOES NOT PRECEDE : "⊁" U2281 # DOES NOT SUCCEED : "⊄" U2284 # NOT A SUBSET OF : "⊄" U2284 # NOT A SUBSET OF : "⊅" U2285 # NOT A SUPERSET OF : "⊈" U2288 # NEITHER A SUBSET OF NOR EQUAL TO : "⊉" U2289 # NEITHER A SUPERSET OF NOR EQUAL TO : "⊬" U22AC # DOES NOT PROVE : "⊭" U22AD # NOT TRUE : "⊮" U22AE # DOES NOT FORCE : "⊯" U22AF # NEGATED DOUBLE VERTICAL BAR DOUBLE RIGHT TURNSTILE : "⋠" U22E0 # DOES NOT PRECEDE OR EQUAL : "⋡" U22E1 # DOES NOT SUCCEED OR EQUAL : "⋢" U22E2 # NOT SQUARE IMAGE OF OR EQUAL TO : "⋣" U22E3 # NOT SQUARE ORIGINAL OF OR EQUAL TO : "⋪" U22EA # NOT NORMAL SUBGROUP OF : "⋫" U22EB # DOES NOT CONTAIN AS NORMAL SUBGROUP : "⋬" U22EC # NOT NORMAL SUBGROUP OF OR EQUAL TO : "⋭" U22ED # DOES NOT CONTAIN AS NORMAL SUBGROUP OR EQUAL : "⌀" U2300 # DIAMETER SIGN <1> : "①" U2460 # CIRCLED DIGIT ONE : "①" U2460 # CIRCLED DIGIT ONE <2> : "②" U2461 # CIRCLED DIGIT TWO : "②" U2461 # CIRCLED DIGIT TWO : "②" U2461 # CIRCLED DIGIT TWO <3> : "③" U2462 # CIRCLED DIGIT THREE : "③" U2462 # CIRCLED DIGIT THREE <4> : "④" U2463 # CIRCLED DIGIT FOUR : "④" U2463 # CIRCLED DIGIT FOUR <5> : "⑤" U2464 # CIRCLED DIGIT FIVE : "⑤" U2464 # CIRCLED DIGIT FIVE <6> : "⑥" U2465 # CIRCLED DIGIT SIX : "⑥" U2465 # CIRCLED DIGIT SIX <7> : "⑦" U2466 # CIRCLED DIGIT SEVEN : "⑦" U2466 # CIRCLED DIGIT SEVEN <8> : "⑧" U2467 # CIRCLED DIGIT EIGHT : "⑧" U2467 # CIRCLED DIGIT EIGHT <9> : "⑨" U2468 # CIRCLED DIGIT NINE : "⑨" U2468 # CIRCLED DIGIT NINE <1> <0> : "⑩" U2469 # CIRCLED NUMBER TEN <1> : "⑩" U2469 # CIRCLED NUMBER TEN <0> : "⑩" U2469 # CIRCLED NUMBER TEN : "⑩" U2469 # CIRCLED NUMBER TEN <1> <1> : "⑪" U246A # CIRCLED NUMBER ELEVEN <1> : "⑪" U246A # CIRCLED NUMBER ELEVEN <1> : "⑪" U246A # CIRCLED NUMBER ELEVEN : "⑪" U246A # CIRCLED NUMBER ELEVEN <1> <2> : "⑫" U246B # CIRCLED NUMBER TWELVE <1> : "⑫" U246B # CIRCLED NUMBER TWELVE <1> : "⑫" U246B # CIRCLED NUMBER TWELVE <2> : "⑫" U246B # CIRCLED NUMBER TWELVE : "⑫" U246B # CIRCLED NUMBER TWELVE : "⑫" U246B # CIRCLED NUMBER TWELVE <1> <3> : "⑬" U246C # CIRCLED NUMBER THIRTEEN <1> : "⑬" U246C # CIRCLED NUMBER THIRTEEN <3> : "⑬" U246C # CIRCLED NUMBER THIRTEEN : "⑬" U246C # CIRCLED NUMBER THIRTEEN <1> <4> : "⑭" U246D # CIRCLED NUMBER FOURTEEN <1> : "⑭" U246D # CIRCLED NUMBER FOURTEEN <4> : "⑭" U246D # CIRCLED NUMBER FOURTEEN : "⑭" U246D # CIRCLED NUMBER FOURTEEN <1> <5> : "⑮" U246E # CIRCLED NUMBER FIFTEEN <1> : "⑮" U246E # CIRCLED NUMBER FIFTEEN <5> : "⑮" U246E # CIRCLED NUMBER FIFTEEN : "⑮" U246E # CIRCLED NUMBER FIFTEEN <1> <6> : "⑯" U246F # CIRCLED NUMBER SIXTEEN <1> : "⑯" U246F # CIRCLED NUMBER SIXTEEN <6> : "⑯" U246F # CIRCLED NUMBER SIXTEEN : "⑯" U246F # CIRCLED NUMBER SIXTEEN <1> <7> : "⑰" U2470 # CIRCLED NUMBER SEVENTEEN <1> : "⑰" U2470 # CIRCLED NUMBER SEVENTEEN <7> : "⑰" U2470 # CIRCLED NUMBER SEVENTEEN : "⑰" U2470 # CIRCLED NUMBER SEVENTEEN <1> <8> : "⑱" U2471 # CIRCLED NUMBER EIGHTEEN <1> : "⑱" U2471 # CIRCLED NUMBER EIGHTEEN <8> : "⑱" U2471 # CIRCLED NUMBER EIGHTEEN : "⑱" U2471 # CIRCLED NUMBER EIGHTEEN <1> <9> : "⑲" U2472 # CIRCLED NUMBER NINETEEN <1> : "⑲" U2472 # CIRCLED NUMBER NINETEEN <9> : "⑲" U2472 # CIRCLED NUMBER NINETEEN : "⑲" U2472 # CIRCLED NUMBER NINETEEN <2> <0> : "⑳" U2473 # CIRCLED NUMBER TWENTY <2> : "⑳" U2473 # CIRCLED NUMBER TWENTY <0> : "⑳" U2473 # CIRCLED NUMBER TWENTY : "⑳" U2473 # CIRCLED NUMBER TWENTY <0> : "⑳" U2473 # CIRCLED NUMBER TWENTY : "⑳" U2473 # CIRCLED NUMBER TWENTY : "Ⓐ" U24B6 # CIRCLED LATIN CAPITAL LETTER A : "Ⓑ" U24B7 # CIRCLED LATIN CAPITAL LETTER B : "Ⓒ" U24B8 # CIRCLED LATIN CAPITAL LETTER C : "Ⓓ" U24B9 # CIRCLED LATIN CAPITAL LETTER D : "Ⓔ" U24BA # CIRCLED LATIN CAPITAL LETTER E : "Ⓕ" U24BB # CIRCLED LATIN CAPITAL LETTER F : "Ⓖ" U24BC # CIRCLED LATIN CAPITAL LETTER G : "Ⓗ" U24BD # CIRCLED LATIN CAPITAL LETTER H : "Ⓘ" U24BE # CIRCLED LATIN CAPITAL LETTER I : "Ⓙ" U24BF # CIRCLED LATIN CAPITAL LETTER J : "Ⓚ" U24C0 # CIRCLED LATIN CAPITAL LETTER K : "Ⓛ" U24C1 # CIRCLED LATIN CAPITAL LETTER L : "Ⓜ" U24C2 # CIRCLED LATIN CAPITAL LETTER M : "Ⓝ" U24C3 # CIRCLED LATIN CAPITAL LETTER N : "Ⓞ" U24C4 # CIRCLED LATIN CAPITAL LETTER O

: "Ⓟ" U24C5 # CIRCLED LATIN CAPITAL LETTER P : "Ⓠ" U24C6 # CIRCLED LATIN CAPITAL LETTER Q : "Ⓡ" U24C7 # CIRCLED LATIN CAPITAL LETTER R : "Ⓢ" U24C8 # CIRCLED LATIN CAPITAL LETTER S : "Ⓣ" U24C9 # CIRCLED LATIN CAPITAL LETTER T : "Ⓤ" U24CA # CIRCLED LATIN CAPITAL LETTER U : "Ⓥ" U24CB # CIRCLED LATIN CAPITAL LETTER V : "Ⓦ" U24CC # CIRCLED LATIN CAPITAL LETTER W : "Ⓧ" U24CD # CIRCLED LATIN CAPITAL LETTER X : "Ⓨ" U24CE # CIRCLED LATIN CAPITAL LETTER Y : "Ⓩ" U24CF # CIRCLED LATIN CAPITAL LETTER Z : "ⓐ" U24D0 # CIRCLED LATIN SMALL LETTER A : "ⓑ" U24D1 # CIRCLED LATIN SMALL LETTER B : "ⓒ" U24D2 # CIRCLED LATIN SMALL LETTER C : "ⓓ" U24D3 # CIRCLED LATIN SMALL LETTER D : "ⓔ" U24D4 # CIRCLED LATIN SMALL LETTER E : "ⓕ" U24D5 # CIRCLED LATIN SMALL LETTER F : "ⓖ" U24D6 # CIRCLED LATIN SMALL LETTER G : "ⓗ" U24D7 # CIRCLED LATIN SMALL LETTER H : "ⓘ" U24D8 # CIRCLED LATIN SMALL LETTER I : "ⓙ" U24D9 # CIRCLED LATIN SMALL LETTER J : "ⓚ" U24DA # CIRCLED LATIN SMALL LETTER K : "ⓛ" U24DB # CIRCLED LATIN SMALL LETTER L : "ⓜ" U24DC # CIRCLED LATIN SMALL LETTER M : "ⓝ" U24DD # CIRCLED LATIN SMALL LETTER N : "ⓞ" U24DE # CIRCLED LATIN SMALL LETTER O

: "ⓟ" U24DF # CIRCLED LATIN SMALL LETTER P : "ⓠ" U24E0 # CIRCLED LATIN SMALL LETTER Q : "ⓡ" U24E1 # CIRCLED LATIN SMALL LETTER R : "ⓢ" U24E2 # CIRCLED LATIN SMALL LETTER S : "ⓣ" U24E3 # CIRCLED LATIN SMALL LETTER T : "ⓤ" U24E4 # CIRCLED LATIN SMALL LETTER U : "ⓥ" U24E5 # CIRCLED LATIN SMALL LETTER V : "ⓦ" U24E6 # CIRCLED LATIN SMALL LETTER W : "ⓧ" U24E7 # CIRCLED LATIN SMALL LETTER X : "ⓨ" U24E8 # CIRCLED LATIN SMALL LETTER Y : "ⓩ" U24E9 # CIRCLED LATIN SMALL LETTER Z <0> : "⓪" U24EA # CIRCLED DIGIT ZERO : "⓪" U24EA # CIRCLED DIGIT ZERO : "⨥" U2A25 # PLUS SIGN WITH DOT BELOW : "⨦" U2A26 # PLUS SIGN WITH TILDE BELOW : "⨪" U2A2A # MINUS SIGN WITH DOT BELOW : "⩦" U2A66 # EQUALS SIGN WITH DOT BELOW : "⩷" U2A77 # EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW : "⩷" U2A77 # EQUALS SIGN WITH TWO DOTS ABOVE AND TWO DOTS BELOW : "⫝̸" U2ADC # FORKING : "⫰" U2AF0 # VERTICAL LINE WITH CIRCLE BELOW : "が" U304C # HIRAGANA LETTER GA : "ぎ" U304E # HIRAGANA LETTER GI : "ぐ" U3050 # HIRAGANA LETTER GU : "げ" U3052 # HIRAGANA LETTER GE : "ご" U3054 # HIRAGANA LETTER GO : "ざ" U3056 # HIRAGANA LETTER ZA : "じ" U3058 # HIRAGANA LETTER ZI : "ず" U305A # HIRAGANA LETTER ZU : "ぜ" U305C # HIRAGANA LETTER ZE : "ぞ" U305E # HIRAGANA LETTER ZO : "だ" U3060 # HIRAGANA LETTER DA : "ぢ" U3062 # HIRAGANA LETTER DI : "づ" U3065 # HIRAGANA LETTER DU : "で" U3067 # HIRAGANA LETTER DE : "ど" U3069 # HIRAGANA LETTER DO : "ば" U3070 # HIRAGANA LETTER BA : "ぱ" U3071 # HIRAGANA LETTER PA : "び" U3073 # HIRAGANA LETTER BI : "ぴ" U3074 # HIRAGANA LETTER PI : "ぶ" U3076 # HIRAGANA LETTER BU : "ぷ" U3077 # HIRAGANA LETTER PU : "べ" U3079 # HIRAGANA LETTER BE : "ぺ" U307A # HIRAGANA LETTER PE : "ぼ" U307C # HIRAGANA LETTER BO : "ぽ" U307D # HIRAGANA LETTER PO : "ゔ" U3094 # HIRAGANA LETTER VU : "ゞ" U309E # HIRAGANA VOICED ITERATION MARK : "ガ" U30AC # KATAKANA LETTER GA : "ギ" U30AE # KATAKANA LETTER GI : "グ" U30B0 # KATAKANA LETTER GU : "ゲ" U30B2 # KATAKANA LETTER GE : "ゴ" U30B4 # KATAKANA LETTER GO : "ザ" U30B6 # KATAKANA LETTER ZA : "ジ" U30B8 # KATAKANA LETTER ZI : "ズ" U30BA # KATAKANA LETTER ZU : "ゼ" U30BC # KATAKANA LETTER ZE : "ゾ" U30BE # KATAKANA LETTER ZO : "ダ" U30C0 # KATAKANA LETTER DA : "ヂ" U30C2 # KATAKANA LETTER DI : "ヅ" U30C5 # KATAKANA LETTER DU : "デ" U30C7 # KATAKANA LETTER DE : "ド" U30C9 # KATAKANA LETTER DO : "バ" U30D0 # KATAKANA LETTER BA : "パ" U30D1 # KATAKANA LETTER PA : "ビ" U30D3 # KATAKANA LETTER BI : "ピ" U30D4 # KATAKANA LETTER PI : "ブ" U30D6 # KATAKANA LETTER BU : "プ" U30D7 # KATAKANA LETTER PU : "ベ" U30D9 # KATAKANA LETTER BE : "ペ" U30DA # KATAKANA LETTER PE : "ボ" U30DC # KATAKANA LETTER BO : "ポ" U30DD # KATAKANA LETTER PO : "ヴ" U30F4 # KATAKANA LETTER VU : "ヷ" U30F7 # KATAKANA LETTER VA : "ヸ" U30F8 # KATAKANA LETTER VI : "ヹ" U30F9 # KATAKANA LETTER VE : "ヺ" U30FA # KATAKANA LETTER VO : "ヾ" U30FE # KATAKANA VOICED ITERATION MARK : "㆒" U3192 # IDEOGRAPHIC ANNOTATION ONE MARK : "㆒" U3192 # IDEOGRAPHIC ANNOTATION ONE MARK : "㆓" U3193 # IDEOGRAPHIC ANNOTATION TWO MARK : "㆓" U3193 # IDEOGRAPHIC ANNOTATION TWO MARK : "㆔" U3194 # IDEOGRAPHIC ANNOTATION THREE MARK : "㆔" U3194 # IDEOGRAPHIC ANNOTATION THREE MARK : "㆕" U3195 # IDEOGRAPHIC ANNOTATION FOUR MARK : "㆕" U3195 # IDEOGRAPHIC ANNOTATION FOUR MARK : "㆖" U3196 # IDEOGRAPHIC ANNOTATION TOP MARK : "㆖" U3196 # IDEOGRAPHIC ANNOTATION TOP MARK : "㆗" U3197 # IDEOGRAPHIC ANNOTATION MIDDLE MARK : "㆗" U3197 # IDEOGRAPHIC ANNOTATION MIDDLE MARK : "㆘" U3198 # IDEOGRAPHIC ANNOTATION BOTTOM MARK : "㆘" U3198 # IDEOGRAPHIC ANNOTATION BOTTOM MARK : "㆙" U3199 # IDEOGRAPHIC ANNOTATION FIRST MARK : "㆙" U3199 # IDEOGRAPHIC ANNOTATION FIRST MARK : "㆚" U319A # IDEOGRAPHIC ANNOTATION SECOND MARK : "㆚" U319A # IDEOGRAPHIC ANNOTATION SECOND MARK : "㆛" U319B # IDEOGRAPHIC ANNOTATION THIRD MARK : "㆛" U319B # IDEOGRAPHIC ANNOTATION THIRD MARK : "㆜" U319C # IDEOGRAPHIC ANNOTATION FOURTH MARK : "㆜" U319C # IDEOGRAPHIC ANNOTATION FOURTH MARK : "㆝" U319D # IDEOGRAPHIC ANNOTATION HEAVEN MARK : "㆝" U319D # IDEOGRAPHIC ANNOTATION HEAVEN MARK : "㆞" U319E # IDEOGRAPHIC ANNOTATION EARTH MARK : "㆞" U319E # IDEOGRAPHIC ANNOTATION EARTH MARK : "㆟" U319F # IDEOGRAPHIC ANNOTATION MAN MARK : "㆟" U319F # IDEOGRAPHIC ANNOTATION MAN MARK <2> <1> : "㉑" U3251 # CIRCLED NUMBER TWENTY ONE <2> : "㉑" U3251 # CIRCLED NUMBER TWENTY ONE <1> : "㉑" U3251 # CIRCLED NUMBER TWENTY ONE : "㉑" U3251 # CIRCLED NUMBER TWENTY ONE <1> : "㉑" U3251 # CIRCLED NUMBER TWENTY ONE : "㉑" U3251 # CIRCLED NUMBER TWENTY ONE <2> <2> : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO <2> : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO <2> : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO <2> : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO <2> : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO : "㉒" U3252 # CIRCLED NUMBER TWENTY TWO <2> <3> : "㉓" U3253 # CIRCLED NUMBER TWENTY THREE <2> : "㉓" U3253 # CIRCLED NUMBER TWENTY THREE <3> : "㉓" U3253 # CIRCLED NUMBER TWENTY THREE : "㉓" U3253 # CIRCLED NUMBER TWENTY THREE <3> : "㉓" U3253 # CIRCLED NUMBER TWENTY THREE : "㉓" U3253 # CIRCLED NUMBER TWENTY THREE <2> <4> : "㉔" U3254 # CIRCLED NUMBER TWENTY FOUR <2> : "㉔" U3254 # CIRCLED NUMBER TWENTY FOUR <4> : "㉔" U3254 # CIRCLED NUMBER TWENTY FOUR : "㉔" U3254 # CIRCLED NUMBER TWENTY FOUR <4> : "㉔" U3254 # CIRCLED NUMBER TWENTY FOUR : "㉔" U3254 # CIRCLED NUMBER TWENTY FOUR <2> <5> : "㉕" U3255 # CIRCLED NUMBER TWENTY FIVE <2> : "㉕" U3255 # CIRCLED NUMBER TWENTY FIVE <5> : "㉕" U3255 # CIRCLED NUMBER TWENTY FIVE : "㉕" U3255 # CIRCLED NUMBER TWENTY FIVE <5> : "㉕" U3255 # CIRCLED NUMBER TWENTY FIVE : "㉕" U3255 # CIRCLED NUMBER TWENTY FIVE <2> <6> : "㉖" U3256 # CIRCLED NUMBER TWENTY SIX <2> : "㉖" U3256 # CIRCLED NUMBER TWENTY SIX <6> : "㉖" U3256 # CIRCLED NUMBER TWENTY SIX : "㉖" U3256 # CIRCLED NUMBER TWENTY SIX <6> : "㉖" U3256 # CIRCLED NUMBER TWENTY SIX : "㉖" U3256 # CIRCLED NUMBER TWENTY SIX <2> <7> : "㉗" U3257 # CIRCLED NUMBER TWENTY SEVEN <2> : "㉗" U3257 # CIRCLED NUMBER TWENTY SEVEN <7> : "㉗" U3257 # CIRCLED NUMBER TWENTY SEVEN : "㉗" U3257 # CIRCLED NUMBER TWENTY SEVEN <7> : "㉗" U3257 # CIRCLED NUMBER TWENTY SEVEN : "㉗" U3257 # CIRCLED NUMBER TWENTY SEVEN <2> <8> : "㉘" U3258 # CIRCLED NUMBER TWENTY EIGHT <2> : "㉘" U3258 # CIRCLED NUMBER TWENTY EIGHT <8> : "㉘" U3258 # CIRCLED NUMBER TWENTY EIGHT : "㉘" U3258 # CIRCLED NUMBER TWENTY EIGHT <8> : "㉘" U3258 # CIRCLED NUMBER TWENTY EIGHT : "㉘" U3258 # CIRCLED NUMBER TWENTY EIGHT <2> <9> : "㉙" U3259 # CIRCLED NUMBER TWENTY NINE <2> : "㉙" U3259 # CIRCLED NUMBER TWENTY NINE <9> : "㉙" U3259 # CIRCLED NUMBER TWENTY NINE : "㉙" U3259 # CIRCLED NUMBER TWENTY NINE <9> : "㉙" U3259 # CIRCLED NUMBER TWENTY NINE : "㉙" U3259 # CIRCLED NUMBER TWENTY NINE <3> <0> : "㉚" U325A # CIRCLED NUMBER THIRTY <3> : "㉚" U325A # CIRCLED NUMBER THIRTY <0> : "㉚" U325A # CIRCLED NUMBER THIRTY : "㉚" U325A # CIRCLED NUMBER THIRTY <3> <1> : "㉛" U325B # CIRCLED NUMBER THIRTY ONE <3> : "㉛" U325B # CIRCLED NUMBER THIRTY ONE <1> : "㉛" U325B # CIRCLED NUMBER THIRTY ONE : "㉛" U325B # CIRCLED NUMBER THIRTY ONE <3> <2> : "㉜" U325C # CIRCLED NUMBER THIRTY TWO <3> : "㉜" U325C # CIRCLED NUMBER THIRTY TWO <3> : "㉜" U325C # CIRCLED NUMBER THIRTY TWO <2> : "㉜" U325C # CIRCLED NUMBER THIRTY TWO : "㉜" U325C # CIRCLED NUMBER THIRTY TWO : "㉜" U325C # CIRCLED NUMBER THIRTY TWO <3> <3> : "㉝" U325D # CIRCLED NUMBER THIRTY THREE <3> : "㉝" U325D # CIRCLED NUMBER THIRTY THREE <3> : "㉝" U325D # CIRCLED NUMBER THIRTY THREE : "㉝" U325D # CIRCLED NUMBER THIRTY THREE <3> <4> : "㉞" U325E # CIRCLED NUMBER THIRTY FOUR <3> : "㉞" U325E # CIRCLED NUMBER THIRTY FOUR <4> : "㉞" U325E # CIRCLED NUMBER THIRTY FOUR : "㉞" U325E # CIRCLED NUMBER THIRTY FOUR <3> <5> : "㉟" U325F # CIRCLED NUMBER THIRTY FIVE <3> : "㉟" U325F # CIRCLED NUMBER THIRTY FIVE <5> : "㉟" U325F # CIRCLED NUMBER THIRTY FIVE : "㉟" U325F # CIRCLED NUMBER THIRTY FIVE : "㉠" U3260 # CIRCLED HANGUL KIYEOK : "㉡" U3261 # CIRCLED HANGUL NIEUN : "㉢" U3262 # CIRCLED HANGUL TIKEUT : "㉣" U3263 # CIRCLED HANGUL RIEUL : "㉤" U3264 # CIRCLED HANGUL MIEUM : "㉥" U3265 # CIRCLED HANGUL PIEUP : "㉦" U3266 # CIRCLED HANGUL SIOS : "㉧" U3267 # CIRCLED HANGUL IEUNG : "㉨" U3268 # CIRCLED HANGUL CIEUC : "㉩" U3269 # CIRCLED HANGUL CHIEUCH : "㉪" U326A # CIRCLED HANGUL KHIEUKH : "㉫" U326B # CIRCLED HANGUL THIEUTH : "㉬" U326C # CIRCLED HANGUL PHIEUPH : "㉭" U326D # CIRCLED HANGUL HIEUH : "㉮" U326E # CIRCLED HANGUL KIYEOK A : "㉯" U326F # CIRCLED HANGUL NIEUN A : "㉰" U3270 # CIRCLED HANGUL TIKEUT A : "㉱" U3271 # CIRCLED HANGUL RIEUL A : "㉲" U3272 # CIRCLED HANGUL MIEUM A : "㉳" U3273 # CIRCLED HANGUL PIEUP A : "㉴" U3274 # CIRCLED HANGUL SIOS A : "㉵" U3275 # CIRCLED HANGUL IEUNG A : "㉶" U3276 # CIRCLED HANGUL CIEUC A : "㉷" U3277 # CIRCLED HANGUL CHIEUCH A : "㉸" U3278 # CIRCLED HANGUL KHIEUKH A : "㉹" U3279 # CIRCLED HANGUL THIEUTH A : "㉺" U327A # CIRCLED HANGUL PHIEUPH A : "㉻" U327B # CIRCLED HANGUL HIEUH A : "㊀" U3280 # CIRCLED IDEOGRAPH ONE : "㊁" U3281 # CIRCLED IDEOGRAPH TWO : "㊂" U3282 # CIRCLED IDEOGRAPH THREE : "㊃" U3283 # CIRCLED IDEOGRAPH FOUR : "㊄" U3284 # CIRCLED IDEOGRAPH FIVE : "㊅" U3285 # CIRCLED IDEOGRAPH SIX : "㊆" U3286 # CIRCLED IDEOGRAPH SEVEN : "㊇" U3287 # CIRCLED IDEOGRAPH EIGHT : "㊈" U3288 # CIRCLED IDEOGRAPH NINE : "㊉" U3289 # CIRCLED IDEOGRAPH TEN : "㊊" U328A # CIRCLED IDEOGRAPH MOON : "㊋" U328B # CIRCLED IDEOGRAPH FIRE : "㊌" U328C # CIRCLED IDEOGRAPH WATER : "㊍" U328D # CIRCLED IDEOGRAPH WOOD : "㊎" U328E # CIRCLED IDEOGRAPH METAL : "㊏" U328F # CIRCLED IDEOGRAPH EARTH : "㊐" U3290 # CIRCLED IDEOGRAPH SUN : "㊑" U3291 # CIRCLED IDEOGRAPH STOCK : "㊒" U3292 # CIRCLED IDEOGRAPH HAVE : "㊓" U3293 # CIRCLED IDEOGRAPH SOCIETY : "㊔" U3294 # CIRCLED IDEOGRAPH NAME : "㊕" U3295 # CIRCLED IDEOGRAPH SPECIAL : "㊖" U3296 # CIRCLED IDEOGRAPH FINANCIAL : "㊗" U3297 # CIRCLED IDEOGRAPH CONGRATULATION : "㊘" U3298 # CIRCLED IDEOGRAPH LABOR : "㊙" U3299 # CIRCLED IDEOGRAPH SECRET : "㊚" U329A # CIRCLED IDEOGRAPH MALE : "㊛" U329B # CIRCLED IDEOGRAPH FEMALE : "㊜" U329C # CIRCLED IDEOGRAPH SUITABLE : "㊝" U329D # CIRCLED IDEOGRAPH EXCELLENT : "㊞" U329E # CIRCLED IDEOGRAPH PRINT : "㊟" U329F # CIRCLED IDEOGRAPH ATTENTION : "㊠" U32A0 # CIRCLED IDEOGRAPH ITEM : "㊡" U32A1 # CIRCLED IDEOGRAPH REST : "㊢" U32A2 # CIRCLED IDEOGRAPH COPY : "㊣" U32A3 # CIRCLED IDEOGRAPH CORRECT : "㊤" U32A4 # CIRCLED IDEOGRAPH HIGH : "㊥" U32A5 # CIRCLED IDEOGRAPH CENTRE : "㊦" U32A6 # CIRCLED IDEOGRAPH LOW : "㊧" U32A7 # CIRCLED IDEOGRAPH LEFT : "㊨" U32A8 # CIRCLED IDEOGRAPH RIGHT : "㊩" U32A9 # CIRCLED IDEOGRAPH MEDICINE : "㊪" U32AA # CIRCLED IDEOGRAPH RELIGION : "㊫" U32AB # CIRCLED IDEOGRAPH STUDY : "㊬" U32AC # CIRCLED IDEOGRAPH SUPERVISE : "㊭" U32AD # CIRCLED IDEOGRAPH ENTERPRISE : "㊮" U32AE # CIRCLED IDEOGRAPH RESOURCE : "㊯" U32AF # CIRCLED IDEOGRAPH ALLIANCE : "㊰" U32B0 # CIRCLED IDEOGRAPH NIGHT <3> <6> : "㊱" U32B1 # CIRCLED NUMBER THIRTY SIX <3> : "㊱" U32B1 # CIRCLED NUMBER THIRTY SIX <6> : "㊱" U32B1 # CIRCLED NUMBER THIRTY SIX : "㊱" U32B1 # CIRCLED NUMBER THIRTY SIX <3> <7> : "㊲" U32B2 # CIRCLED NUMBER THIRTY SEVEN <3> : "㊲" U32B2 # CIRCLED NUMBER THIRTY SEVEN <7> : "㊲" U32B2 # CIRCLED NUMBER THIRTY SEVEN : "㊲" U32B2 # CIRCLED NUMBER THIRTY SEVEN <3> <8> : "㊳" U32B3 # CIRCLED NUMBER THIRTY EIGHT <3> : "㊳" U32B3 # CIRCLED NUMBER THIRTY EIGHT <8> : "㊳" U32B3 # CIRCLED NUMBER THIRTY EIGHT : "㊳" U32B3 # CIRCLED NUMBER THIRTY EIGHT <3> <9> : "㊴" U32B4 # CIRCLED NUMBER THIRTY NINE <3> : "㊴" U32B4 # CIRCLED NUMBER THIRTY NINE <9> : "㊴" U32B4 # CIRCLED NUMBER THIRTY NINE : "㊴" U32B4 # CIRCLED NUMBER THIRTY NINE <4> <0> : "㊵" U32B5 # CIRCLED NUMBER FORTY <4> : "㊵" U32B5 # CIRCLED NUMBER FORTY <0> : "㊵" U32B5 # CIRCLED NUMBER FORTY : "㊵" U32B5 # CIRCLED NUMBER FORTY <4> <1> : "㊶" U32B6 # CIRCLED NUMBER FORTY ONE <4> : "㊶" U32B6 # CIRCLED NUMBER FORTY ONE <1> : "㊶" U32B6 # CIRCLED NUMBER FORTY ONE : "㊶" U32B6 # CIRCLED NUMBER FORTY ONE <4> <2> : "㊷" U32B7 # CIRCLED NUMBER FORTY TWO <4> : "㊷" U32B7 # CIRCLED NUMBER FORTY TWO <4> : "㊷" U32B7 # CIRCLED NUMBER FORTY TWO <2> : "㊷" U32B7 # CIRCLED NUMBER FORTY TWO : "㊷" U32B7 # CIRCLED NUMBER FORTY TWO : "㊷" U32B7 # CIRCLED NUMBER FORTY TWO <4> <3> : "㊸" U32B8 # CIRCLED NUMBER FORTY THREE <4> : "㊸" U32B8 # CIRCLED NUMBER FORTY THREE <3> : "㊸" U32B8 # CIRCLED NUMBER FORTY THREE : "㊸" U32B8 # CIRCLED NUMBER FORTY THREE <4> <4> : "㊹" U32B9 # CIRCLED NUMBER FORTY FOUR <4> : "㊹" U32B9 # CIRCLED NUMBER FORTY FOUR <4> : "㊹" U32B9 # CIRCLED NUMBER FORTY FOUR : "㊹" U32B9 # CIRCLED NUMBER FORTY FOUR <4> <5> : "㊺" U32BA # CIRCLED NUMBER FORTY FIVE <4> : "㊺" U32BA # CIRCLED NUMBER FORTY FIVE <5> : "㊺" U32BA # CIRCLED NUMBER FORTY FIVE : "㊺" U32BA # CIRCLED NUMBER FORTY FIVE <4> <6> : "㊻" U32BB # CIRCLED NUMBER FORTY SIX <4> : "㊻" U32BB # CIRCLED NUMBER FORTY SIX <6> : "㊻" U32BB # CIRCLED NUMBER FORTY SIX : "㊻" U32BB # CIRCLED NUMBER FORTY SIX <4> <7> : "㊼" U32BC # CIRCLED NUMBER FORTY SEVEN <4> : "㊼" U32BC # CIRCLED NUMBER FORTY SEVEN <7> : "㊼" U32BC # CIRCLED NUMBER FORTY SEVEN : "㊼" U32BC # CIRCLED NUMBER FORTY SEVEN <4> <8> : "㊽" U32BD # CIRCLED NUMBER FORTY EIGHT <4> : "㊽" U32BD # CIRCLED NUMBER FORTY EIGHT <8> : "㊽" U32BD # CIRCLED NUMBER FORTY EIGHT : "㊽" U32BD # CIRCLED NUMBER FORTY EIGHT <4> <9> : "㊾" U32BE # CIRCLED NUMBER FORTY NINE <4> : "㊾" U32BE # CIRCLED NUMBER FORTY NINE <9> : "㊾" U32BE # CIRCLED NUMBER FORTY NINE : "㊾" U32BE # CIRCLED NUMBER FORTY NINE <5> <0> : "㊿" U32BF # CIRCLED NUMBER FIFTY <5> : "㊿" U32BF # CIRCLED NUMBER FIFTY <0> : "㊿" U32BF # CIRCLED NUMBER FIFTY : "㊿" U32BF # CIRCLED NUMBER FIFTY : "㋐" U32D0 # CIRCLED KATAKANA A : "㋑" U32D1 # CIRCLED KATAKANA I : "㋒" U32D2 # CIRCLED KATAKANA U : "㋓" U32D3 # CIRCLED KATAKANA E : "㋔" U32D4 # CIRCLED KATAKANA O : "㋕" U32D5 # CIRCLED KATAKANA KA : "㋖" U32D6 # CIRCLED KATAKANA KI : "㋗" U32D7 # CIRCLED KATAKANA KU : "㋘" U32D8 # CIRCLED KATAKANA KE : "㋙" U32D9 # CIRCLED KATAKANA KO : "㋚" U32DA # CIRCLED KATAKANA SA : "㋛" U32DB # CIRCLED KATAKANA SI : "㋜" U32DC # CIRCLED KATAKANA SU : "㋝" U32DD # CIRCLED KATAKANA SE : "㋞" U32DE # CIRCLED KATAKANA SO : "㋟" U32DF # CIRCLED KATAKANA TA : "㋠" U32E0 # CIRCLED KATAKANA TI : "㋡" U32E1 # CIRCLED KATAKANA TU : "㋢" U32E2 # CIRCLED KATAKANA TE : "㋣" U32E3 # CIRCLED KATAKANA TO : "㋤" U32E4 # CIRCLED KATAKANA NA : "㋥" U32E5 # CIRCLED KATAKANA NI : "㋦" U32E6 # CIRCLED KATAKANA NU : "㋧" U32E7 # CIRCLED KATAKANA NE : "㋨" U32E8 # CIRCLED KATAKANA NO : "㋩" U32E9 # CIRCLED KATAKANA HA : "㋪" U32EA # CIRCLED KATAKANA HI : "㋫" U32EB # CIRCLED KATAKANA HU : "㋬" U32EC # CIRCLED KATAKANA HE : "㋭" U32ED # CIRCLED KATAKANA HO : "㋮" U32EE # CIRCLED KATAKANA MA : "㋯" U32EF # CIRCLED KATAKANA MI : "㋰" U32F0 # CIRCLED KATAKANA MU : "㋱" U32F1 # CIRCLED KATAKANA ME : "㋲" U32F2 # CIRCLED KATAKANA MO : "㋳" U32F3 # CIRCLED KATAKANA YA : "㋴" U32F4 # CIRCLED KATAKANA YU : "㋵" U32F5 # CIRCLED KATAKANA YO : "㋶" U32F6 # CIRCLED KATAKANA RA : "㋷" U32F7 # CIRCLED KATAKANA RI : "㋸" U32F8 # CIRCLED KATAKANA RU : "㋹" U32F9 # CIRCLED KATAKANA RE : "㋺" U32FA # CIRCLED KATAKANA RO : "㋻" U32FB # CIRCLED KATAKANA WA : "㋼" U32FC # CIRCLED KATAKANA WI : "㋽" U32FD # CIRCLED KATAKANA WE : "㋾" U32FE # CIRCLED KATAKANA WO : "יִ" UFB1D # HEBREW LETTER YOD WITH HIRIQ : "ײַ" UFB1F # HEBREW LIGATURE YIDDISH YOD YOD PATAH : "שׁ" UFB2A # HEBREW LETTER SHIN WITH SHIN DOT : "שׂ" UFB2B # HEBREW LETTER SHIN WITH SIN DOT : "שּׁ" UFB2C # HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT : "שּׁ" UFB2C # HEBREW LETTER SHIN WITH DAGESH AND SHIN DOT : "שּׂ" UFB2D # HEBREW LETTER SHIN WITH DAGESH AND SIN DOT : "שּׂ" UFB2D # HEBREW LETTER SHIN WITH DAGESH AND SIN DOT : "אַ" UFB2E # HEBREW LETTER ALEF WITH PATAH : "אָ" UFB2F # HEBREW LETTER ALEF WITH QAMATS : "אּ" UFB30 # HEBREW LETTER ALEF WITH MAPIQ : "בּ" UFB31 # HEBREW LETTER BET WITH DAGESH : "גּ" UFB32 # HEBREW LETTER GIMEL WITH DAGESH : "דּ" UFB33 # HEBREW LETTER DALET WITH DAGESH : "הּ" UFB34 # HEBREW LETTER HE WITH MAPIQ : "וּ" UFB35 # HEBREW LETTER VAV WITH DAGESH : "זּ" UFB36 # HEBREW LETTER ZAYIN WITH DAGESH : "טּ" UFB38 # HEBREW LETTER TET WITH DAGESH : "יּ" UFB39 # HEBREW LETTER YOD WITH DAGESH : "ךּ" UFB3A # HEBREW LETTER FINAL KAF WITH DAGESH : "כּ" UFB3B # HEBREW LETTER KAF WITH DAGESH : "לּ" UFB3C # HEBREW LETTER LAMED WITH DAGESH : "מּ" UFB3E # HEBREW LETTER MEM WITH DAGESH : "נּ" UFB40 # HEBREW LETTER NUN WITH DAGESH : "סּ" UFB41 # HEBREW LETTER SAMEKH WITH DAGESH : "ףּ" UFB43 # HEBREW LETTER FINAL PE WITH DAGESH : "פּ" UFB44 # HEBREW LETTER PE WITH DAGESH : "צּ" UFB46 # HEBREW LETTER TSADI WITH DAGESH : "קּ" UFB47 # HEBREW LETTER QOF WITH DAGESH : "רּ" UFB48 # HEBREW LETTER RESH WITH DAGESH : "שּ" UFB49 # HEBREW LETTER SHIN WITH DAGESH : "תּ" UFB4A # HEBREW LETTER TAV WITH DAGESH : "וֹ" UFB4B # HEBREW LETTER VAV WITH HOLAM : "בֿ" UFB4C # HEBREW LETTER BET WITH RAFE : "כֿ" UFB4D # HEBREW LETTER KAF WITH RAFE : "פֿ" UFB4E # HEBREW LETTER PE WITH RAFE : "𝅗𝅥" U1D15E # MUSICAL SYMBOL HALF NOTE : "𝅘𝅥" U1D15F # MUSICAL SYMBOL QUARTER NOTE : "𝅘𝅥𝅮" U1D160 # MUSICAL SYMBOL EIGHTH NOTE : "𝅘𝅥𝅯" U1D161 # MUSICAL SYMBOL SIXTEENTH NOTE : "𝅘𝅥𝅰" U1D162 # MUSICAL SYMBOL THIRTY-SECOND NOTE : "𝅘𝅥𝅱" U1D163 # MUSICAL SYMBOL SIXTY-FOURTH NOTE : "𝅘𝅥𝅲" U1D164 # MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE : "𝆹𝅥" U1D1BB # MUSICAL SYMBOL MINIMA : "𝆺𝅥" U1D1BC # MUSICAL SYMBOL MINIMA BLACK : "𝆹𝅥𝅮" U1D1BD # MUSICAL SYMBOL SEMIMINIMA WHITE : "𝆺𝅥𝅮" U1D1BE # MUSICAL SYMBOL SEMIMINIMA BLACK : "𝆹𝅥𝅯" U1D1BF # MUSICAL SYMBOL FUSA WHITE : "𝆺𝅥𝅯" U1D1C0 # MUSICAL SYMBOL FUSA BLACK # # Khmer digraphs # : "ាំ" : "ោះ" : "េះ" : "ុំ" : "ុះ" # # Arabic Lam-Alef ligatures # : "لا" # ARABIC LIGATURE LAM WITH ALEF : "لأ" # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE : "لإ" # ARABIC LIGATURE LAM WITH ALEF WITH HAMZA BELOW : "لآ" # ARABIC LIGATURE LAM WITH ALEF WITH MADDA ABOVE # # French-Dvorak Bépo compositions # : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "ȷ" U0237 # LATIN SMALL LETTER DOTLESS J : "Ŀ" U013F # LATIN CAPITAL LETTER L WITH MIDDLE DOT : "ŀ" U0140 # LATIN SMALL LETTER L WITH MIDDLE DOT : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "̇" U0307 # COMBINING DOT ABOVE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "́" U0301 # COMBINING ACUTE ACCENT : "Ṩ" U1E68 # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE : "ṩ" U1E69 # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE : "̣" U0323 # COMBINING DOT BELOW : "̣" U0323 # COMBINING DOT BELOW : "̣" U0323 # COMBINING DOT BELOW : "Ắ" Abreveacute # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "Ằ" Abrevegrave # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "Ẳ" Abrevehook # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "Ẵ" Abrevetilde # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "ắ" abreveacute # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "ằ" abrevegrave # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "ẳ" abrevehook # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "ẵ" abrevetilde # LATIN SMALL LETTER A WITH BREVE AND TILDE : "̆" U0306 # COMBINING BREVE : "₍" U208D # SUBSCRIPT LEFT PARENTHESIS : "₎" U208E # SUBSCRIPT RIGHT PARENTHESIS : "₊" U208A # SUBSCRIPT PLUS SIGN : "₋" U208B # SUBSCRIPT MINUS <0> : "₀" zerosubscript # SUBSCRIPT ZERO <1> : "₁" onesubscript # SUBSCRIPT ONE <2> : "₂" twosubscript # SUBSCRIPT TWO <3> : "₃" threesubscript # SUBSCRIPT THREE <4> : "₄" foursubscript # SUBSCRIPT FOUR <5> : "₅" fivesubscript # SUBSCRIPT FIVE <6> : "₆" sixsubscript # SUBSCRIPT SIX <7> : "₇" sevensubscript # SUBSCRIPT SEVEN <8> : "₈" eightsubscript # SUBSCRIPT EIGHT <9> : "₉" ninesubscript # SUBSCRIPT NINE : "₌" U208C # SUBSCRIPT EQUALS SIGN : "Dž" U01C5 # LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON : "Ṧ" U1E66 # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE : "ṧ" U1E67 # LATIN SMALL LETTER S WITH CARON AND DOT ABOVE : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "̌" U030C # COMBINING CARON : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "₵" U20B5 # CEDI SIGN : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "₵" U20B5 # CEDI SIGN : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "̧" U0327 # COMBINING CEDILLA : "⁻" U207B # SUPERSCRIPT MINUS : "Ấ" Acircumflexacute # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ầ" Acircumflexgrave # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE : "Ẩ" Acircumflexhook # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "Ẫ" Acircumflextilde # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE : "ấ" acircumflexacute # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "ầ" acircumflexgrave # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE : "ẩ" acircumflexhook # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "ẫ" acircumflextilde # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE : "Ế" Ecircumflexacute # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ề" Ecircumflexgrave # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE : "Ể" Ecircumflexhook # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "Ễ" Ecircumflextilde # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE : "ế" ecircumflexacute # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "ề" ecircumflexgrave # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE : "ể" ecircumflexhook # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "ễ" ecircumflextilde # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE : "Ố" Ocircumflexacute # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ồ" Ocircumflexgrave # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE : "Ổ" Ocircumflexhook # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "Ỗ" Ocircumflextilde # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE : "ố" ocircumflexacute # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "ồ" ocircumflexgrave # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE : "ổ" ocircumflexhook # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "ỗ" ocircumflextilde # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE : "̂" U0302 # COMBINING CIRCUMFLEX ACCENT : "Ș" U0218 # LATIN CAPITAL LETTER S WITH COMMA BELOW : "ș" U0219 # LATIN SMALL LETTER S WITH COMMA BELOW : "Ț" U021A # LATIN CAPITAL LETTER T WITH COMMA BELOW : "ț" U021B # LATIN SMALL LETTER T WITH COMMA BELOW : "," comma # COMMA : "̦" U0326 # COMBINING COMMA BELOW : "," comma # COMMA : "₳" U20B3 # AUSTRAL SIGN : "؋" U060B # AFGHANI SIGN : "₱" U20B1 # PESO SIGN : "฿" Thai_baht # THAI CURRENCY SYMBOL BAHT : "₵" U20B5 # CEDI SIGN : "₡" ColonSign # COLON SIGN : "₵" U20B5 # CEDI SIGN : "¢" cent # CENT SIGN : "₯" U20AF # DRACHMA SIGN : "₫" DongSign # DONG SIGN : "₠" EcuSign # EURO-CURRENCY SIGN : "€" EuroSign # EURO SIGN : "₣" FFrancSign # FRENCH FRANC SIGN : "ƒ" function # LATIN SMALL LETTER F WITH HOOK : "₲" U20B2 # GUARANI SIGN : "₲" U20B2 # GUARANI SIGN : "₴" U20B4 # HRYVNIA SIGN : "₴" U20B4 # HRYVNIA SIGN : "៛" U17DB # KHMER CURRENCY SYMBOL RIEL : "﷼" UFDFC # RIAL SIGN : "₭" U20AD # KIP SIGN : "₭" U20AD # KIP SIGN : "₤" LiraSign # LIRA SIGN : "£" sterling # POUND SIGN : "ℳ" U2133 # SCRIPT CAPITAL M : "₥" MillSign # MILL SIGN : "₦" NairaSign # NAIRA SIGN : "₦" NairaSign # NAIRA SIGN : "૱" U0AF1 # GUJARATI RUPEE SIGN : "௹" U0BF9 # TAMIL RUPEE SIGN

: "₧" PesetaSign # PESETA SIGN

: "₰" U20B0 # GERMAN PENNY SIGN : "₢" CruzeiroSign # CRUZEIRO SIGN : "₨" RupeeSign # RUPEE SIGN : "$" dollar # DOLLAR SIGN : "₪" NewSheqelSign # NEW SHEQEL SIGN : "₮" U20AE # TUGRIK SIGN : "৳" U09F3 # BENGALI RUPEE SIGN : "৲" U09F2 # BENGALI RUPEE MARK : "৲" U09F2 # BENGALI RUPEE MARK : "圓" U5713 # YUAN / WEN : "元" U5143 # YUAN / WEN : "₩" WonSign # WON SIGN : "₩" WonSign # WON SIGN : "円" U5186 # YEN : "¥" yen # YEN SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN : "¤" currency # CURRENCY SIGN : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "̈" U0308 # COMBINING DIAERESIS : "̋" U030B # COMBINING DOUBLE ACUTE ACCENT : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "̀" U0300 # COMBINING GRAVE ACCENT : "Α" U0391 # GREEK CAPITAL LETTER ALPHA : "α" U03B1 # GREEK SMALL LETTER ALPHA : "Β" U0392 # GREEK CAPITAL LETTER BETA : "β" U03B2 # GREEK SMALL LETTER BETA : "Δ" U0394 # GREEK CAPITAL LETTER DELTA : "δ" U03B4 # GREEK SMALL LETTER DELTA : "Ε" U0395 # GREEK CAPITAL LETTER EPSILON : "ε" U03B5 # GREEK SMALL LETTER EPSILON : "Φ" U03A6 # GREEK CAPITAL LETTER PHI : "φ" U03C6 # GREEK SMALL LETTER PHI : "Γ" U0393 # GREEK CAPITAL LETTER GAMMA : "γ" U03B3 # GREEK SMALL LETTER GAMMA : "Η" U0397 # GREEK CAPITAL LETTER ETA : "η" U03B7 # GREEK SMALL LETTER ETA : "Ι" U0399 # GREEK CAPITAL LETTER IOTA : "ι" U03B9 # GREEK SMALL LETTER IOTA : "Θ" U0398 # GREEK CAPITAL LETTER THETA : "θ" U03B8 # GREEK SMALL LETTER THETA : "Κ" U039A # GREEK CAPITAL LETTER KAPPA : "κ" U03BA # GREEK SMALL LETTER KAPPA : "Λ" U039B # GREEK CAPITAL LETTER LAMDA : "λ" U03BB # GREEK SMALL LETTER LAMDA : "Μ" U039C # GREEK CAPITAL LETTER MU : "μ" U03BC # GREEK SMALL LETTER MU : "Ν" U039D # GREEK CAPITAL LETTER NU : "ν" U03BD # GREEK SMALL LETTER NU : "Ο" U039F # GREEK CAPITAL LETTER OMICRON : "ο" U03BF # GREEK SMALL LETTER OMICRON

: "Π" U03A0 # GREEK CAPITAL LETTER PI

: "π" U03C0 # GREEK SMALL LETTER PI : "Χ" U03A7 # GREEK CAPITAL LETTER CHI : "χ" U03C7 # GREEK SMALL LETTER CHI : "Ρ" U03A1 # GREEK CAPITAL LETTER RHO : "ρ" U03C1 # GREEK SMALL LETTER RHO : "Σ" U03A3 # GREEK CAPITAL LETTER SIGMA : "σ" U03C3 # GREEK SMALL LETTER SIGMA : "Τ" U03A4 # GREEK CAPITAL LETTER TAU : "τ" U03C4 # GREEK SMALL LETTER TAU : "Υ" U03A5 # GREEK CAPITAL LETTER UPSILON : "υ" U03C5 # GREEK SMALL LETTER UPSILON : "Ω" U03A9 # GREEK CAPITAL LETTER OMEGA : "ω" U03C9 # GREEK SMALL LETTER OMEGA : "Ξ" U039E # GREEK CAPITAL LETTER XI : "ξ" U03BE # GREEK SMALL LETTER XI : "Ψ" U03A8 # GREEK CAPITAL LETTER PSI : "ψ" U03C8 # GREEK SMALL LETTER PSI : "Ζ" U0396 # GREEK CAPITAL LETTER ZETA : "ζ" U03B6 # GREEK SMALL LETTER ZETA : "µ" U00B5 # MICRO SIGN : "µ" U00B5 # MICRO SIGN : "µ" U00B5 # MICRO SIGN : "Ɓ" U0181 # LATIN CAPITAL LETTER B WITH HOOK : "ɓ" U0253 # LATIN SMALL LETTER B WITH HOOK : "Ƈ" U0187 # LATIN CAPITAL LETTER C WITH HOOK : "ƈ" U0188 # LATIN SMALL LETTER C WITH HOOK : "Ɗ" U018A # LATIN CAPITAL LETTER D WITH HOOK : "ɗ" U0257 # LATIN SMALL LETTER D WITH HOOK : "ᶑ" U1D91 # LATIN SMALL LETTER D WITH HOOK AND TAIL : "Ƒ" U0191 # LATIN CAPITAL LETTER F WITH HOOK : "ƒ" function # LATIN SMALL LETTER F WITH HOOK : "Ɠ" U0193 # LATIN CAPITAL LETTER G WITH HOOK : "ɠ" U0260 # LATIN SMALL LETTER G WITH HOOK : "ɦ" U0266 # LATIN SMALL LETTER H WITH HOOK : "ʄ" U0284 # LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK : "Ƙ" U0198 # LATIN CAPITAL LETTER K WITH HOOK : "ƙ" U0199 # LATIN SMALL LETTER K WITH HOOK : "Ɱ" U2C6E # LATIN CAPITAL LETTER M WITH HOOK : "ɱ" U0271 # LATIN SMALL LETTER M WITH HOOK : "Ɲ" U019D # LATIN CAPITAL LETTER N WITH LEFT HOOK : "ɲ" U0272 # LATIN SMALL LETTER N WITH LEFT HOOK

: "Ƥ" U01A4 # LATIN CAPITAL LETTER P WITH HOOK

: "ƥ" U01A5 # LATIN SMALL LETTER P WITH HOOK : "ʠ" U02A0 # LATIN SMALL LETTER Q WITH HOOK : "ɝ" U025D # LATIN SMALL LETTER REVERSED OPEN E WITH HOOK : "ɼ" U027C # LATIN SMALL LETTER R WITH LONG LEG : "ʂ" U0282 # LATIN SMALL LETTER S WITH HOOK : "ɚ" U025A # LATIN SMALL LETTER SCHWA WITH HOOK : "Ƭ" U01AC # LATIN CAPITAL LETTER T WITH HOOK : "ƭ" U01AD # LATIN SMALL LETTER T WITH HOOK : "ɻ" U027B # LATIN SMALL LETTER TURNED R WITH HOOK : "Ʋ" U01B2 # LATIN CAPITAL LETTER V WITH HOOK : "ʋ" U028B # LATIN SMALL LETTER V WITH HOOK : "Ⱳ" U2C72 # LATIN CAPITAL LETTER W WITH HOOK : "ⱳ" U2C73 # LATIN SMALL LETTER W WITH HOOK : "Ȥ" U0224 # LATIN CAPITAL LETTER Z WITH HOOK : "ȥ" U0225 # LATIN SMALL LETTER Z WITH HOOK : "̉" U0309 # COMBINING HOOK ABOVE : "̉" U0309 # COMBINING HOOK ABOVE : "̉" U0309 # COMBINING HOOK ABOVE : "Ớ" Ohornacute # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "Ợ" Ohornbelowdot # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW : "Ờ" Ohorngrave # LATIN CAPITAL LETTER O WITH HORN AND GRAVE : "Ở" Ohornhook # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE : "Ỡ" Ohorntilde # LATIN CAPITAL LETTER O WITH HORN AND TILDE : "ớ" ohornacute # LATIN SMALL LETTER O WITH HORN AND ACUTE : "ợ" ohornbelowdot # LATIN SMALL LETTER O WITH HORN AND DOT BELOW : "ờ" ohorngrave # LATIN SMALL LETTER O WITH HORN AND GRAVE : "ở" ohornhook # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE : "ỡ" ohorntilde # LATIN SMALL LETTER O WITH HORN AND TILDE : "Ứ" Uhornacute # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "Ự" Uhornbelowdot # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW : "Ừ" Uhorngrave # LATIN CAPITAL LETTER U WITH HORN AND GRAVE : "Ử" Uhornhook # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE : "Ữ" Uhorntilde # LATIN CAPITAL LETTER U WITH HORN AND TILDE : "ứ" uhornacute # LATIN SMALL LETTER U WITH HORN AND ACUTE : "ự" uhornbelowdot # LATIN SMALL LETTER U WITH HORN AND DOT BELOW : "ừ" uhorngrave # LATIN SMALL LETTER U WITH HORN AND GRAVE : "ử" uhornhook # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE : "ữ" uhorntilde # LATIN SMALL LETTER U WITH HORN AND TILDE : "̛" U031B # COMBINING HORN : "̛" U031B # COMBINING HORN : "̛" U031B # COMBINING HORN : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "Ǖ" U01D5 # LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON : "ǖ" U01D6 # LATIN SMALL LETTER U WITH DIAERESIS AND MACRON : "̄" U0304 # COMBINING MACRON : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "̨" U0328 # COMBINING OGONEK : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "̊" U030A # COMBINING RING ABOVE <2> : "ƻ" U01BB # LATIN LETTER TWO WITH STROKE : "≠" notequal # NOT EQUAL TO : "Ⱥ" U023A # LATIN CAPITAL LETTER A WITH STROKE : "ⱥ" U2C65 # LATIN SMALL LETTER A WITH STROKE : "Ƀ" U0243 # LATIN CAPITAL LETTER B WITH STROKE : "Ȼ" U023B # LATIN CAPITAL LETTER C WITH STROKE : "ȼ" U023C # LATIN SMALL LETTER C WITH STROKE : "Ɇ" U0246 # LATIN CAPITAL LETTER E WITH STROKE : "ɇ" U0247 # LATIN SMALL LETTER E WITH STROKE : "≯" U226F # NOT GREATER-THAN : "≱" U2271 # NEITHER GREATER-THAN NOR EQUAL TO : "Ɉ" U0248 # LATIN CAPITAL LETTER J WITH STROKE : "ɉ" U0249 # LATIN SMALL LETTER J WITH STROKE : "ᵼ" U1D7C # LATIN SMALL LETTER IOTA WITH STROKE : "ɟ" U025F # LATIN SMALL LETTER DOTLESS J WITH STROKE : "≮" U226E # NOT LESS-THAN : "≰" U2270 # NEITHER LESS-THAN NOR EQUAL TO : "Ǿ" U01FE # LATIN CAPITAL LETTER O WITH STROKE AND ACUTE : "ǿ" U01FF # LATIN SMALL LETTER O WITH STROKE AND ACUTE

: "Ᵽ" U2C63 # LATIN CAPITAL LETTER P WITH STROKE

: "ᵽ" U1D7D # LATIN SMALL LETTER P WITH STROKE : "Ɍ" U024C # LATIN CAPITAL LETTER R WITH STROKE : "ɍ" U024D # LATIN SMALL LETTER R WITH STROKE : "Ʉ" U0244 # LATIN CAPITAL LETTER U BAR : "ʉ" U0289 # LATIN SMALL LETTER U BAR : "Ɏ" U024E # LATIN CAPITAL LETTER Y WITH STROKE : "ɏ" U024F # LATIN SMALL LETTER Y WITH STROKE : "/" slash # SOLIDUS : "̸" U0338 # COMBINING LONG SOLIDUS OVERLAY : "/" slash # SOLIDUS : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "Ṏ" U1E4E # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "ṏ" U1E4F # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "≃" similarequal # ASYMPTOTICALLY EQUAL TO : "≲" U2272 # LESS-THAN OR EQUIVALENT TO : "≳" U2273 # GREATER-THAN OR EQUIVALENT TO : "̃" U0303 # COMBINING TILDE : "Ṥ" U1E64 # LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE : "ṥ" U1E65 # LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE : "Ṩ" U1E68 # LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE : "ṩ" U1E69 # LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE : "Ṧ" U1E66 # LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE : "ṧ" U1E67 # LATIN SMALL LETTER S WITH CARON AND DOT ABOVE : "Ǡ" U01E0 # LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON : "ǡ" U01E1 # LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON : "Ȱ" U0230 # LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON : "ȱ" U0231 # LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON : "ɟ" U025F # LATIN SMALL LETTER DOTLESS J WITH STROKE : "ɟ" U025F # LATIN SMALL LETTER DOTLESS J WITH STROKE : "Ắ" Abreveacute # LATIN CAPITAL LETTER A WITH BREVE AND ACUTE : "ắ" abreveacute # LATIN SMALL LETTER A WITH BREVE AND ACUTE : "Ḉ" U1E08 # LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE : "ḉ" U1E09 # LATIN SMALL LETTER C WITH CEDILLA AND ACUTE : "Ấ" Acircumflexacute # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE : "ấ" acircumflexacute # LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE : "Ế" Ecircumflexacute # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE : "ế" ecircumflexacute # LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE : "Ố" Ocircumflexacute # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE : "ố" ocircumflexacute # LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE : "Ḯ" U1E2E # LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE : "ḯ" U1E2F # LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE : "Ǘ" U01D7 # LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE : "ǘ" U01D8 # LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE : "Ớ" Ohornacute # LATIN CAPITAL LETTER O WITH HORN AND ACUTE : "ớ" ohornacute # LATIN SMALL LETTER O WITH HORN AND ACUTE : "Ứ" Uhornacute # LATIN CAPITAL LETTER U WITH HORN AND ACUTE : "ứ" uhornacute # LATIN SMALL LETTER U WITH HORN AND ACUTE : "Ḗ" U1E16 # LATIN CAPITAL LETTER E WITH MACRON AND ACUTE : "ḗ" U1E17 # LATIN SMALL LETTER E WITH MACRON AND ACUTE : "Ṓ" U1E52 # LATIN CAPITAL LETTER O WITH MACRON AND ACUTE : "ṓ" U1E53 # LATIN SMALL LETTER O WITH MACRON AND ACUTE : "Ǻ" U01FA # LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE : "ǻ" U01FB # LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE : "Ṍ" U1E4C # LATIN CAPITAL LETTER O WITH TILDE AND ACUTE : "ṍ" U1E4D # LATIN SMALL LETTER O WITH TILDE AND ACUTE : "Ṹ" U1E78 # LATIN CAPITAL LETTER U WITH TILDE AND ACUTE : "ṹ" U1E79 # LATIN SMALL LETTER U WITH TILDE AND ACUTE : "Ặ" Abrevebelowdot # LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW : "ặ" abrevebelowdot # LATIN SMALL LETTER A WITH BREVE AND DOT BELOW : "Ậ" Acircumflexbelowdot # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "ậ" acircumflexbelowdot # LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW : "Ệ" Ecircumflexbelowdot # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "ệ" ecircumflexbelowdot # LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW : "Ộ" Ocircumflexbelowdot # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "ộ" ocircumflexbelowdot # LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW : "Ợ" Ohornbelowdot # LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW : "ợ" ohornbelowdot # LATIN SMALL LETTER O WITH HORN AND DOT BELOW : "Ự" Uhornbelowdot # LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW : "ự" uhornbelowdot # LATIN SMALL LETTER U WITH HORN AND DOT BELOW : "Ḹ" U1E38 # LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON : "ḹ" U1E39 # LATIN SMALL LETTER L WITH DOT BELOW AND MACRON : "Ṝ" U1E5C # LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON : "ṝ" U1E5D # LATIN SMALL LETTER R WITH DOT BELOW AND MACRON : "Ḝ" U1E1C # LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE : "ḝ" U1E1D # LATIN SMALL LETTER E WITH CEDILLA AND BREVE : "Ằ" Abrevegrave # LATIN CAPITAL LETTER A WITH BREVE AND GRAVE : "ằ" abrevegrave # LATIN SMALL LETTER A WITH BREVE AND GRAVE : "Ẳ" Abrevehook # LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE : "ẳ" abrevehook # LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE : "Ẵ" Abrevetilde # LATIN CAPITAL LETTER A WITH BREVE AND TILDE : "ẵ" abrevetilde # LATIN SMALL LETTER A WITH BREVE AND TILDE : "Ǚ" U01D9 # LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON : "ǚ" U01DA # LATIN SMALL LETTER U WITH DIAERESIS AND CARON : "₵" U20B5 # CEDI SIGN : "₵" U20B5 # CEDI SIGN : "₵" U20B5 # CEDI SIGN : "₵" U20B5 # CEDI SIGN : "Ầ" Acircumflexgrave # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE : "ầ" acircumflexgrave # LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE : "Ề" Ecircumflexgrave # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE : "ề" ecircumflexgrave # LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE : "Ồ" Ocircumflexgrave # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE : "ồ" ocircumflexgrave # LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE : "Ẩ" Acircumflexhook # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "ẩ" acircumflexhook # LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE : "Ể" Ecircumflexhook # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "ể" ecircumflexhook # LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE : "Ổ" Ocircumflexhook # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "ổ" ocircumflexhook # LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE : "Ẫ" Acircumflextilde # LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE : "ẫ" acircumflextilde # LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE : "Ễ" Ecircumflextilde # LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE : "ễ" ecircumflextilde # LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE : "Ỗ" Ocircumflextilde # LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE : "ỗ" ocircumflextilde # LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE : "Ǜ" U01DB # LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE : "ǜ" U01DC # LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE : "Ǟ" U01DE # LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON : "ǟ" U01DF # LATIN SMALL LETTER A WITH DIAERESIS AND MACRON : "Ȫ" U022A # LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON : "ȫ" U022B # LATIN SMALL LETTER O WITH DIAERESIS AND MACRON : "Ṏ" U1E4E # LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS : "ṏ" U1E4F # LATIN SMALL LETTER O WITH TILDE AND DIAERESIS : "Ờ" Ohorngrave # LATIN CAPITAL LETTER O WITH HORN AND GRAVE : "ờ" ohorngrave # LATIN SMALL LETTER O WITH HORN AND GRAVE : "Ừ" Uhorngrave # LATIN CAPITAL LETTER U WITH HORN AND GRAVE : "ừ" uhorngrave # LATIN SMALL LETTER U WITH HORN AND GRAVE : "Ḕ" U1E14 # LATIN CAPITAL LETTER E WITH MACRON AND GRAVE : "ḕ" U1E15 # LATIN SMALL LETTER E WITH MACRON AND GRAVE : "Ṑ" U1E50 # LATIN CAPITAL LETTER O WITH MACRON AND GRAVE : "ṑ" U1E51 # LATIN SMALL LETTER O WITH MACRON AND GRAVE : "Ở" Ohornhook # LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE : "ở" ohornhook # LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE : "Ử" Uhornhook # LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE : "ử" uhornhook # LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE : "Ỡ" Ohorntilde # LATIN CAPITAL LETTER O WITH HORN AND TILDE : "ỡ" ohorntilde # LATIN SMALL LETTER O WITH HORN AND TILDE : "Ữ" Uhorntilde # LATIN CAPITAL LETTER U WITH HORN AND TILDE : "ữ" uhorntilde # LATIN SMALL LETTER U WITH HORN AND TILDE : "Ǭ" U01EC # LATIN CAPITAL LETTER O WITH OGONEK AND MACRON : "ǭ" U01ED # LATIN SMALL LETTER O WITH OGONEK AND MACRON : "Ȭ" U022C # LATIN CAPITAL LETTER O WITH TILDE AND MACRON : "ȭ" U022D # LATIN SMALL LETTER O WITH TILDE AND MACRON : "ϒ" U03D2 # GREEK UPSILON WITH HOOK SYMBOL : "ϒ" U03D2 # GREEK UPSILON WITH HOOK SYMBOL : "Ᾱ" U1FB9 # GREEK CAPITAL LETTER ALPHA WITH MACRON : "Ᾱ" U1FB9 # GREEK CAPITAL LETTER ALPHA WITH MACRON : "ᾱ" U1FB1 # GREEK SMALL LETTER ALPHA WITH MACRON : "ᾱ" U1FB1 # GREEK SMALL LETTER ALPHA WITH MACRON : "Ῑ" U1FD9 # GREEK CAPITAL LETTER IOTA WITH MACRON : "Ῑ" U1FD9 # GREEK CAPITAL LETTER IOTA WITH MACRON : "ῑ" U1FD1 # GREEK SMALL LETTER IOTA WITH MACRON : "ῑ" U1FD1 # GREEK SMALL LETTER IOTA WITH MACRON : "Ῡ" U1FE9 # GREEK CAPITAL LETTER UPSILON WITH MACRON : "Ῡ" U1FE9 # GREEK CAPITAL LETTER UPSILON WITH MACRON : "ῡ" U1FE1 # GREEK SMALL LETTER UPSILON WITH MACRON : "ῡ" U1FE1 # GREEK SMALL LETTER UPSILON WITH MACRON : "ϼ" U03FC # GREEK RHO WITH STROKE SYMBOL : "ϼ" U03FC # GREEK RHO WITH STROKE SYMBOL # # Cyrillic NFDs # : "а̏" # CYRILLIC SMALL LETTER A WITH COMBINING DOUBLE GRAVE ACCENT : "а̏" # CYRILLIC SMALL LETTER A WITH COMBINING DOUBLE GRAVE ACCENT : "а̑" # CYRILLIC SMALL LETTER A WITH COMBINING INVERTED BREVE : "а̀" # CYRILLIC SMALL LETTER A WITH COMBINING GRAVE ACCENT : "а̀" # CYRILLIC SMALL LETTER A WITH COMBINING GRAVE ACCENT : "а́" # CYRILLIC SMALL LETTER A WITH COMBINING ACUTE ACCENT : "а́" # CYRILLIC SMALL LETTER A WITH COMBINING ACUTE ACCENT : "а́" # CYRILLIC SMALL LETTER A WITH COMBINING ACUTE ACCENT : "а̄" # CYRILLIC SMALL LETTER A WITH COMBINING MACRON : "а̄" # CYRILLIC SMALL LETTER A WITH COMBINING MACRON : "а̄" # CYRILLIC SMALL LETTER A WITH COMBINING MACRON : "а̂" # CYRILLIC SMALL LETTER A WITH COMBINING CIRCUMFLEX ACCENT : "а̂" # CYRILLIC SMALL LETTER A WITH COMBINING CIRCUMFLEX ACCENT : "А̏" # CYRILLIC CAPITAL LETTER A WITH COMBINING DOUBLE GRAVE ACCENT : "А̏" # CYRILLIC CAPITAL LETTER A WITH COMBINING DOUBLE GRAVE ACCENT : "А̑" # CYRILLIC CAPITAL LETTER A WITH COMBINING INVERTED BREVE : "А̀" # CYRILLIC CAPITAL LETTER A WITH COMBINING GRAVE ACCENT : "А̀" # CYRILLIC CAPITAL LETTER A WITH COMBINING GRAVE ACCENT : "А́" # CYRILLIC CAPITAL LETTER A WITH COMBINING ACUTE ACCENT : "А́" # CYRILLIC CAPITAL LETTER A WITH COMBINING ACUTE ACCENT : "А́" # CYRILLIC CAPITAL LETTER A WITH COMBINING ACUTE ACCENT : "А̄" # CYRILLIC CAPITAL LETTER A WITH COMBINING MACRON : "А̄" # CYRILLIC CAPITAL LETTER A WITH COMBINING MACRON : "А̄" # CYRILLIC CAPITAL LETTER A WITH COMBINING MACRON : "А̂" # CYRILLIC CAPITAL LETTER A WITH COMBINING CIRCUMFLEX ACCENT : "А̂" # CYRILLIC CAPITAL LETTER A WITH COMBINING CIRCUMFLEX ACCENT : "е̏" # CYRILLIC SMALL LETTER IE WITH COMBINING DOUBLE GRAVE ACCENT : "е̏" # CYRILLIC SMALL LETTER IE WITH COMBINING DOUBLE GRAVE ACCENT : "е̑" # CYRILLIC SMALL LETTER IE WITH COMBINING INVERTED BREVE : "е́" # CYRILLIC SMALL LETTER IE WITH COMBINING ACUTE ACCENT : "е́" # CYRILLIC SMALL LETTER IE WITH COMBINING ACUTE ACCENT : "е́" # CYRILLIC SMALL LETTER IE WITH COMBINING ACUTE ACCENT : "е̄" # CYRILLIC SMALL LETTER IE WITH COMBINING MACRON : "е̄" # CYRILLIC SMALL LETTER IE WITH COMBINING MACRON : "е̄" # CYRILLIC SMALL LETTER IE WITH COMBINING MACRON : "е̂" # CYRILLIC SMALL LETTER IE WITH COMBINING CIRCUMFLEX ACCENT : "е̂" # CYRILLIC SMALL LETTER IE WITH COMBINING CIRCUMFLEX ACCENT : "Е̏" # CYRILLIC CAPITAL LETTER IE WITH COMBINING DOUBLE GRAVE ACCENT : "Е̏" # CYRILLIC CAPITAL LETTER IE WITH COMBINING DOUBLE GRAVE ACCENT : "Е̑" # CYRILLIC CAPITAL LETTER IE WITH COMBINING INVERTED BREVE : "Е́" # CYRILLIC CAPITAL LETTER IE WITH COMBINING ACUTE ACCENT : "Е́" # CYRILLIC CAPITAL LETTER IE WITH COMBINING ACUTE ACCENT : "Е́" # CYRILLIC CAPITAL LETTER IE WITH COMBINING ACUTE ACCENT : "Е̄" # CYRILLIC CAPITAL LETTER IE WITH COMBINING MACRON : "Е̄" # CYRILLIC CAPITAL LETTER IE WITH COMBINING MACRON : "Е̄" # CYRILLIC CAPITAL LETTER IE WITH COMBINING MACRON : "Е̂" # CYRILLIC CAPITAL LETTER IE WITH COMBINING CIRCUMFLEX ACCENT : "Е̂" # CYRILLIC CAPITAL LETTER IE WITH COMBINING CIRCUMFLEX ACCENT : "и̏" # CYRILLIC SMALL LETTER I WITH COMBINING DOUBLE GRAVE ACCENT : "и̏" # CYRILLIC SMALL LETTER I WITH COMBINING DOUBLE GRAVE ACCENT : "и̑" # CYRILLIC SMALL LETTER I WITH COMBINING INVERTED BREVE : "и́" # CYRILLIC SMALL LETTER I WITH COMBINING ACUTE ACCENT : "и́" # CYRILLIC SMALL LETTER I WITH COMBINING ACUTE ACCENT : "и́" # CYRILLIC SMALL LETTER I WITH COMBINING ACUTE ACCENT : "и̂" # CYRILLIC SMALL LETTER I WITH COMBINING CIRCUMFLEX ACCENT : "и̂" # CYRILLIC SMALL LETTER I WITH COMBINING CIRCUMFLEX ACCENT : "И̏" # CYRILLIC CAPITAL LETTER I WITH COMBINING DOUBLE GRAVE ACCENT : "И̏" # CYRILLIC CAPITAL LETTER I WITH COMBINING DOUBLE GRAVE ACCENT : "И̑" # CYRILLIC CAPITAL LETTER I WITH COMBINING INVERTED BREVE : "И́" # CYRILLIC CAPITAL LETTER I WITH COMBINING ACUTE ACCENT : "И́" # CYRILLIC CAPITAL LETTER I WITH COMBINING ACUTE ACCENT : "И́" # CYRILLIC CAPITAL LETTER I WITH COMBINING ACUTE ACCENT : "И̂" # CYRILLIC CAPITAL LETTER I WITH COMBINING CIRCUMFLEX ACCENT : "И̂" # CYRILLIC CAPITAL LETTER I WITH COMBINING CIRCUMFLEX ACCENT : "о̏" # CYRILLIC SMALL LETTER O WITH COMBINING DOUBLE GRAVE ACCENT : "о̏" # CYRILLIC SMALL LETTER O WITH COMBINING DOUBLE GRAVE ACCENT : "о̑" # CYRILLIC SMALL LETTER O WITH COMBINING INVERTED BREVE : "о̀" # CYRILLIC SMALL LETTER O WITH COMBINING GRAVE ACCENT : "о̀" # CYRILLIC SMALL LETTER O WITH COMBINING GRAVE ACCENT : "о́" # CYRILLIC SMALL LETTER O WITH COMBINING ACUTE ACCENT : "о́" # CYRILLIC SMALL LETTER O WITH COMBINING ACUTE ACCENT : "о́" # CYRILLIC SMALL LETTER O WITH COMBINING ACUTE ACCENT : "о̄" # CYRILLIC SMALL LETTER O WITH COMBINING MACRON : "о̄" # CYRILLIC SMALL LETTER O WITH COMBINING MACRON : "о̄" # CYRILLIC SMALL LETTER O WITH COMBINING MACRON : "о̂" # CYRILLIC SMALL LETTER O WITH COMBINING CIRCUMFLEX ACCENT : "о̂" # CYRILLIC SMALL LETTER O WITH COMBINING CIRCUMFLEX ACCENT : "О̏" # CYRILLIC CAPITAL LETTER O WITH COMBINING DOUBLE GRAVE ACCENT : "О̏" # CYRILLIC CAPITAL LETTER O WITH COMBINING DOUBLE GRAVE ACCENT : "О̑" # CYRILLIC CAPITAL LETTER O WITH COMBINING INVERTED BREVE : "О̀" # CYRILLIC CAPITAL LETTER O WITH COMBINING GRAVE ACCENT : "О̀" # CYRILLIC CAPITAL LETTER O WITH COMBINING GRAVE ACCENT : "О́" # CYRILLIC CAPITAL LETTER O WITH COMBINING ACUTE ACCENT : "О́" # CYRILLIC CAPITAL LETTER O WITH COMBINING ACUTE ACCENT : "О́" # CYRILLIC CAPITAL LETTER O WITH COMBINING ACUTE ACCENT : "О̄" # CYRILLIC CAPITAL LETTER O WITH COMBINING MACRON : "О̄" # CYRILLIC CAPITAL LETTER O WITH COMBINING MACRON : "О̄" # CYRILLIC CAPITAL LETTER O WITH COMBINING MACRON : "О̂" # CYRILLIC CAPITAL LETTER O WITH COMBINING CIRCUMFLEX ACCENT : "О̂" # CYRILLIC CAPITAL LETTER O WITH COMBINING CIRCUMFLEX ACCENT : "у̏" # CYRILLIC SMALL LETTER U WITH COMBINING DOUBLE GRAVE ACCENT : "у̏" # CYRILLIC SMALL LETTER U WITH COMBINING DOUBLE GRAVE ACCENT : "у̑" # CYRILLIC SMALL LETTER U WITH COMBINING INVERTED BREVE : "у̀" # CYRILLIC SMALL LETTER U WITH COMBINING GRAVE ACCENT : "у̀" # CYRILLIC SMALL LETTER U WITH COMBINING GRAVE ACCENT : "у́" # CYRILLIC SMALL LETTER U WITH COMBINING ACUTE ACCENT : "у́" # CYRILLIC SMALL LETTER U WITH COMBINING ACUTE ACCENT : "у́" # CYRILLIC SMALL LETTER U WITH COMBINING ACUTE ACCENT : "у̂" # CYRILLIC SMALL LETTER U WITH COMBINING CIRCUMFLEX ACCENT : "у̂" # CYRILLIC SMALL LETTER U WITH COMBINING CIRCUMFLEX ACCENT : "У̏" # CYRILLIC CAPITAL LETTER U WITH COMBINING DOUBLE GRAVE ACCENT : "У̏" # CYRILLIC CAPITAL LETTER U WITH COMBINING DOUBLE GRAVE ACCENT : "У̑" # CYRILLIC CAPITAL LETTER U WITH COMBINING INVERTED BREVE : "У̀" # CYRILLIC CAPITAL LETTER U WITH COMBINING GRAVE ACCENT : "У̀" # CYRILLIC CAPITAL LETTER U WITH COMBINING GRAVE ACCENT : "У́" # CYRILLIC CAPITAL LETTER U WITH COMBINING ACUTE ACCENT : "У́" # CYRILLIC CAPITAL LETTER U WITH COMBINING ACUTE ACCENT : "У́" # CYRILLIC CAPITAL LETTER U WITH COMBINING ACUTE ACCENT : "У̂" # CYRILLIC CAPITAL LETTER U WITH COMBINING CIRCUMFLEX ACCENT : "У̂" # CYRILLIC CAPITAL LETTER U WITH COMBINING CIRCUMFLEX ACCENT : "р̏" # CYRILLIC SMALL LETTER ER WITH COMBINING DOUBLE GRAVE ACCENT : "р̏" # CYRILLIC SMALL LETTER ER WITH COMBINING DOUBLE GRAVE ACCENT : "р̑" # CYRILLIC SMALL LETTER ER WITH COMBINING INVERTED BREVE : "р̀" # CYRILLIC SMALL LETTER ER WITH COMBINING GRAVE ACCENT : "р̀" # CYRILLIC SMALL LETTER ER WITH COMBINING GRAVE ACCENT : "р́" # CYRILLIC SMALL LETTER ER WITH COMBINING ACUTE ACCENT : "р́" # CYRILLIC SMALL LETTER ER WITH COMBINING ACUTE ACCENT : "р́" # CYRILLIC SMALL LETTER ER WITH COMBINING ACUTE ACCENT : "р̄" # CYRILLIC SMALL LETTER ER WITH COMBINING MACRON : "р̄" # CYRILLIC SMALL LETTER ER WITH COMBINING MACRON : "р̄" # CYRILLIC SMALL LETTER ER WITH COMBINING MACRON : "р̂" # CYRILLIC SMALL LETTER ER WITH COMBINING CIRCUMFLEX ACCENT : "р̂" # CYRILLIC SMALL LETTER ER WITH COMBINING CIRCUMFLEX ACCENT : "Р̏" # CYRILLIC CAPITAL LETTER ER WITH COMBINING DOUBLE GRAVE ACCENT : "Р̏" # CYRILLIC CAPITAL LETTER ER WITH COMBINING DOUBLE GRAVE ACCENT : "Р̑" # CYRILLIC CAPITAL LETTER ER WITH COMBINING INVERTED BREVE : "Р̀" # CYRILLIC CAPITAL LETTER ER WITH COMBINING GRAVE ACCENT : "Р̀" # CYRILLIC CAPITAL LETTER ER WITH COMBINING GRAVE ACCENT : "Р́" # CYRILLIC CAPITAL LETTER ER WITH COMBINING ACUTE ACCENT : "Р́" # CYRILLIC CAPITAL LETTER ER WITH COMBINING ACUTE ACCENT : "Р́" # CYRILLIC CAPITAL LETTER ER WITH COMBINING ACUTE ACCENT : "Р̄" # CYRILLIC CAPITAL LETTER ER WITH COMBINING MACRON : "Р̄" # CYRILLIC CAPITAL LETTER ER WITH COMBINING MACRON : "Р̄" # CYRILLIC CAPITAL LETTER ER WITH COMBINING MACRON : "Р̂" # CYRILLIC CAPITAL LETTER ER WITH COMBINING CIRCUMFLEX ACCENT : "Р̂" # CYRILLIC CAPITAL LETTER ER WITH COMBINING CIRCUMFLEX ACCENT : "🙌" # PERSON RAISING BOTH HANDS IN CELEBRATION # APL support Geoff Streeter 2012-01-04 # APL was initially an overstruck language. The original APL terminal was an IBM golfball # with a specially designed golfball. This meant that characters could be overstruck to # produce other characters. This gave APL a richness of primitives which is still powerful # today. Overstrikes were always independent of order. # APLs have extended this into a number of dialects. Let us try to support lots of them. # Together with some that have not been used yet. Some traditional ones are not included. # Characters from "Mathematical Operators" : "√" U221a # v / SQUARE ROOT : "√" U221a # / v SQUARE ROOT <8> <8> : "∞" U221e # 8 8 INFINITY : "≡" U2261 # = _ IDENTICAL TO : "≢" U2262 # _ ≠ NOT IDENTICAL TO : "≢" U2262 # ≠ _ NOT IDENTICAL TO : "≤" U2264 # < _ LESS-THAN OR EQUAL TO : "≤" U2264 # _ < LESS-THAN OR EQUAL TO : "≥" U2265 # > _ GREATER-THAN OR EQUAL TO : "≥" U2265 # _ > GREATER-THAN OR EQUAL TO : "⊆" U2286 # _ ⊂ SUBSET OF OR EQUAL TO : "⊆" U2286 # ⊂ _ SUBSET OF OR EQUAL TO : "⊇" U2287 # _ ⊃ SUPERSET OF OR EQUAL TO : "⊇" U2287 # ⊃ _ SUPERSET OF OR EQUAL TO : "⊖" U2296 # ○ - CIRCLED MINUS : "⊖" U2296 # - ○ CIRCLED MINUS : "⊙" U2299 # ○ - CIRCLED DOT : "⊙" U2299 # - ○ CIRCLED DOT : "⋄" U22c4 # < > DIAMOND OPERATOR : "⋄" U22c4 # > < DIAMOND OPERATOR : "⋄" U22c4 # ∧ ∨ DIAMOND OPERATOR : "⋄" U22c4 # ∨ ∧ DIAMOND OPERATOR : "∴" therefore # THEREFORE : "∵" because # BECAUSE # Characters from "Miscellaneous Technical" : "⌶" U2336 # ⊥ ⊤ APL FUNCTIONAL SYMBOL I-BEAM : "⌶" U2336 # ⊥ ⊤ APL FUNCTIONAL SYMBOL I-BEAM : "⌷" U2337 # [ ] APL FUNCTIONAL SYMBOL SQUISH QUAD : "⌷" U2337 # ] [ APL FUNCTIONAL SYMBOL SQUISH QUAD : "⌸" U2338 # ⎕ = APL FUNCTIONAL SYMBOL QUAD EQUAL : "⌸" U2338 # = ⎕ APL FUNCTIONAL SYMBOL QUAD EQUAL : "⌹" U2339 # ⎕ ÷ APL FUNCTIONAL SYMBOL QUAD DIVIDE : "⌹" U2339 # ÷ ⎕ APL FUNCTIONAL SYMBOL QUAD DIVIDE : "⌺" U233a # ⎕ ⋄ APL FUNCTIONAL SYMBOL QUAD DIAMOND : "⌺" U233a # ⋄ ⎕ APL FUNCTIONAL SYMBOL QUAD DIAMOND : "⌻" U233b # ⎕ ∘ APL FUNCTIONAL SYMBOL QUAD JOT : "⌻" U233b # ∘ ⎕ APL FUNCTIONAL SYMBOL QUAD JOT : "⌼" U233c # ⎕ ○ APL FUNCTIONAL SYMBOL QUAD CIRCLE : "⌼" U233c # ○ ⎕ APL FUNCTIONAL SYMBOL QUAD CIRCLE : "⌽" U233d # ○ | APL FUNCTIONAL SYMBOL CIRCLE STILE : "⌽" U233d # | ○ APL FUNCTIONAL SYMBOL CIRCLE STILE : "⌾" U233e # ○ ∘ APL FUNCTIONAL SYMBOL CIRCLE JOT : "⌾" U233e # ∘ ○ APL FUNCTIONAL SYMBOL CIRCLE JOT : "⌿" U233f # / - APL FUNCTIONAL SYMBOL SLASH BAR : "⌿" U233f # - / APL FUNCTIONAL SYMBOL SLASH BAR : "⍀" U2340 # \ - APL FUNCTIONAL SYMBOL BACKSLASH BAR : "⍀" U2340 # - \ APL FUNCTIONAL SYMBOL BACKSLASH BAR : "⍁" U2341 # / ⎕ APL FUNCTIONAL SYMBOL QUAD SLASH : "⍁" U2341 # ⎕ / APL FUNCTIONAL SYMBOL QUAD SLASH : "⍂" U2342 # \ ⎕ APL FUNCTIONAL SYMBOL QUAD BACKSLASH : "⍂" U2342 # ⎕ \ APL FUNCTIONAL SYMBOL QUAD BACKSLASH : "⍃" U2343 # < ⎕ APL FUNCTIONAL SYMBOL QUAD LESS-THAN : "⍃" U2343 # ⎕ < APL FUNCTIONAL SYMBOL QUAD LESS-THAN : "⍄" U2344 # > ⎕ APL FUNCTIONAL SYMBOL QUAD GREATER-THAN : "⍄" U2344 # ⎕ > APL FUNCTIONAL SYMBOL QUAD GREATER-THAN : "⍅" U2345 # ← | APL FUNCTIONAL SYMBOL LEFTWARDS VANE : "⍅" U2345 # | ← APL FUNCTIONAL SYMBOL LEFTWARDS VANE : "⍆" U2346 # → | APL FUNCTIONAL SYMBOL RIGHTWARDS VANE : "⍆" U2346 # | → APL FUNCTIONAL SYMBOL RIGHTWARDS VANE : "⍇" U2347 # ← ⎕ APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW : "⍇" U2347 # ⎕ ← APL FUNCTIONAL SYMBOL QUAD LEFTWARDS ARROW : "⍈" U2348 # → ⎕ APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW : "⍈" U2348 # ⎕ → APL FUNCTIONAL SYMBOL QUAD RIGHTWARDS ARROW : "⍉" U2349 # ○ \ APL FUNCTIONAL SYMBOL CIRCLE SLOPE : "⍉" U2349 # \ ○ APL FUNCTIONAL SYMBOL CIRCLE SLOPE : "⍊" U234a # _ ⊥ APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR : "⍊" U234a # ⊥ _ APL FUNCTIONAL SYMBOL DOWN TACK UNDERBAR : "⍋" U234b # ∆ | APL FUNCTIONAL SYMBOL DELTA STILE : "⍋" U234b # | ∆ APL FUNCTIONAL SYMBOL DELTA STILE : "⍌" U234c # ∨ ⎕ APL FUNCTIONAL SYMBOL QUAD DOWN CARET : "⍌" U234c # ⎕ ∨ APL FUNCTIONAL SYMBOL QUAD DOWN CARET : "⍍" U234d # ∆ ⎕ APL FUNCTIONAL SYMBOL QUAD DELTA : "⍍" U234d # ⎕ ∆ APL FUNCTIONAL SYMBOL QUAD DELTA : "⍎" U234e # ∘ ⊥ APL FUNCTIONAL SYMBOL DOWN TACK JOT : "⍎" U234e # ⊥ ∘ APL FUNCTIONAL SYMBOL DOWN TACK JOT : "⍏" U234f # ↑ - APL FUNCTIONAL SYMBOL UPWARDS VANE : "⍏" U234f # - ↑ APL FUNCTIONAL SYMBOL UPWARDS VANE : "⍐" U2350 # ↑ ⎕ APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW : "⍐" U2350 # ⎕ ↑ APL FUNCTIONAL SYMBOL QUAD UPWARDS ARROW # I cannot get anything to work with . Given that no extant APLs use ⍑ I will just leave the lines # in place. : "⍑" U2351 # ¯ ⊤ APL FUNCTIONAL SYMBOL UP TACK OVERBAR : "⍑" U2351 # ⊤ ¯ APL FUNCTIONAL SYMBOL UP TACK OVERBAR : "⍒" U2352 # ∇ | APL FUNCTIONAL SYMBOL DEL STILE : "⍒" U2352 # | ∇ APL FUNCTIONAL SYMBOL DEL STILE : "⍓" U2353 # ∧ ⎕ APL FUNCTIONAL SYMBOL QUAD UP CARET : "⍓" U2353 # ⎕ ∧ APL FUNCTIONAL SYMBOL QUAD UP CARET : "⍔" U2354 # ∇ ⎕ APL FUNCTIONAL SYMBOL QUAD DEL : "⍔" U2354 # ⎕ ∇ APL FUNCTIONAL SYMBOL QUAD DEL : "⍕" U2355 # ∘ ⊤ APL FUNCTIONAL SYMBOL UP TACK JOT : "⍕" U2355 # ⊤ ∘ APL FUNCTIONAL SYMBOL UP TACK JOT : "⍖" U2356 # ↓ - APL FUNCTIONAL SYMBOL DOWNWARDS VANE : "⍖" U2356 # - ↓ APL FUNCTIONAL SYMBOL DOWNWARDS VANE : "⍗" U2357 # ↓ ⎕ APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW : "⍗" U2357 # ⎕ ↓ APL FUNCTIONAL SYMBOL QUAD DOWNWARDS ARROW # This line clashes with the (and similar) that appear to be there to provide # a work around for the problems with . Or to cope with keyboards that do not have (more likely). # All APL keyboards have , it is used as the -ve sign for numbers. # I do not know of an extant APL using ⍘ : "⍘" U2358 # _ ' APL FUNCTIONAL SYMBOL QUOTE UNDERBAR : "⍙" U2359 # ∆ _ APL FUNCTIONAL SYMBOL DELTA UNDERBAR : "⍙" U2359 # _ ∆ APL FUNCTIONAL SYMBOL DELTA UNDERBAR : "⍚" U235a # ⋄ _ APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR : "⍚" U235a # _ ⋄ APL FUNCTIONAL SYMBOL DIAMOND UNDERBAR : "⍛" U235b # ∘ _ APL FUNCTIONAL SYMBOL JOT UNDERBAR : "⍛" U235b # _ ∘ APL FUNCTIONAL SYMBOL JOT UNDERBAR : "⍜" U235c # ○ _ APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR : "⍜" U235c # _ ○ APL FUNCTIONAL SYMBOL CIRCLE UNDERBAR : "⍝" U235d # ∘ ∩ APL FUNCTIONAL SYMBOL UP SHOE JOT : "⍝" U235d # ∩ ∘ APL FUNCTIONAL SYMBOL UP SHOE JOT : "⍞" U235e # * ¨ APL FUNCTIONAL SYMBOL QUOTE QUAD : "⍞" U235e # ¨ * APL FUNCTIONAL SYMBOL QUOTE QUAD : "⍟" U235f # ○ * APL FUNCTIONAL SYMBOL CIRCLE STAR : "⍟" U235f # * ○ APL FUNCTIONAL SYMBOL CIRCLE STAR : "⍠" U2360 # : ⎕ APL FUNCTIONAL SYMBOL QUAD COLON : "⍠" U2360 # ⎕ : APL FUNCTIONAL SYMBOL QUAD COLON : "⍡" U2361 # ¨ ⊤ APL FUNCTIONAL SYMBOL UP TACK DIAERESIS : "⍡" U2361 # ⊤ ¨ APL FUNCTIONAL SYMBOL UP TACK DIAERESIS : "⍢" U2362 # ¨ ∇ APL FUNCTIONAL SYMBOL DEL DIAERESIS : "⍢" U2362 # ∇ ¨ APL FUNCTIONAL SYMBOL DEL DIAERESIS : "⍣" U2363 # * ¨ APL FUNCTIONAL SYMBOL STAR DIAERESIS : "⍣" U2363 # ¨ * APL FUNCTIONAL SYMBOL STAR DIAERESIS : "⍤" U2364 # ∘ ¨ APL FUNCTIONAL SYMBOL JOT DIAERESIS : "⍤" U2364 # ¨ ∘ APL FUNCTIONAL SYMBOL JOT DIAERESIS : "⍥" U2365 # ○ ¨ APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS : "⍥" U2365 # ¨ ○ APL FUNCTIONAL SYMBOL CIRCLE DIAERESIS : "⍦" U2366 # ∪ | APL FUNCTIONAL SYMBOL DOWN SHOE STILE : "⍦" U2366 # | ∪ APL FUNCTIONAL SYMBOL DOWN SHOE STILE : "⍧" U2367 # ⊂ | APL FUNCTIONAL SYMBOL LEFT SHOE STILE : "⍧" U2367 # | ⊂ APL FUNCTIONAL SYMBOL LEFT SHOE STILE : "⍨" U2368 # ~ ¨ APL FUNCTIONAL SYMBOL TILDE DIAERESIS : "⍩" U2369 # ¨ > APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS : "⍩" U2369 # > ¨ APL FUNCTIONAL SYMBOL GREATER-THAN DIAERESIS : "⍫" U236b # ∇ ~ APL FUNCTIONAL SYMBOL DEL TILDE : "⍫" U236b # ~ ∇ APL FUNCTIONAL SYMBOL DEL TILDE <0> : "⍬" U236c # 0 ~ APL FUNCTIONAL SYMBOL ZILDE <0> : "⍬" U236c # ~ 0 APL FUNCTIONAL SYMBOL ZILDE : "⍭" U236d # | ~ APL FUNCTIONAL SYMBOL STILE TILDE : "⍭" U236d # ~ | APL FUNCTIONAL SYMBOL STILE TILDE # This line does not work. It clashes with # for Ǭ and # for ǭ. # Given that no extant APLs use ⍮ I will just leave the line in place. : "⍮" U236e # ; _ APL FUNCTIONAL SYMBOL SEMICOLON UNDERBAR : "⍯" U236f # ≠ ⎕ APL FUNCTIONAL SYMBOL QUAD NOT EQUAL : "⍯" U236f # ⎕ ≠ APL FUNCTIONAL SYMBOL QUAD NOT EQUAL : "⍰" U2370 # ? ⎕ APL FUNCTIONAL SYMBOL QUAD QUESTION : "⍰" U2370 # ⎕ ? APL FUNCTIONAL SYMBOL QUAD QUESTION : "⍱" U2371 # ∨ ~ APL FUNCTIONAL SYMBOL DOWN CARET TILDE : "⍱" U2371 # ~ ∨ APL FUNCTIONAL SYMBOL DOWN CARET TILDE : "⍲" U2372 # ∧ ~ APL FUNCTIONAL SYMBOL UP CARET TILDE : "⍲" U2372 # ~ ∧ APL FUNCTIONAL SYMBOL UP CARET TILDE : "⍶" U2376 # ⍺ _ APL FUNCTIONAL SYMBOL ALPHA UNDERBAR : "⍶" U2376 # _ ⍺ APL FUNCTIONAL SYMBOL ALPHA UNDERBAR : "⍷" U2377 # ∊ _ APL FUNCTIONAL SYMBOL EPSILON UNDERBAR : "⍷" U2377 # _ ∊ APL FUNCTIONAL SYMBOL EPSILON UNDERBAR : "⍸" U2378 # ⍳ _ APL FUNCTIONAL SYMBOL IOTA UNDERBAR : "⍸" U2378 # _ ⍳ APL FUNCTIONAL SYMBOL IOTA UNDERBAR : "⍹" U2379 # ⍵ _ APL FUNCTIONAL SYMBOL OMEGA UNDERBAR : "⍹" U2379 # _ ⍵ APL FUNCTIONAL SYMBOL OMEGA UNDERBAR xkbcommon-libxkbcommon-54ee7ac/test/data/locale/locale.alias000066400000000000000000002322671510033435100243000ustar00rootroot00000000000000# # This file contains alias names of locales. # Each alias name is described within one line. # The first word is the alias name (simplified locale name), # the second word is the full locale name. # # POSIX C POSIX-UTF2 C C_C.C C C.en C C.ASCII C C.iso88591 en_US.ISO8859-1 Cextend en_US.ISO8859-1 Cextend.en en_US.ISO8859-1 English_United-States.437 C C.UTF-8 en_US.UTF-8 # a3 is not an ISO 639 language code, but in Cyrillic, "Z" looks like "3". a3 az_AZ.KOI8-C a3_AZ az_AZ.KOI8-C a3_AZ.koi8c az_AZ.KOI8-C a3_AZ.KOI-C az_AZ.KOI8-C a3_AZ.UTF-8 az_AZ.UTF-8 af af_ZA.ISO8859-1 af_ZA af_ZA.ISO8859-1 af_ZA.iso88591 af_ZA.ISO8859-1 af_ZA.ISO-8859-1 af_ZA.ISO8859-1 af_ZA.utf8 af_ZA.UTF-8 am am_ET.UTF-8 am_ET am_ET.UTF-8 ar ar_AA.ISO8859-6 ar_AA ar_AA.ISO8859-6 AR_AA ar_AA.ISO8859-6 Ar_AA ar_AA.ISO8859-6 AR_AA.UTF-8 ar_AA.UTF-8 ar_AA.iso88596 ar_AA.ISO8859-6 ar_AA.ISO-8859-6 ar_AA.ISO8859-6 ar_AE ar_AE.ISO8859-6 ar_AE.iso88596 ar_AE.ISO8859-6 ar_AE.ISO-8859-6 ar_AE.ISO8859-6 ar_AE.utf8 ar_AE.UTF-8 ar_BH ar_BH.ISO8859-6 ar_BH.iso88596 ar_BH.ISO8859-6 ar_BH.ISO-8859-6 ar_BH.ISO8859-6 ar_BH.utf8 ar_BH.UTF-8 ar_DZ ar_DZ.ISO8859-6 ar_DZ.iso88596 ar_DZ.ISO8859-6 ar_DZ.ISO-8859-6 ar_DZ.ISO8859-6 ar_DZ.utf8 ar_DZ.UTF-8 ar_EG ar_EG.ISO8859-6 ar_EG.iso88596 ar_EG.ISO8859-6 ar_EG.ISO-8859-6 ar_EG.ISO8859-6 ar_EG.utf8 ar_EG.UTF-8 ar_IN ar_IN.UTF-8 ar_IN.utf8 ar_IN.UTF-8 ar_IQ ar_IQ.ISO8859-6 ar_IQ.iso88596 ar_IQ.ISO8859-6 ar_IQ.ISO-8859-6 ar_IQ.ISO8859-6 ar_IQ.utf8 ar_IQ.UTF-8 ar_JO ar_JO.ISO8859-6 ar_JO.iso88596 ar_JO.ISO8859-6 ar_JO.ISO-8859-6 ar_JO.ISO8859-6 ar_JO.utf8 ar_JO.UTF-8 ar_KW ar_KW.ISO8859-6 ar_KW.iso88596 ar_KW.ISO8859-6 ar_KW.ISO-8859-6 ar_KW.ISO8859-6 ar_KW.utf8 ar_KW.UTF-8 ar_LB ar_LB.ISO8859-6 ar_LB.iso88596 ar_LB.ISO8859-6 ar_LB.ISO-8859-6 ar_LB.ISO8859-6 ar_LB.utf8 ar_LB.UTF-8 ar_LY ar_LY.ISO8859-6 ar_LY.iso88596 ar_LY.ISO8859-6 ar_LY.ISO-8859-6 ar_LY.ISO8859-6 ar_LY.utf8 ar_LY.UTF-8 ar_MA ar_MA.ISO8859-6 ar_MA.iso88596 ar_MA.ISO8859-6 ar_MA.ISO-8859-6 ar_MA.ISO8859-6 ar_MA.utf8 ar_MA.UTF-8 ar_OM ar_OM.ISO8859-6 ar_OM.iso88596 ar_OM.ISO8859-6 ar_OM.ISO-8859-6 ar_OM.ISO8859-6 ar_OM.utf8 ar_OM.UTF-8 ar_QA ar_QA.ISO8859-6 ar_QA.iso88596 ar_QA.ISO8859-6 ar_QA.ISO-8859-6 ar_QA.ISO8859-6 ar_QA.utf8 ar_QA.UTF-8 ar_SA ar_SA.ISO8859-6 ar_SA.iso88596 ar_SA.ISO8859-6 ar_SA.ISO-8859-6 ar_SA.ISO8859-6 ar_SA.utf8 ar_SA.UTF-8 ar_SD ar_SD.ISO8859-6 ar_SD.iso88596 ar_SD.ISO8859-6 ar_SD.ISO-8859-6 ar_SD.ISO8859-6 ar_SD.utf8 ar_SD.UTF-8 ar_SY ar_SY.ISO8859-6 ar_SY.iso88596 ar_SY.ISO8859-6 ar_SY.ISO-8859-6 ar_SY.ISO8859-6 ar_SY.utf8 ar_SY.UTF-8 ar_TN ar_TN.ISO8859-6 ar_TN.iso88596 ar_TN.ISO8859-6 ar_TN.ISO-8859-6 ar_TN.ISO8859-6 ar_TN.utf8 ar_TN.UTF-8 as as_IN.UTF-8 as_IN as_IN.UTF-8 as_IN.utf8 as_IN.UTF-8 ar_YE ar_YE.ISO8859-6 ar_YE.iso88596 ar_YE.ISO8859-6 ar_YE.ISO-8859-6 ar_YE.ISO8859-6 ar_YE.utf8 ar_YE.UTF-8 az az_AZ.ISO8859-9E az_AZ az_AZ.ISO8859-9E az_AZ.iso88599e az_AZ.ISO8859-9E be be_BY.CP1251 be@latin be_BY.UTF-8@latin be_BY be_BY.CP1251 be_BY@latin be_BY.UTF-8@latin be_BY.cp1251 be_BY.CP1251 be_BY.microsoftcp1251 be_BY.CP1251 be_BY.microsoft-cp1251 be_BY.CP1251 be_BY.MICROSOFT-CP1251 be_BY.CP1251 be_BY.utf8 be_BY.UTF-8 be_BY.utf8@latin be_BY.UTF-8@latin bg bg_BG.CP1251 bg_BG bg_BG.CP1251 bg_BG.cp1251 bg_BG.CP1251 bg_BG.microsoftcp1251 bg_BG.CP1251 bg_BG.microsoft-cp1251 bg_BG.CP1251 bg_BG.MICROSOFT-CP1251 bg_BG.CP1251 bg_BG.iso88595 bg_BG.ISO8859-5 bg_BG.ISO-8859-5 bg_BG.ISO8859-5 bg_BG.koi8r bg_BG.KOI8-R be_BG.utf8 bg_BG.UTF-8 bn_IN bn_IN.UTF-8 bn_IN.utf8 bn_IN.UTF-8 bo_IN bo_IN.UTF-8 bo_IN.utf8 bo_IN.UTF-8 br br_FR.ISO8859-1 br_FR br_FR.ISO8859-1 br_FR.iso88591 br_FR.ISO8859-1 br_FR.ISO-8859-1 br_FR.ISO8859-1 br_FR.iso885914 br_FR.ISO8859-14 br_FR.ISO-8859-14 br_FR.ISO8859-14 br_FR.iso885915 br_FR.ISO8859-15 br_FR.ISO-8859-15 br_FR.ISO8859-15 br_FR.ISO-8859-15@euro br_FR.ISO8859-15 br_FR@euro br_FR.ISO8859-15 br_FR.UTF-8@euro br_FR.UTF-8 bs bs_BA.ISO8859-2 bs_BA bs_BA.ISO8859-2 bs_BA.iso88592 bs_BA.ISO8859-2 bs_BA.ISO-8859-2 bs_BA.ISO8859-2 bs_BA.ISO_8859-2 bs_BA.ISO8859-2 ca ca_ES.ISO8859-1 ca_AD ca_AD.ISO8859-1 ca_AD@euro ca_AD.ISO8859-15 ca_AD.iso88591 ca_AD.ISO8859-1 ca_AD.ISO-8859-1 ca_AD.ISO8859-1 ca_AD.iso885915 ca_AD.ISO8859-15 ca_AD.utf8 ca_AD.UTF-8 ca_AD.ISO-8859-15 ca_AD.ISO8859-15 ca_AD.ISO-8859-15@euro ca_AD.ISO8859-15 ca_AD.UTF-8@euro ca_AD.UTF-8 ca_ES ca_ES.ISO8859-1 ca_ES@euro ca_ES.ISO8859-15 ca_ES.iso88591 ca_ES.ISO8859-1 ca_ES.ISO-8859-1 ca_ES.ISO8859-1 ca_ES.iso885915 ca_ES.ISO8859-15 ca_ES.utf8 ca_ES.UTF-8 ca_ES.ISO-8859-15 ca_ES.ISO8859-15 ca_ES.ISO-8859-15@euro ca_ES.ISO8859-15 ca_ES.UTF-8@euro ca_ES.UTF-8 ca_FR ca_FR.ISO8859-1 ca_FR@euro ca_FR.ISO8859-15 ca_FR.iso88591 ca_FR.ISO8859-1 ca_FR.ISO-8859-1 ca_FR.ISO8859-1 ca_FR.iso885915 ca_FR.ISO8859-15 ca_FR.utf8 ca_FR.UTF-8 ca_FR.ISO-8859-15 ca_FR.ISO8859-15 ca_FR.ISO-8859-15@euro ca_FR.ISO8859-15 ca_FR.UTF-8@euro ca_FR.UTF-8 ca_IT ca_IT.ISO8859-1 ca_IT@euro ca_IT.ISO8859-15 ca_IT.iso88591 ca_IT.ISO8859-1 ca_IT.ISO-8859-1 ca_IT.ISO8859-1 ca_IT.iso885915 ca_IT.ISO8859-15 ca_IT.utf8 ca_IT.UTF-8 ca_IT.ISO-8859-15 ca_IT.ISO8859-15 ca_IT.ISO-8859-15@euro ca_IT.ISO8859-15 ca_IT.UTF-8@euro ca_IT.UTF-8 cs cs_CZ.ISO8859-2 cs_CS cs_CZ.ISO8859-2 cs_CS.ISO8859-2 cs_CZ.ISO8859-2 cs_CZ cs_CZ.ISO8859-2 cs_CZ.iso88592 cs_CZ.ISO8859-2 cs_CS.iso8859-2 cs_CZ.ISO8859-2 cs_CZ.ISO-8859-2 cs_CZ.ISO8859-2 cs_CZ.ISO_8859-2 cs_CZ.ISO8859-2 cs_CZ.utf8 cs_CZ.UTF-8 cy cy_GB.ISO8859-1 cy_GB cy_GB.ISO8859-1 cy_GB.iso88591 cy_GB.ISO8859-1 cy_GB.ISO-8859-1 cy_GB.ISO8859-1 cy_GB.iso885914 cy_GB.ISO8859-14 cy_GB.ISO-8859-14 cy_GB.ISO8859-14 cy_GB.iso885915 cy_GB.ISO8859-15 cy_GB.ISO-8859-15 cy_GB.ISO8859-15 da da_DK.ISO8859-1 da.ISO8859-15 da_DK.ISO8859-15 da_DK da_DK.ISO8859-1 DA_DK da_DK.ISO8859-1 da_DK.88591 da_DK.ISO8859-1 da_DK.88591.en da_DK.ISO8859-1 da_DK.iso88591 da_DK.ISO8859-1 da_DK.ISO-8859-1 da_DK.ISO8859-1 da_DK.ISO_8859-1 da_DK.ISO8859-1 da_DK.iso885915 da_DK.ISO8859-15 da_DK.ISO-8859-15 da_DK.ISO8859-15 da_DK.8859-15 da_DK.ISO8859-15 da_DK.utf8 da_DK.UTF-8 DA_DK.UTF-8 da_DK.UTF-8 de de_DE.ISO8859-1 de.ISO8859-15 de_DE.ISO8859-15 de_AT de_AT.ISO8859-1 de_AT@euro de_AT.ISO8859-15 de_AT.iso88591 de_AT.ISO8859-1 de_AT.ISO-8859-1 de_AT.ISO8859-1 de_AT.ISO_8859-1 de_AT.ISO8859-1 de_AT.iso885915 de_AT.ISO8859-15 de_AT.ISO-8859-15 de_AT.ISO8859-15 de_AT.ISO-8859-15@euro de_AT.ISO8859-15 de_AT.UTF-8@euro de_AT.UTF-8 de_AT.utf8 de_AT.UTF-8 de_BE de_BE.ISO8859-1 de_BE@euro de_BE.ISO8859-15 de_BE.iso88591 de_BE.ISO8859-1 de_BE.ISO_8859-1 de_BE.ISO8859-1 de_BE.ISO-8859-1 de_BE.ISO8859-1 de_BE.iso885915 de_BE.ISO8859-15 de_BE.ISO_8859-15 de_BE.ISO8859-15 de_BE.ISO-8859-15 de_BE.ISO8859-15 de_BE.ISO-8859-15@euro de_BE.ISO8859-15 de_BE.UTF-8@euro de_BE.UTF-8 de_CH de_CH.ISO8859-1 de_CH.iso88591 de_CH.ISO8859-1 de_CH.ISO_8859-1 de_CH.ISO8859-1 de_CH.ISO-8859-1 de_CH.ISO8859-1 de_CH.iso885915 de_CH.ISO8859-15 de_CH.ISO_8859-15 de_CH.ISO8859-15 de_CH.ISO-8859-15 de_CH.ISO8859-15 de_CH.utf8 de_CH.UTF-8 de_DE de_DE.ISO8859-1 de_DE@euro de_DE.ISO8859-15 de_DE.88591 de_DE.ISO8859-1 de_DE.88591.en de_DE.ISO8859-1 de_DE.iso88591 de_DE.ISO8859-1 de_DE.ISO-8859-1 de_DE.ISO8859-1 de_DE.ISO_8859-1 de_DE.ISO8859-1 de_DE.iso885915 de_DE.ISO8859-15 de_DE.ISO-8859-15 de_DE.ISO8859-15 de_DE.ISO_8859-15 de_DE.ISO8859-15 de_DE.8859-15 de_DE.ISO8859-15 de_DE.8859-15@euro de_DE.ISO8859-15 de_DE.ISO-8859-15@euro de_DE.ISO8859-15 de_DE.UTF-8@euro de_DE.UTF-8 de_DE.utf8 de_DE.UTF-8 de_IT de_IT.UTF-8 de_IT.utf8 de_IT.UTF-8 de_LI de_LI.ISO8859-1 de_LI.iso88591 de_LI.ISO8859-1 de_LI.ISO_8859-1 de_LI.ISO8859-1 de_LI.ISO-8859-1 de_LI.ISO8859-1 de_LI.iso885915 de_LI.ISO8859-15 de_LI.ISO_8859-15 de_LI.ISO8859-15 de_LI.ISO-8859-15 de_LI.ISO8859-15 de_LI.utf8 de_LI.UTF-8 de_LU de_LU.ISO8859-1 de_LU@euro de_LU.ISO8859-15 de_LU.iso88591 de_LU.ISO8859-1 de_LU.ISO_8859-1 de_LU.ISO8859-1 de_LU.ISO-8859-1 de_LU.ISO8859-1 de_LU.iso885915 de_LU.ISO8859-15 de_LU.ISO_8859-15 de_LU.ISO8859-15 de_LU.ISO-8859-15 de_LU.ISO8859-15 de_LU.ISO-8859-15@euro de_LU.ISO8859-15 de_LU.UTF-8@euro de_LU.UTF-8 de_LU.utf8 de_LU.UTF-8 GER_DE.8859 de_DE.ISO8859-1 GER_DE.8859.in de_DE.ISO8859-1 ee ee_EE.ISO8859-4 ee_EE ee_EE.ISO8859-4 ee_EE.iso88594 ee_EE.ISO8859-4 el el_GR.ISO8859-7 el_GR el_GR.ISO8859-7 el_GR.iso88597 el_GR.ISO8859-7 el_GR.ISO-8859-7 el_GR.ISO8859-7 el_GR@euro el_GR.ISO8859-15 el_GR.utf8 el_GR.UTF-8 en en_US.ISO8859-1 en.ISO-8859-1 en_US.ISO8859-1 en_AU en_AU.ISO8859-1 en_AU.iso88591 en_AU.ISO8859-1 en_AU.ISO-8859-1 en_AU.ISO8859-1 en_AU.ISO_8859-1 en_AU.ISO8859-1 en_AU.utf8 en_AU.UTF-8 en_BE en_BE.ISO8859-1 en_BE@euro en_BE.ISO8859-15 en_BE.utf8 en_BE.UTF-8 en_BW en_BW.ISO8859-1 en_BW.utf8 en_BW.UTF-8 en_BW.iso88591 en_BW.ISO8859-1 en_BW.ISO-8859-1 en_BW.ISO8859-1 en_CA en_CA.ISO8859-1 en_CA.iso88591 en_CA.ISO8859-1 en_CA.ISO-8859-1 en_CA.ISO8859-1 en_CA.ISO_8859-1 en_CA.ISO8859-1 en_CA.utf8 en_CA.UTF-8 en_DL.utf8 en_DL.UTF-8 en_GB en_GB.ISO8859-1 en_GB.88591 en_GB.ISO8859-1 en_GB.88591.en en_GB.ISO8859-1 en_GB.iso88591 en_GB.ISO8859-1 en_GB.ISO-8859-1 en_GB.ISO8859-1 en_GB.ISO_8859-1 en_GB.ISO8859-1 en_GB.iso885915 en_GB.ISO8859-15 en_GB.ISO-8859-15 en_GB.ISO8859-15 en_GB.utf8 en_GB.UTF-8 en_UK en_GB.ISO8859-1 ENG_GB.8859 en_GB.ISO8859-1 ENG_GB.8859.in en_GB.ISO8859-1 en_HK en_HK.ISO8859-1 en_HK.iso88591 en_HK.ISO8859-1 en_HK.ISO-8859-1 en_HK.ISO8859-1 en_HK.utf8 en_HK.UTF-8 en_IE en_IE.ISO8859-1 en_IE.iso88591 en_IE.ISO8859-1 en_IE.ISO-8859-1 en_IE.ISO8859-1 en_IE.iso885915 en_IE.ISO8859-15 en_IE.ISO-8859-15 en_IE.ISO8859-15 en_IE.ISO-8859-15@euro en_IE.ISO8859-15 en_IE@euro en_IE.ISO8859-15 en_IE.UTF-8@euro en_IE.UTF-8 en_IE.utf8 en_IE.UTF-8 en_IN.utf8 en_IN.UTF-8 en_IN en_IN.ISO8859-1 en_NZ en_NZ.ISO8859-1 en_NZ.iso88591 en_NZ.ISO8859-1 en_NZ.ISO-8859-1 en_NZ.ISO8859-1 en_NZ.utf8 en_NZ.UTF-8 en_PH en_PH.ISO8859-1 en_PH.utf8 en_PH.UTF-8 en_PH.iso88591 en_PH.ISO8859-1 en_PH.ISO-8859-1 en_PH.ISO8859-1 en_SG en_SG.ISO8859-1 en_SG.utf8 en_SG.UTF-8 en_SG.iso88591 en_SG.ISO8859-1 en_SG.ISO-8859-1 en_SG.ISO8859-1 en_US en_US.ISO8859-1 EN_US en_US.ISO8859-1 en_US.88591 en_US.ISO8859-1 en_US.88591.en en_US.ISO8859-1 en_US.iso88591 en_US.ISO8859-1 en_US.ISO-8859-1 en_US.ISO8859-1 en_US.ISO_8859-1 en_US.ISO8859-1 en_US.iso885915 en_US.ISO8859-15 en_US.ISO-8859-15 en_US.ISO8859-15 en_US.8859-15 en_US.ISO8859-15 en_US.ISO8859-15@euro en_US.ISO8859-15 en_US.utf8 en_US.UTF-8 EN_US.UTF-8 en_US.UTF-8 en_ZA en_ZA.ISO8859-1 en_ZA.88591 en_ZA.ISO8859-1 en_ZA.88591.en en_ZA.ISO8859-1 en_ZA.iso88591 en_ZA.ISO8859-1 en_ZA.ISO-8859-1 en_ZA.ISO8859-1 en_ZA.ISO_8859-1 en_ZA.ISO8859-1 en_ZA.iso885915 en_ZA.ISO8859-15 en_ZA.ISO-8859-15 en_ZA.ISO8859-15 en_ZA.utf8 en_ZA.UTF-8 en_ZW en_ZW.ISO8859-1 en_ZW.utf8 en_ZS.UTF-8 en_ZW.iso88591 en_ZW.ISO8859-1 en_ZW.ISO-8859-1 en_ZW.ISO8859-1 eo eo_XX.ISO8859-3 eo_EO eo_EO.ISO8859-3 eo_XX eo_XX.ISO8859-3 es es_ES.ISO8859-1 es.UTF-8 es_ES.UTF-8 es_AR es_AR.ISO8859-1 es_AR.iso88591 es_AR.ISO8859-1 es_AR.ISO-8859-1 es_AR.ISO8859-1 es_AR.utf8 es_AR.UTF-8 es_BO es_BO.ISO8859-1 es_BO.iso88591 es_BO.ISO8859-1 es_BO.ISO-8859-1 es_BO.ISO8859-1 es_BO.utf8 es_BO.UTF-8 es_CL es_CL.ISO8859-1 es_CL.iso88591 es_CL.ISO8859-1 es_CL.ISO-8859-1 es_CL.ISO8859-1 es_CL.utf8 es_CL.UTF-8 es_CO es_CO.ISO8859-1 es_CO.iso88591 es_CO.ISO8859-1 es_CO.ISO-8859-1 es_CO.ISO8859-1 es_CO.utf8 es_CO.UTF-8 es_CR es_CR.ISO8859-1 es_CR.iso88591 es_CR.ISO8859-1 es_CR.ISO-8859-1 es_CR.ISO8859-1 es_CR.utf8 es_CR.UTF-8 es_DO es_DO.ISO8859-1 es_DO.iso88591 es_DO.ISO8859-1 es_DO.ISO-8859-1 es_DO.ISO8859-1 es_DO.utf8 es_DO.UTF-8 es_EC es_EC.ISO8859-1 es_EC.iso88591 es_EC.ISO8859-1 es_EC.ISO-8859-1 es_EC.ISO8859-1 es_EC.utf8 es_EC.UTF-8 es_ES es_ES.ISO8859-1 es_ES.88591 es_ES.ISO8859-1 es_ES.88591.en es_ES.ISO8859-1 es_ES.iso88591 es_ES.ISO8859-1 es_ES.ISO-8859-1 es_ES.ISO8859-1 es_ES.ISO_8859-1 es_ES.ISO8859-1 es_ES.iso885915 es_ES.ISO8859-15 es_ES.ISO-8859-15 es_ES.ISO8859-15 es_ES.ISO-8859-15@euro es_ES.ISO8859-15 es_ES@euro es_ES.ISO8859-15 es_ES.UTF-8@euro es_ES.UTF-8 es_ES.utf8 es_ES.UTF-8 es_GT es_GT.ISO8859-1 es_GT.iso88591 es_GT.ISO8859-1 es_GT.ISO-8859-1 es_GT.ISO8859-1 es_GT.utf8 es_GT.UTF-8 es_HN es_HN.ISO8859-1 es_HN.iso88591 es_HN.ISO8859-1 es_HN.ISO-8859-1 es_HN.ISO8859-1 es_HN.utf8 es_HN.UTF-8 es_MX es_MX.ISO8859-1 es_MX.iso88591 es_MX.ISO8859-1 es_MX.ISO-8859-1 es_MX.ISO8859-1 es_MX.utf8 es_MX.UTF-8 es_NI es_NI.ISO8859-1 es_NI.iso88591 es_NI.ISO8859-1 es_NI.ISO-8859-1 es_NI.ISO8859-1 es_NI.utf8 es_NI.UTF-8 es_PA es_PA.ISO8859-1 es_PA.iso88591 es_PA.ISO8859-1 es_PA.ISO-8859-1 es_PA.ISO8859-1 es_PA.iso885915 es_PA.ISO8859-15 es_PA.utf8 es_PA.UTF-8 es_PE es_PE.ISO8859-1 es_PE.iso88591 es_PE.ISO8859-1 es_PE.ISO-8859-1 es_PE.ISO8859-1 es_PE.iso885915 es_PE.ISO8859-15 es_PE.utf8 es_PE.UTF-8 es_PR es_PR.ISO8859-1 es_PR.iso88591 es_PR.ISO8859-1 es_PR.ISO-8859-1 es_PR.ISO8859-1 es_PR.utf8 es_PR.UTF-8 es_PY es_PY.ISO8859-1 es_PY.iso88591 es_PY.ISO8859-1 es_PY.ISO-8859-1 es_PY.ISO8859-1 es_PY.iso885915 es_PY.ISO8859-15 es_PY.utf8 es_PY.UTF-8 es_SV es_SV.ISO8859-1 es_SV.iso88591 es_SV.ISO8859-1 es_SV.ISO-8859-1 es_SV.ISO8859-1 es_SV.iso885915 es_SV.ISO8859-15 es_SV.utf8 es_SV.UTF-8 es_US es_US.ISO8859-1 es_US.iso88591 es_US.ISO8859-1 es_US.ISO-8859-1 es_US.ISO8859-1 es_UY es_UY.ISO8859-1 es_UY.iso88591 es_UY.ISO8859-1 es_UY.ISO-8859-1 es_UY.ISO8859-1 es_UY.iso885915 es_UY.ISO8859-15 es_UY.utf8 es_UY.UTF-8 es_VE es_VE.ISO8859-1 es_VE.iso88591 es_VE.ISO8859-1 es_VE.ISO-8859-1 es_VE.ISO8859-1 es_VE.iso885915 es_VE.ISO8859-15 es_VE.utf8 es_VE.UTF-8 # According to Estonian local standards, ISO8859-4 is not a recommended # charset. EVS8:2000 specifies ISO8859-15 as the base charset. et et_EE.ISO8859-15 et_EE et_EE.ISO8859-15 et_EE.iso88591 et_EE.ISO8859-1 et_EE.ISO-8859-1 et_EE.ISO8859-1 et_EE.iso88594 et_EE.ISO8859-4 et_EE.ISO-8859-4 et_EE.ISO8859-4 et_EE.iso885913 et_EE.ISO8859-13 et_EE.ISO-8859-13 et_EE.ISO8859-13 et_EE.iso885915 et_EE.ISO8859-15 et_EE.ISO-8859-15 et_EE.ISO8859-15 et_EE.utf8 et_EE.UTF-8 eu eu_ES.ISO8859-1 eu_ES eu_ES.ISO8859-1 eu_ES.iso88591 eu_ES.ISO8859-1 eu_ES.ISO-8859-1 eu_ES.ISO8859-1 eu_ES.iso885915 eu_ES.ISO8859-15 eu_ES.ISO-8859-15 eu_ES.ISO8859-15 eu_ES.ISO-8859-15@euro eu_ES.ISO8859-15 eu_ES@euro eu_ES.ISO8859-15 eu_ES.UTF-8@euro eu_ES.UTF-8 fa fa_IR.UTF-8 fa_IR fa_IR.UTF-8 fa_IR.isiri3342 fa_IR.ISIRI-3342 fa_IR.utf8 fa_IR.UTF-8 fi fi_FI.ISO8859-15 fi.ISO8859-15 fi_FI.ISO8859-15 fi_FI fi_FI.ISO8859-15 fi_FI.88591 fi_FI.ISO8859-1 fi_FI.88591.en fi_FI.ISO8859-1 fi_FI.iso88591 fi_FI.ISO8859-1 fi_FI.ISO-8859-1 fi_FI.ISO8859-1 fi_FI.ISO_8859-1 fi_FI.ISO8859-1 fi_FI.iso885915 fi_FI.ISO8859-15 fi_FI.ISO-8859-15 fi_FI.ISO8859-15 fi_FI.ISO-8859-15@euro fi_FI.ISO8859-15 fi_FI@euro fi_FI.ISO8859-15 fi_FI.utf8 fi_FI.UTF-8 fi_FI.UTF-8@euro fi_FI.UTF-8 fo fo_FO.ISO8859-1 fo_FO fo_FO.ISO8859-1 fo_FO.iso88591 fo_FO.ISO8859-1 fo_FO.ISO-8859-1 fo_FO.ISO8859-1 fo_FO.iso885915 fo_FO.ISO8859-15 fo_FO.ISO-8859-15 fo_FO.ISO8859-15 fo_FO.utf8 fo_FO.UTF-8 fr fr_FR.ISO8859-1 fr.ISO8859-15 fr_FR.ISO8859-15 fr.UTF-8 fr_FR.UTF-8 fr_BE fr_BE.ISO8859-1 fr_BE.88591 fr_BE.ISO8859-1 fr_BE.88591.en fr_BE.ISO8859-1 fr_BE.ISO-8859-1 fr_BE.ISO8859-1 fr_BE.ISO_8859-1 fr_BE.ISO8859-1 fr_BE.iso885915 fr_BE.ISO8859-15 fr_BE.ISO-8859-15 fr_BE.ISO8859-15 fr_BE.ISO-8859-15@euro fr_BE.ISO8859-15 fr_BE@euro fr_BE.ISO8859-15 fr_BE.utf8 fr_BE.UTF-8 fr_BE.UTF-8@euro fr_BE.UTF-8 fr_CA fr_CA.ISO8859-1 fr_CA.88591 fr_CA.ISO8859-1 fr_CA.88591.en fr_CA.ISO8859-1 fr_CA.iso88591 fr_CA.ISO8859-1 fr_CA.ISO-8859-1 fr_CA.ISO8859-1 fr_CA.ISO_8859-1 fr_CA.ISO8859-1 fr_CA.iso885915 fr_CA.ISO8859-15 fr_CA.ISO-8859-15 fr_CA.ISO8859-15 fr_CA.utf8 fr_CA.UTF-8 fr_CH fr_CH.ISO8859-1 fr_CH.88591 fr_CH.ISO8859-1 fr_CH.88591.en fr_CH.ISO8859-1 fr_CH.ISO-8859-1 fr_CH.ISO8859-1 fr_CH.ISO_8859-1 fr_CH.ISO8859-1 fr_CH.iso885915 fr_CH.ISO8859-15 fr_CH.ISO-8859-15 fr_CH.ISO8859-15 fr_CH.utf8 fr_CH.UTF-8 fr_FR fr_FR.ISO8859-1 fr_FR.88591 fr_FR.ISO8859-1 fr_FR.88591.en fr_FR.ISO8859-1 fr_FR.iso88591 fr_FR.ISO8859-1 fr_FR.ISO-8859-1 fr_FR.ISO8859-1 fr_FR.ISO_8859-1 fr_FR.ISO8859-1 fr_FR.iso885915 fr_FR.ISO8859-15 fr_FR.ISO-8859-15 fr_FR.ISO8859-15 fr_FR.ISO-8859-15@euro fr_FR.ISO8859-15 fr_FR@euro fr_FR.ISO8859-15 fr_FR.UTF-8@euro fr_FR.UTF-8 fr_FR.utf8 fr_FR.UTF-8 fr_LU fr_LU.ISO8859-1 fr_LU.88591 fr_LU.ISO8859-1 fr_LU.88591.en fr_LU.ISO8859-1 fr_LU.iso88591 fr_LU.ISO8859-1 fr_LU.ISO-8859-1 fr_LU.ISO8859-1 fr_LU.ISO_8859-1 fr_LU.ISO8859-1 fr_LU.iso885915 fr_LU.ISO8859-15 fr_LU.ISO-8859-15 fr_LU.ISO8859-15 fr_LU.ISO-8859-15@euro fr_LU.ISO8859-15 fr_LU@euro fr_LU.ISO8859-15 fr_LU.UTF-8@euro fr_LU.UTF-8 fr_LU.utf8 fr_LU.UTF-8 FRE_FR.8859 fr_FR.ISO8859-1 FRE_FR.8859.in fr_FR.ISO8859-1 ga ga_IE.ISO8859-1 ga_IE ga_IE.ISO8859-1 ga_IE.iso88591 ga_IE.ISO8859-1 ga_IE.ISO-8859-1 ga_IE.ISO8859-1 ga_IE.iso885914 ga_IE.ISO8859-14 ga_IE.ISO-8859-14 ga_IE.ISO8859-14 ga_IE.iso885915 ga_IE.ISO8859-15 ga_IE.ISO-8859-15 ga_IE.ISO8859-15 ga_IE.ISO-8859-15@euro ga_IE.ISO8859-15 ga_IE@euro ga_IE.ISO8859-15 ga_IE.UTF-8@euro ga_IE.UTF-8 ga_IE.utf8 ga_IE.UTF-8 gd gd_GB.ISO8859-1 gd_GB gd_GB.ISO8859-1 gd_GB.iso88591 gd_GB.ISO8859-1 gd_GB.ISO-8859-1 gd_GB.ISO8859-1 gd_GB.iso885914 gd_GB.ISO8859-14 gd_GB.ISO-8859-14 gd_GB.ISO8859-14 gd_GB.iso885915 gd_GB.ISO8859-15 gd_GB.ISO-8859-15 gd_GB.ISO8859-15 gl gl_ES.ISO8859-1 gl_ES gl_ES.ISO8859-1 gl_ES.iso88591 gl_ES.ISO8859-1 gl_ES.ISO-8859-1 gl_ES.ISO8859-1 gl_ES.iso885915 gl_ES.ISO8859-15 gl_ES.ISO-8859-15 gl_ES.ISO8859-15 gl_ES.ISO-8859-15@euro gl_ES.ISO8859-15 gl_ES@euro gl_ES.ISO8859-15 gl_ES.UTF-8@euro gl_ES.UTF-8 gl_ES.utf8 gl_ES.UTF-8 gu_IN gu_IN.UTF-8 gu_IN.utf8 gu_IN.UTF-8 gv gv_GB.ISO8859-1 gv_GB gv_GB.ISO8859-1 gv_GB.iso88591 gv_GB.ISO8859-1 gv_GB.ISO-8859-1 gv_GB.ISO8859-1 gv_GB.iso885914 gv_GB.ISO8859-14 gv_GB.ISO-8859-14 gv_GB.ISO8859-14 gv_GB.iso885915 gv_GB.ISO8859-15 gv_GB.ISO-8859-15 gv_GB.ISO8859-15 he he_IL.ISO8859-8 he_IL he_IL.ISO8859-8 HE_IL he_IL.ISO8859-8 he_IL.iso88598 he_IL.ISO8859-8 he_IL.ISO-8859-8 he_IL.ISO8859-8 he_IL.cp1255 he_IL.CP1255 he_IL.microsoftcp1255 he_IL.CP1255 he_IL.microsoft-cp1255 he_IL.CP1255 he_IL.MICROSOFT-CP1255 he_IL.CP1255 he_IL.utf8 he_IL.UTF-8 HE_IL.UTF-8 he_IL.UTF-8 hi hi_IN.ISCII-DEV hi_IN hi_IN.ISCII-DEV HI_IN hi_IN.ISCII-DEV hi_IN.isciidev hi_IN.ISCII-DEV hi_IN.utf8 hi_IN.UTF-8 HI_IN.UTF-8 hi_IN.UTF-8 hne hne_IN.UTF-8 hne_IN hne_IN.UTF-8 hne_IN.utf8 hne_IN.UTF-8 hr hr_HR.ISO8859-2 hr_HR hr_HR.ISO8859-2 hr_HR.iso88592 hr_HR.ISO8859-2 hr_HR.ISO-8859-2 hr_HR.ISO8859-2 hr_HR.ISO_8859-2 hr_HR.ISO8859-2 hr_HR.utf8 hr_HR.UTF-8 hu hu_HU.ISO8859-2 hu_HU hu_HU.ISO8859-2 hu_HU.iso88592 hu_HU.ISO8859-2 hu_HU.ISO-8859-2 hu_HU.ISO8859-2 hu_HU.utf8 hu_HU.UTF-8 ia ia.UTF-8 ia.utf8 ia.UTF-8 ie ie.UTF-8 ie.utf8 ie.UTF-8 is is_IS.ISO8859-1 is_IS is_IS.ISO8859-1 is_IS.iso88591 is_IS.ISO8859-1 is_IS.ISO-8859-1 is_IS.ISO8859-1 is_IS.ISO_8859-1 is_IS.ISO8859-1 is_IS.iso885915 is_IS.ISO8859-15 is_IS.ISO-8859-15 is_IS.ISO8859-15 is_IS.utf8 is_IS.UTF-8 it it_IT.ISO8859-1 it.ISO8859-15 it_IT.ISO8859-15 it.UTF-8 it_IT.UTF-8 it_CH it_CH.ISO8859-1 it_CH.iso88591 it_CH.ISO8859-1 it_CH.ISO_8859-1 it_CH.ISO8859-1 it_CH.ISO-8859-1 it_CH.ISO8859-1 it_CH.iso885915 it_CH.ISO8859-15 it_CH.utf8 it_CH.UTF-8 it_IT it_IT.ISO8859-1 it_IT.88591 it_IT.ISO8859-1 it_IT.88591.en it_IT.ISO8859-1 it_IT.iso88591 it_IT.ISO8859-1 it_IT.ISO-8859-1 it_IT.ISO8859-1 it_IT.ISO_8859-1 it_IT.ISO8859-1 it_IT.iso885915 it_IT.ISO8859-15 it_IT.ISO-8859-15 it_IT.ISO8859-15 it_IT.ISO-8859-15@euro it_IT.ISO8859-15 it_IT@euro it_IT.ISO8859-15 it_IT.utf8 it_IT.UTF-8 it_IT.UTF-8@euro it_IT.UTF-8 # NUNACOM is an encoding for the Inuktitut syllabics # we have little else on this encoding. iu iu_CA.NUNACOM-8 iu_CA iu_CA.NUNACOM-8 iu_CA.nunacom8 iu_CA.NUNACOM-8 ja_JP ja_JP.eucJP ja ja_JP.eucJP ja.JIS ja_JP.JIS7 ja.SJIS ja_JP.SJIS ja_JP.ujis ja_JP.eucJP Jp_JP ja_JP.eucJP ja_JP.AJEC ja_JP.eucJP ja_JP.EUC ja_JP.eucJP ja_JP.EUC-JP ja_JP.eucJP ja_JP.EUC_JP ja_JP.eucJP ja_JP.eucjp ja_JP.eucJP ja_JP.ISO-2022-JP ja_JP.JIS7 ja_JP.JIS ja_JP.JIS7 ja_JP.jis7 ja_JP.JIS7 ja_JP.mscode ja_JP.SJIS ja_JP.PCK ja_JP.SJIS ja_JP.sjis ja_JP.SJIS ja_JP.utf8 ja_JP.UTF-8 JA_JP.utf8 ja_JP.UTF-8 ka ka_GE.GEORGIAN-ACADEMY ka_GE ka_GE.GEORGIAN-ACADEMY ka_GE.georgianacademy ka_GE.GEORGIAN-ACADEMY ka_GE.georgianrs ka_GE.GEORGIAN-ACADEMY ka_GE.georgianps ka_GE.GEORGIAN-PS kl kl_GL.ISO8859-1 kl_GL kl_GL.ISO8859-1 kl_GL.iso88591 kl_GL.ISO8859-1 kl_GL.ISO-8859-1 kl_GL.ISO8859-1 kl_GL.iso885915 kl_GL.ISO8859-15 kl_GL.utf8 kl_GL.UTF-8 km_KH km_KH.UTF-8 km_KH.utf8 km_KH.UTF-8 kn kn_IN.UTF-8 kn_IN kn_IN.UTF-8 kn_IN.utf8 kn_IN.UTF-8 ko ko_KR.eucKR ko.UTF-8 ko_KR.UTF-8 ko_KR ko_KR.eucKR KO_KR ko_KR.eucKR ko_KR.EUC ko_KR.eucKR ko_KR.EUC-KR ko_KR.eucKR ko_KR.euc ko_KR.eucKR ko_KR.euckr ko_KR.eucKR ko_KR.utf8 ko_KR.UTF-8 KO_KR.UTF-8 ko_KR.UTF-8 ks ks_IN.UTF-8 ks_IN ks_IN.UTF-8 ks_IN.utf8 ks_IN.UTF-8 ks_IN@devanagari ks_IN.UTF-8@devanagari ks_IN.utf8@devanagari ks_IN.UTF-8@devanagari kw kw_GB.ISO8859-1 kw_GB kw_GB.ISO8859-1 kw_GB.iso88591 kw_GB.ISO8859-1 kw_GB.ISO-8859-1 kw_GB.ISO8859-1 kw_GB.iso885914 kw_GB.ISO8859-14 kw_GB.ISO-8859-14 kw_GB.ISO8859-14 kw_GB.iso885915 kw_GB.ISO8859-15 kw_GB.ISO-8859-15 kw_GB.ISO8859-15 ky ky_KG.UTF-8 ky_KG ky_KG.UTF-8 ky_KG.utf8 ky_KG.UTF-8 lo lo_LA.MULELAO-1 lo_LA lo_LA.MULELAO-1 lo_LA.cp1133 lo_LA.IBM-CP1133 lo_LA.ibmcp1133 lo_LA.IBM-CP1133 lo_LA.mulelao1 lo_LA.MULELAO-1 lt lt_LT.ISO8859-13 lt_LT lt_LT.ISO8859-13 lt_LT.iso88594 lt_LT.ISO8859-4 lt_LT.ISO-8859-4 lt_LT.ISO8859-4 lt_LT.ISO_8859-4 lt_LT.ISO8859-4 lt_LT.iso885913 lt_LT.ISO8859-13 lt_LT.ISO-8859-13 lt_LT.ISO8859-13 lt_LT.ISO_8859-13 lt_LT.ISO8859-13 lt_LT.utf8 lt_LT.UTF-8 lv lv_LV.ISO8859-13 lv_LV lv_LV.ISO8859-13 lv_LV.iso88594 lv_LV.ISO8859-4 lv_LV.ISO-8859-4 lv_LV.ISO8859-4 lv_LV.iso885913 lv_LV.ISO8859-13 lv_LV.ISO-8859-13 lv_LV.ISO8859-13 lv_LV.ISO_8859-13 lv_LV.ISO8859-13 lv_LV.utf8 lv_LV.UTF-8 mai mai_IN.UTF-8 mai_IN mai_IN.UTF-8 mai_IN.utf8 mai_IN.UTF-8 mi mi_NZ.ISO8859-1 mi_NZ mi_NZ.ISO8859-1 mi_NZ.iso88591 mi_NZ.ISO8859-1 mk mk_MK.ISO8859-5 mk_MK mk_MK.ISO8859-5 mk_MK.iso88595 mk_MK.ISO8859-5 mk_MK.ISO-8859-5 mk_MK.ISO8859-5 mk_MK.cp1251 mk_MK.CP1251 mk_MK.microsoftcp1251 mk_MK.CP1251 mk_MK.microsoft-cp1251 mk_MK.CP1251 mk_MK.MICROSOFT-CP1251 mk_MK.CP1251 mk_MK.utf8 mk_MK.UTF-8 ml ml_IN.UTF-8 ml_IN ml_IN.UTF-8 ml_IN.utf8 ml_IN.UTF-8 mr mr_IN.UTF-8 mr_IN mr_IN.UTF-8 mr_IN.utf8 mr_IN.UTF-8 ms ms_MY.ISO8859-1 ms_MY ms_MY.ISO8859-1 ms_MY.iso88591 ms_MY.ISO8859-1 ms_MY.ISO-8859-1 ms_MY.ISO8859-1 mt mt_MT.ISO8859-3 mt_MT mt_MT.ISO8859-3 mt_MT.ISO-8859-3 mt_MT.ISO8859-3 nb nb_NO.ISO8859-1 nb_NO nb_NO.ISO8859-1 nb_NO.88591 nb_NO.ISO8859-1 nb_NO.iso88591 nb_NO.ISO8859-1 nb_NO.ISO-8859-1 nb_NO.ISO8859-1 nb_NO.iso885915 nb_NO.ISO8859-15 nb_NO.ISO-8859-15 nb_NO.ISO8859-15 nb_NO.utf8 nb_NO.UTF-8 ne_NP ne_NP.UTF-8 ne_NP.utf8 ne_NP.UTF-8 nl nl_NL.ISO8859-1 nl.ISO8859-15 nl_NL.ISO8859-15 nl_BE nl_BE.ISO8859-1 nl_BE.88591 nl_BE.ISO8859-1 nl_BE.88591.en nl_BE.ISO8859-1 nl_BE.iso88591 nl_BE.ISO8859-1 nl_BE.ISO-8859-1 nl_BE.ISO8859-1 nl_BE.ISO_8859-1 nl_BE.ISO8859-1 nl_BE.iso885915 nl_BE.ISO8859-15 nl_BE.ISO-8859-15 nl_BE.ISO8859-15 nl_BE.ISO-8859-15@euro nl_BE.ISO8859-15 nl_BE@euro nl_BE.ISO8859-15 nl_BE.utf8 nl_BE.UTF-8 nl_BE.UTF-8@euro nl_BE.UTF-8 nl_NL nl_NL.ISO8859-1 nl_NL.88591 nl_NL.ISO8859-1 nl_NL.88591.en nl_NL.ISO8859-1 nl_NL.iso88591 nl_NL.ISO8859-1 nl_NL.ISO-8859-1 nl_NL.ISO8859-1 nl_NL.ISO_8859-1 nl_NL.ISO8859-1 nl_NL.iso885915 nl_NL.ISO8859-15 nl_NL.ISO-8859-15 nl_NL.ISO8859-15 nl_NL.ISO-8859-15@euro nl_NL.ISO8859-15 nl_NL@euro nl_NL.ISO8859-15 nl_NL.utf8 nl_NL.UTF-8 nl_NL.UTF-8@euro nl_NL.UTF-8 nn nn_NO.ISO8859-1 nn_NO nn_NO.ISO8859-1 nn_NO.88591 nn_NO.ISO8859-1 nn_NO.ISO-8859-1 nn_NO.ISO8859-1 nn_NO.ISO_8859-1 nn_NO.ISO8859-1 nn_NO.iso885915 nn_NO.ISO8859-15 nn_NO.ISO-8859-15 nn_NO.ISO8859-15 nn_NO.utf8 nn_NO.UTF-8 no no_NO.ISO8859-1 no_NO no_NO.ISO8859-1 no_NO.88591 no_NO.ISO8859-1 no_NO.88591.en no_NO.ISO8859-1 no_NO.iso88591 no_NO.ISO8859-1 no_NO.ISO-8859-1 no_NO.ISO8859-1 no_NO.ISO8859-1@bokmal no_NO.ISO8859-1 no_NO.ISO8859-1@nynorsk no_NO.ISO8859-1 no_NO.iso885915 no_NO.ISO8859-15 no_NO.ISO-8859-15 no_NO.ISO8859-15 no_NO.utf8 no_NO.UTF-8 nr nr_ZA.ISO8859-1 nr_ZA nr_ZA.ISO8859-1 nr_ZA.iso88591 nr_ZA.ISO8859-1 nr_ZA.utf8 nr_ZA.UTF-8 nso nso_ZA.ISO8859-15 nso_ZA nso_ZA.ISO8859-15 nso_ZA.iso885915 nso_ZA.ISO8859-15 nso_ZA.utf8 nso_ZA.UTF-8 ny ny_NO.ISO8859-1 ny_NO ny_NO.ISO8859-1 ny_NO.88591 ny_NO.ISO8859-1 ny_NO.ISO_8859-1 ny_NO.ISO8859-1 ny_NO.iso885915 ny_NO.ISO8859-15 no@nynorsk ny_NO.ISO8859-1 nynorsk nn_NO.ISO8859-1 oc oc_FR.ISO8859-1 oc_FR oc_FR.ISO8859-1 oc_FR.iso88591 oc_FR.ISO8859-1 oc_FR.ISO-8859-1 oc_FR.ISO8859-1 oc_FR.iso885915 oc_FR.ISO8859-15 oc_FR.ISO-8859-15 oc_FR.ISO8859-15 oc_FR@euro oc_FR.ISO8859-15 or or_IN.UTF-8 or_IN or_IN.UTF-8 or_IN.utf8 or_IN.UTF-8 pa pa_IN.UTF-8 pa_IN pa_IN.UTF-8 pa_IN.utf8 pa_IN.UTF-8 pa_PK.utf8 pa_PK.UTF-8 pd pd_US.ISO8859-1 pd_DE pd_DE.ISO8859-1 pd_US pd_US.ISO8859-1 pd_DE.iso88591 pd_DE.ISO8859-1 pd_US.iso88591 pd_US.ISO8859-1 pd_DE.iso885915 pd_DE.ISO8859-15 pd_US.iso885915 pd_US.ISO8859-15 ph ph_PH.ISO8859-1 ph_PH ph_PH.ISO8859-1 ph_PH.iso88591 ph_PH.ISO8859-1 pl pl_PL.ISO8859-2 pl.UTF-8 pl_PL.UTF-8 pl_PL pl_PL.ISO8859-2 pl_PL.iso88592 pl_PL.ISO8859-2 pl_PL.ISO-8859-2 pl_PL.ISO8859-2 pl_PL.utf8 pl_PL.UTF-8 pp pp_AN.ISO8859-1 pp_AN pp_AN.ISO8859-1 pp_AN.iso88591 pp_AN.ISO8859-1 pt pt_PT.ISO8859-1 pt.ISO8859-15 pt_PT.ISO8859-15 pt_BR pt_BR.ISO8859-1 pt_BR.88591 pt_BR.ISO8859-1 pt_BR.88591.en pt_BR.ISO8859-1 pt_BR.iso88591 pt_BR.ISO8859-1 pt_BR.ISO-8859-1 pt_BR.ISO8859-1 pt_BR.ISO_8859-1 pt_BR.ISO8859-1 pt_BR.iso885915 pt_BR.ISO8859-15 pt_BR.utf8 pt_BR.UTF-8 pt_PT pt_PT.ISO8859-1 pt_PT.88591 pt_PT.ISO8859-1 pt_PT.88591.en pt_PT.ISO8859-1 pt_PT.iso88591 pt_PT.ISO8859-1 pt_PT.ISO-8859-1 pt_PT.ISO8859-1 pt_PT.ISO_8859-1 pt_PT.ISO8859-1 pt_PT.iso885915 pt_PT.ISO8859-15 pt_PT.ISO-8859-15 pt_PT.ISO8859-15 pt_PT.ISO-8859-15@euro pt_PT.ISO8859-15 pt_PT@euro pt_PT.ISO8859-15 pt_PT.utf8 pt_PT.UTF-8 pt_PT.UTF-8@euro pt_PT.UTF-8 ro ro_RO.ISO8859-2 ro_RO ro_RO.ISO8859-2 ro_RO.iso88592 ro_RO.ISO8859-2 ro_RO.ISO-8859-2 ro_RO.ISO8859-2 ro_RO.utf8 ro_RO.UTF-8 ru ru_RU.UTF-8 ru.koi8-r ru_RU.KOI8-R ru.UTF-8 ru_RU.UTF-8 ru_RU ru_RU.UTF-8 ru_RU.utf8 ru_RU.UTF-8 ru_RU.iso88595 ru_RU.ISO8859-5 ru_RU.ISO-8859-5 ru_RU.ISO8859-5 ru_RU.koi8r ru_RU.KOI8-R ru_RU.cp1251 ru_RU.CP1251 ru_RU.microsoftcp1251 ru_RU.CP1251 ru_RU.microsoft-cp1251 ru_RU.CP1251 ru_RU.MICROSOFT-CP1251 ru_RU.CP1251 ru_UA ru_UA.KOI8-U ru_UA.koi8u ru_UA.KOI8-U ru_UA.cp1251 ru_UA.CP1251 ru_UA.microsoftcp1251 ru_UA.CP1251 ru_UA.microsoft-cp1251 ru_UA.CP1251 ru_UA.MICROSOFT-CP1251 ru_UA.CP1251 rw rw_RW.ISO8859-1 rw_RW rw_RW.ISO8859-1 rw_RW.iso8859-1 rw_RW.ISO8859-1 rw_RW.ISO-8859-1 rw_RW.ISO8859-1 rw_RW.utf8 rw_RW.UTF-8 sd sd_IN.UTF-8 sd_IN.utf8 sd_IN.UTF-8 sd@devanagari sd_IN.UTF-8@devanagari sd_IN@devanagari sd_IN.UTF-8@devanagari sd_IN.utf8@devanagari sd_IN.UTF-8@devanagari se_NO se_NO.UTF-8 se_NO.utf8 se_NO.UTF-8 si si_LK.UTF-8 si_LK si_LK.UTF-8 sk sk_SK.ISO8859-2 sk_SK sk_SK.ISO8859-2 sk_SK.iso88592 sk_SK.ISO8859-2 sk_SK.ISO-8859-2 sk_SK.ISO8859-2 sk_SK.utf8 sk_SK.UTF-8 sl sl_SI.ISO8859-2 sl_SI sl_SI.ISO8859-2 sl_SI.iso88592 sl_SI.ISO8859-2 sl_SI.ISO-8859-2 sl_SI.ISO8859-2 sl_SI.utf8 sl_SI.UTF-8 sq sq_AL.ISO8859-2 sq_AL sq_AL.ISO8859-2 sq_AL.iso88592 sq_AL.ISO8859-2 sq_AL.ISO-8859-2 sq_AL.ISO8859-2 sq_AL.utf8 sq_AL.UTF-8 sr sr_RS.UTF-8 sr@cyrillic sr_RS.UTF-8 sr@latin sr_RS.UTF-8@latin sr@Latn sr_RS.UTF-8@latin sr_RS sr_RS.UTF-8 sr_RS@latin sr_RS.UTF-8@latin sr_RS@Latn sr_RS.UTF-8@latin sr_RS.UTF-8@Latn sr_RS.UTF-8@latin sr_RS.utf8 sr_RS.UTF-8 sr_ME sr_ME.UTF-8 sr_ME.utf8 sr_ME.UTF-8 ss ss_ZA.ISO8859-1 ss_ZA ss_ZA.ISO8859-1 ss_ZA.iso88591 ss_ZA.ISO8859-1 ss_ZA.utf8 ss_ZA.UTF-8 st st_ZA.ISO8859-1 st_ZA st_ZA.ISO8859-1 st_ZA.iso88591 st_ZA.ISO8859-1 st_ZA.utf8 st_ZA.UTF-8 sv sv_SE.ISO8859-1 sv.ISO8859-15 sv_SE.ISO8859-15 sv.UTF-8 sv_SE.UTF-8 sv_FI sv_FI.ISO8859-1 sv_FI.iso88591 sv_FI.ISO8859-1 sv_FI.ISO-8859-1 sv_FI.ISO8859-1 sv_FI.iso885915 sv_FI.ISO8859-15 sv_FI.ISO-8859-15 sv_FI.ISO8859-15 sv_FI.ISO-8859-15@euro sv_FI.ISO8859-15 sv_FI@euro sv_FI.ISO8859-15 sv_FI.UTF-8@euro sv_FI.UTF-8 sv_FI.utf8 sv_FI.UTF-8 sv_SE sv_SE.ISO8859-1 sv_SE.88591 sv_SE.ISO8859-1 sv_SE.88591.en sv_SE.ISO8859-1 sv_SE.iso88591 sv_SE.ISO8859-1 sv_SE.ISO-8859-1 sv_SE.ISO8859-1 sv_SE.ISO_8859-1 sv_SE.ISO8859-1 sv_SE.iso885915 sv_SE.ISO8859-15 sv_SE.ISO-8859-15 sv_SE.ISO8859-15 sv_SE@euro sv_SE.ISO8859-15 sv_SE.utf8 sv_SE.UTF-8 ta ta_IN.TSCII-0 ta_IN ta_IN.TSCII-0 ta_IN.tscii ta_IN.TSCII-0 ta_IN.tscii0 ta_IN.TSCII-0 te te_IN.UTF-8 te.UTF-8 te_IN.UTF-8 te_IN.utf8 te_IN.UTF-8 tg tg_TJ.KOI8-C tg_TJ tg_TJ.KOI8-C tg_TJ.koi8c tg_TJ.KOI8-C th th_TH.ISO8859-11 th_TH th_TH.ISO8859-11 th_TH.ISO-8859-11 th_TH.ISO8859-11 th_TH.tis620 th_TH.TIS620 th_TH.TIS-620 th_TH.TIS620 th_TH.TACTIS th_TH.TIS620 th_TH.utf8 th_TH.UTF-8 tl tl_PH.ISO8859-1 tl_PH tl_PH.ISO8859-1 tl_PH.iso88591 tl_PH.ISO8859-1 tl_PH.ISO-8859-1 tl_PH.ISO8859-1 tn tn_ZA.ISO8859-15 tn_ZA tn_ZA.ISO8859-15 tn_ZA.iso8859-15 tn_ZA.ISO8859-15 tn_ZA.utf8 tn_ZA.UTF-8 tr tr_TR.ISO8859-9 tr_TR tr_TR.ISO8859-9 TR_TR tr_TR.ISO8859-9 tr_TR.iso88599 tr_TR.ISO8859-9 tr_TR.ISO-8859-9 tr_TR.ISO8859-9 tr_TR.utf8 tr_TR.UTF-8 TR_TR.utf8 tr_TR.UTF-8 ts ts_ZA.ISO8859-1 ts_ZA ts_ZA.ISO8859-1 ts_ZA.iso88591 ts_ZA.ISO8859-1 ts_ZA.utf8 ts_ZA.UTF-8 tt tt_RU.TATAR-CYR tt_RU tt_RU.TATAR-CYR tt_RU.tatarcyr tt_RU.TATAR-CYR tt_RU.koi8c tt_RU.KOI8-C uk uk_UA.KOI8-U uk_UA uk_UA.KOI8-U uk_UA.iso88595 uk_UA.ISO8859-5 uk_UA.koi8u uk_UA.KOI8-U uk_UA.cp1251 uk_UA.CP1251 uk_UA.microsoftcp1251 uk_UA.CP1251 uk_UA.microsoft-cp1251 uk_UA.CP1251 uk_UA.MICROSOFT-CP1251 uk_UA.CP1251 uk_UA.utf8 uk_UA.UTF-8 ur ur_IN.UTF-8 ur_IN ur_IN.UTF-8 ur_IN.utf8 ur_IN.UTF-8 ur ur_PK.CP1256 ur_PK ur_PK.CP1256 ur_PK.cp1256 ur_PK.CP1256 ur_PK.microsoftcp1256 ur_PK.CP1256 ur_PK.microsoft-cp1256 ur_PK.CP1256 ur_PK.MICROSOFT-CP1256 ur_PK.CP1256 uz uz_UZ.UTF-8 uz_UZ uz_UZ.UTF-8 uz_UZ.ISO-8859-1 uz_UZ.ISO8859-1 uz_UZ@cyrillic uz_UZ.UTF-8 uz_UZ.UTF-8@cyrillic uz_UZ.UTF-8 ve ve_ZA.UTF-8 ve_ZA ve_ZA.UTF-8 ve_ZA.utf8 ve_ZA.UTF-8 vi vi_VN.TCVN vi_VN vi_VN.TCVN Vi_VN vi_VN.TCVN VI_VN vi_VN.TCVN vi_VN.tcvn vi_VN.TCVN vi_VN.tcvn5712 vi_VN.TCVN vi_VN.viscii vi_VN.VISCII vi_VN.viscii111 vi_VN.VISCII vi_VN.utf8 vi_VN.UTF-8 VI_VN.UTF-8 vi_VN.UTF-8 wa wa_BE.ISO8859-1 wa_BE wa_BE.ISO8859-1 wa_BE.iso88591 wa_BE.ISO8859-1 wa_BE.ISO-8859-1 wa_BE.ISO8859-1 wa_BE.iso885915 wa_BE.ISO8859-15 wa_BE.ISO-8859-15 wa_BE.ISO8859-15 wa_BE.ISO-8859-15@euro wa_BE.ISO8859-15 wa_BE@euro wa_BE.ISO8859-15 xh xh_ZA.ISO8859-1 xh_ZA xh_ZA.ISO8859-1 xh_ZA.iso88591 xh_ZA.ISO8859-1 xh_ZA.utf8 xh_ZA.UTF-8 yi yi_US.CP1255 yi_US yi_US.CP1255 yi_US.cp1255 yi_US.CP1255 yi_US.microsoftcp1255 yi_US.CP1255 yi_US.microsoft-cp1255 yi_US.CP1255 yi_US.MICROSOFT-CP1255 yi_US.CP1255 zh_CN zh_CN.gb2312 zh_CN.Big5 zh_TW.big5 zh_CN.EUC zh_CN.eucCN zh_CN.GB2312 zh_CN.gb2312 zh_CN.GBK zh_CN.gbk zh_CN.GB18030 zh_CN.gb18030 zh_CN.big5 zh_TW.big5 zh_CN.euc zh_CN.eucCN zh_CN.utf8 zh_CN.UTF-8 ZH_CN.UTF-8 zh_CN.UTF-8 zh_HK zh_HK.big5hkscs zh_HK.BIG5HK zh_HK.big5hkscs zh_HK.Big5hkscs zh_HK.big5hkscs zh_HK.Big5-hkscs zh_HK.big5hkscs zh_HK.Big5_hkscs zh_HK.big5hkscs zh_HK.Big5HKSCS zh_HK.big5hkscs zh_HK.BIG5-HKSCS zh_HK.big5hkscs zh_HK.BIG5_HKSCS zh_HK.big5hkscs zh_HK.Big5-HKSCS zh_HK.big5hkscs zh_HK.big5-hkscs zh_HK.big5hkscs zh_HK.Big5-HKSCS zh_HK.big5hkscs zh_HK.Big5HKSCS zh_HK.big5hkscs zh_HK.Big5 zh_HK.big5 zh_HK.utf8 zh_HK.UTF-8 ZH_HK.UTF-8 zh_HK.UTF-8 ZH_SG.UTF-8 zh_SG.UTF-8 zh_TW zh_TW.big5 zh_TW.Big5 zh_TW.big5 zh_TW.BIG5 zh_TW.big5 Zh_TW.big5 zh_TW.big5 zh_TW.EUC zh_TW.eucTW zh_TW.EUC-TW zh_TW.eucTW zh_TW.utf8 zh_TW.UTF-8 ZH_TW.UTF-8 zh_TW.UTF-8 zu zu_ZA.ISO8859-1 zu_ZA zu_ZA.ISO8859-1 zu_ZA.iso88591 zu_ZA.ISO8859-1 zu_ZA.utf8 zu_ZA.UTF-8 # The following locale names are used in SCO 3.0 english_uk.8859 en_GB.ISO8859-1 english_us.8859 en_US.ISO8859-1 english_us.ascii en_US.ISO8859-1 french_france.8859 fr_FR.ISO8859-1 german_germany.8859 de_DE.ISO8859-1 portuguese_brazil.8859 pt_BR.ISO8859-1 spanish_spain.8859 es_ES.ISO8859-1 # The following locale names are used in HPUX 9.x american.iso88591 en_US.ISO8859-1 arabic.iso88596 ar_AA.ISO8859-6 bokmal nb_NO.ISO8859-1 bokml nb_NO.ISO8859-1 bulgarian bg_BG.CP1251 c-french.iso88591 fr_CA.ISO8859-1 catalan ca_ES.ISO8859-1 chinese-s zh_CN.eucCN chinese-t zh_TW.eucTW croatian hr_HR.ISO8859-2 czech cs_CZ.ISO8859-2 danish da_DK.ISO8859-1 dansk da_DK.ISO8859-1 danish.iso88591 da_DK.ISO8859-1 deutsch de_DE.ISO8859-1 dutch nl_NL.ISO8859-1 dutch.iso88591 nl_BE.ISO8859-1 eesti et_EE.ISO8859-1 english.iso88591 en_EN.ISO8859-1 estonian et_EE.ISO8859-1 finnish fi_FI.ISO8859-1 finnish.iso88591 fi_FI.ISO8859-1 franais fr_FR.ISO8859-1 french fr_FR.ISO8859-1 french.iso88591 fr_CH.ISO8859-1 galego gl_ES.ISO8859-1 galician gl_ES.ISO8859-1 german de_DE.ISO8859-1 german.iso88591 de_CH.ISO8859-1 greek el_GR.ISO8859-7 greek.iso88597 el_GR.ISO8859-7 hebrew he_IL.ISO8859-8 hebrew.iso88598 he_IL.ISO8859-8 hrvatski hr_HR.ISO8859-2 hungarian hu_HU.ISO8859-2 icelandic.iso88591 is_IS.ISO8859-1 icelandic is_IS.ISO8859-1 italian it_IT.ISO8859-1 italian.iso88591 it_IT.ISO8859-1 japanese ja_JP.eucJP japanese.euc ja_JP.eucJP japanese.sjis ja_JP.SJIS korean ko_KR.eucKR korean.euc ko_KR.eucKR lithuanian lt_LT.ISO8859-13 norwegian no_NO.ISO8859-1 norwegian.iso88591 no_NO.ISO8859-1 polish pl_PL.ISO8859-2 portuguese pt_PT.ISO8859-1 portuguese.iso88591 pt_PT.ISO8859-1 romanian ro_RO.ISO8859-2 rumanian ro_RO.ISO8859-2 russian ru_RU.ISO8859-5 serbocroatian sr_RS.UTF-8@latin sinhala si_LK.UTF-8 slovak sk_SK.ISO8859-2 slovene sl_SI.ISO8859-2 slovenian sl_SI.ISO8859-2 spanish es_ES.ISO8859-1 spanish.iso88591 es_ES.ISO8859-1 swedish sv_SE.ISO8859-1 swedish.iso88591 sv_SE.ISO8859-1 turkish tr_TR.ISO8859-9 turkish.iso88599 tr_TR.ISO8859-9 thai th_TH.ISO8859-11 univ.utf8 en_US.UTF-8 # Digital Unix utf universal.utf8@ucs4 en_US.UTF-8 # Solaris and SunOS have iso_8859_1 and iso_8859_15 LC_CTYPES # to augment LANG=C iso_8859_1 en_US.ISO8859-1 iso_8859_15 en_US.ISO8859-15 # Other miscellaneous locale names ISO8859-1 en_US.ISO8859-1 ISO-8859-1 en_US.ISO8859-1 japan ja_JP.eucJP Japanese-EUC ja_JP.eucJP # # This file contains alias names of locales. # Each alias name is described within one line. # The first word is the alias name (simplified locale name), # the second word is the full locale name. # # POSIX: C POSIX-UTF2: C C_C.C: C C.en: C C.ASCII: C C.iso88591: en_US.ISO8859-1 Cextend: en_US.ISO8859-1 Cextend.en: en_US.ISO8859-1 English_United-States.437: C C.UTF-8: en_US.UTF-8 # a3 is not an ISO 639 language code, but in Cyrillic, "Z" looks like "3". a3: az_AZ.KOI8-C a3_AZ: az_AZ.KOI8-C a3_AZ.koi8c: az_AZ.KOI8-C a3_AZ.KOI-C: az_AZ.KOI8-C a3_AZ.UTF-8: az_AZ.UTF-8 af: af_ZA.ISO8859-1 af_ZA: af_ZA.ISO8859-1 af_ZA.iso88591: af_ZA.ISO8859-1 af_ZA.ISO-8859-1: af_ZA.ISO8859-1 af_ZA.utf8: af_ZA.UTF-8 am: am_ET.UTF-8 am_ET: am_ET.UTF-8 ar: ar_AA.ISO8859-6 ar_AA: ar_AA.ISO8859-6 AR_AA: ar_AA.ISO8859-6 Ar_AA: ar_AA.ISO8859-6 AR_AA.UTF-8: ar_AA.UTF-8 ar_AA.iso88596: ar_AA.ISO8859-6 ar_AA.ISO-8859-6: ar_AA.ISO8859-6 ar_AE: ar_AE.ISO8859-6 ar_AE.iso88596: ar_AE.ISO8859-6 ar_AE.ISO-8859-6: ar_AE.ISO8859-6 ar_AE.utf8: ar_AE.UTF-8 ar_BH: ar_BH.ISO8859-6 ar_BH.iso88596: ar_BH.ISO8859-6 ar_BH.ISO-8859-6: ar_BH.ISO8859-6 ar_BH.utf8: ar_BH.UTF-8 ar_DZ: ar_DZ.ISO8859-6 ar_DZ.iso88596: ar_DZ.ISO8859-6 ar_DZ.ISO-8859-6: ar_DZ.ISO8859-6 ar_DZ.utf8: ar_DZ.UTF-8 ar_EG: ar_EG.ISO8859-6 ar_EG.iso88596: ar_EG.ISO8859-6 ar_EG.ISO-8859-6: ar_EG.ISO8859-6 ar_EG.utf8: ar_EG.UTF-8 ar_IN: ar_IN.UTF-8 ar_IN.utf8: ar_IN.UTF-8 ar_IQ: ar_IQ.ISO8859-6 ar_IQ.iso88596: ar_IQ.ISO8859-6 ar_IQ.ISO-8859-6: ar_IQ.ISO8859-6 ar_IQ.utf8: ar_IQ.UTF-8 ar_JO: ar_JO.ISO8859-6 ar_JO.iso88596: ar_JO.ISO8859-6 ar_JO.ISO-8859-6: ar_JO.ISO8859-6 ar_JO.utf8: ar_JO.UTF-8 ar_KW: ar_KW.ISO8859-6 ar_KW.iso88596: ar_KW.ISO8859-6 ar_KW.ISO-8859-6: ar_KW.ISO8859-6 ar_KW.utf8: ar_KW.UTF-8 ar_LB: ar_LB.ISO8859-6 ar_LB.iso88596: ar_LB.ISO8859-6 ar_LB.ISO-8859-6: ar_LB.ISO8859-6 ar_LB.utf8: ar_LB.UTF-8 ar_LY: ar_LY.ISO8859-6 ar_LY.iso88596: ar_LY.ISO8859-6 ar_LY.ISO-8859-6: ar_LY.ISO8859-6 ar_LY.utf8: ar_LY.UTF-8 ar_MA: ar_MA.ISO8859-6 ar_MA.iso88596: ar_MA.ISO8859-6 ar_MA.ISO-8859-6: ar_MA.ISO8859-6 ar_MA.utf8: ar_MA.UTF-8 ar_OM: ar_OM.ISO8859-6 ar_OM.iso88596: ar_OM.ISO8859-6 ar_OM.ISO-8859-6: ar_OM.ISO8859-6 ar_OM.utf8: ar_OM.UTF-8 ar_QA: ar_QA.ISO8859-6 ar_QA.iso88596: ar_QA.ISO8859-6 ar_QA.ISO-8859-6: ar_QA.ISO8859-6 ar_QA.utf8: ar_QA.UTF-8 ar_SA: ar_SA.ISO8859-6 ar_SA.iso88596: ar_SA.ISO8859-6 ar_SA.ISO-8859-6: ar_SA.ISO8859-6 ar_SA.utf8: ar_SA.UTF-8 ar_SD: ar_SD.ISO8859-6 ar_SD.iso88596: ar_SD.ISO8859-6 ar_SD.ISO-8859-6: ar_SD.ISO8859-6 ar_SD.utf8: ar_SD.UTF-8 ar_SY: ar_SY.ISO8859-6 ar_SY.iso88596: ar_SY.ISO8859-6 ar_SY.ISO-8859-6: ar_SY.ISO8859-6 ar_SY.utf8: ar_SY.UTF-8 ar_TN: ar_TN.ISO8859-6 ar_TN.iso88596: ar_TN.ISO8859-6 ar_TN.ISO-8859-6: ar_TN.ISO8859-6 ar_TN.utf8: ar_TN.UTF-8 as: as_IN.UTF-8 as_IN: as_IN.UTF-8 as_IN.utf8: as_IN.UTF-8 ar_YE: ar_YE.ISO8859-6 ar_YE.iso88596: ar_YE.ISO8859-6 ar_YE.ISO-8859-6: ar_YE.ISO8859-6 ar_YE.utf8: ar_YE.UTF-8 az: az_AZ.ISO8859-9E az_AZ: az_AZ.ISO8859-9E az_AZ.iso88599e: az_AZ.ISO8859-9E be: be_BY.CP1251 be@latin: be_BY.UTF-8@latin be_BY: be_BY.CP1251 be_BY@latin: be_BY.UTF-8@latin be_BY.cp1251: be_BY.CP1251 be_BY.microsoftcp1251: be_BY.CP1251 be_BY.microsoft-cp1251: be_BY.CP1251 be_BY.MICROSOFT-CP1251: be_BY.CP1251 be_BY.utf8: be_BY.UTF-8 be_BY.utf8@latin: be_BY.UTF-8@latin bg: bg_BG.CP1251 bg_BG: bg_BG.CP1251 bg_BG.cp1251: bg_BG.CP1251 bg_BG.microsoftcp1251: bg_BG.CP1251 bg_BG.microsoft-cp1251: bg_BG.CP1251 bg_BG.MICROSOFT-CP1251: bg_BG.CP1251 bg_BG.iso88595: bg_BG.ISO8859-5 bg_BG.ISO-8859-5: bg_BG.ISO8859-5 bg_BG.koi8r: bg_BG.KOI8-R be_BG.utf8: bg_BG.UTF-8 bn_IN: bn_IN.UTF-8 bn_IN.utf8: bn_IN.UTF-8 bo_IN: bo_IN.UTF-8 bo_IN.utf8: bo_IN.UTF-8 br: br_FR.ISO8859-1 br_FR: br_FR.ISO8859-1 br_FR.iso88591: br_FR.ISO8859-1 br_FR.ISO-8859-1: br_FR.ISO8859-1 br_FR.iso885914: br_FR.ISO8859-14 br_FR.ISO-8859-14: br_FR.ISO8859-14 br_FR.iso885915: br_FR.ISO8859-15 br_FR.ISO-8859-15: br_FR.ISO8859-15 br_FR.ISO-8859-15@euro: br_FR.ISO8859-15 br_FR@euro: br_FR.ISO8859-15 br_FR.UTF-8@euro: br_FR.UTF-8 bs: bs_BA.ISO8859-2 bs_BA: bs_BA.ISO8859-2 bs_BA.iso88592: bs_BA.ISO8859-2 bs_BA.ISO-8859-2: bs_BA.ISO8859-2 bs_BA.ISO_8859-2: bs_BA.ISO8859-2 ca: ca_ES.ISO8859-1 ca_AD: ca_AD.ISO8859-1 ca_AD@euro: ca_AD.ISO8859-15 ca_AD.iso88591: ca_AD.ISO8859-1 ca_AD.ISO-8859-1: ca_AD.ISO8859-1 ca_AD.iso885915: ca_AD.ISO8859-15 ca_AD.utf8: ca_AD.UTF-8 ca_AD.ISO-8859-15: ca_AD.ISO8859-15 ca_AD.ISO-8859-15@euro: ca_AD.ISO8859-15 ca_AD.UTF-8@euro: ca_AD.UTF-8 ca_ES: ca_ES.ISO8859-1 ca_ES@euro: ca_ES.ISO8859-15 ca_ES.iso88591: ca_ES.ISO8859-1 ca_ES.ISO-8859-1: ca_ES.ISO8859-1 ca_ES.iso885915: ca_ES.ISO8859-15 ca_ES.utf8: ca_ES.UTF-8 ca_ES.ISO-8859-15: ca_ES.ISO8859-15 ca_ES.ISO-8859-15@euro: ca_ES.ISO8859-15 ca_ES.UTF-8@euro: ca_ES.UTF-8 ca_FR: ca_FR.ISO8859-1 ca_FR@euro: ca_FR.ISO8859-15 ca_FR.iso88591: ca_FR.ISO8859-1 ca_FR.ISO-8859-1: ca_FR.ISO8859-1 ca_FR.iso885915: ca_FR.ISO8859-15 ca_FR.utf8: ca_FR.UTF-8 ca_FR.ISO-8859-15: ca_FR.ISO8859-15 ca_FR.ISO-8859-15@euro: ca_FR.ISO8859-15 ca_FR.UTF-8@euro: ca_FR.UTF-8 ca_IT: ca_IT.ISO8859-1 ca_IT@euro: ca_IT.ISO8859-15 ca_IT.iso88591: ca_IT.ISO8859-1 ca_IT.ISO-8859-1: ca_IT.ISO8859-1 ca_IT.iso885915: ca_IT.ISO8859-15 ca_IT.utf8: ca_IT.UTF-8 ca_IT.ISO-8859-15: ca_IT.ISO8859-15 ca_IT.ISO-8859-15@euro: ca_IT.ISO8859-15 ca_IT.UTF-8@euro: ca_IT.UTF-8 cs: cs_CZ.ISO8859-2 cs_CS: cs_CZ.ISO8859-2 cs_CS.ISO8859-2: cs_CZ.ISO8859-2 cs_CZ: cs_CZ.ISO8859-2 cs_CZ.iso88592: cs_CZ.ISO8859-2 cs_CS.iso8859-2: cs_CZ.ISO8859-2 cs_CZ.ISO-8859-2: cs_CZ.ISO8859-2 cs_CZ.ISO_8859-2: cs_CZ.ISO8859-2 cs_CZ.utf8: cs_CZ.UTF-8 cy: cy_GB.ISO8859-1 cy_GB: cy_GB.ISO8859-1 cy_GB.iso88591: cy_GB.ISO8859-1 cy_GB.ISO-8859-1: cy_GB.ISO8859-1 cy_GB.iso885914: cy_GB.ISO8859-14 cy_GB.ISO-8859-14: cy_GB.ISO8859-14 cy_GB.iso885915: cy_GB.ISO8859-15 cy_GB.ISO-8859-15: cy_GB.ISO8859-15 da: da_DK.ISO8859-1 da.ISO8859-15: da_DK.ISO8859-15 da_DK: da_DK.ISO8859-1 DA_DK: da_DK.ISO8859-1 da_DK.88591: da_DK.ISO8859-1 da_DK.88591.en: da_DK.ISO8859-1 da_DK.iso88591: da_DK.ISO8859-1 da_DK.ISO-8859-1: da_DK.ISO8859-1 da_DK.ISO_8859-1: da_DK.ISO8859-1 da_DK.iso885915: da_DK.ISO8859-15 da_DK.ISO-8859-15: da_DK.ISO8859-15 da_DK.8859-15: da_DK.ISO8859-15 da_DK.utf8: da_DK.UTF-8 DA_DK.UTF-8: da_DK.UTF-8 de: de_DE.ISO8859-1 de.ISO8859-15: de_DE.ISO8859-15 de_AT: de_AT.ISO8859-1 de_AT@euro: de_AT.ISO8859-15 de_AT.iso88591: de_AT.ISO8859-1 de_AT.ISO-8859-1: de_AT.ISO8859-1 de_AT.ISO_8859-1: de_AT.ISO8859-1 de_AT.iso885915: de_AT.ISO8859-15 de_AT.ISO-8859-15: de_AT.ISO8859-15 de_AT.ISO-8859-15@euro: de_AT.ISO8859-15 de_AT.UTF-8@euro: de_AT.UTF-8 de_AT.utf8: de_AT.UTF-8 de_BE: de_BE.ISO8859-1 de_BE@euro: de_BE.ISO8859-15 de_BE.iso88591: de_BE.ISO8859-1 de_BE.ISO_8859-1: de_BE.ISO8859-1 de_BE.ISO-8859-1: de_BE.ISO8859-1 de_BE.iso885915: de_BE.ISO8859-15 de_BE.ISO_8859-15: de_BE.ISO8859-15 de_BE.ISO-8859-15: de_BE.ISO8859-15 de_BE.ISO-8859-15@euro: de_BE.ISO8859-15 de_BE.UTF-8@euro: de_BE.UTF-8 de_CH: de_CH.ISO8859-1 de_CH.iso88591: de_CH.ISO8859-1 de_CH.ISO_8859-1: de_CH.ISO8859-1 de_CH.ISO-8859-1: de_CH.ISO8859-1 de_CH.iso885915: de_CH.ISO8859-15 de_CH.ISO_8859-15: de_CH.ISO8859-15 de_CH.ISO-8859-15: de_CH.ISO8859-15 de_CH.utf8: de_CH.UTF-8 de_DE: de_DE.ISO8859-1 de_DE@euro: de_DE.ISO8859-15 de_DE.88591: de_DE.ISO8859-1 de_DE.88591.en: de_DE.ISO8859-1 de_DE.iso88591: de_DE.ISO8859-1 de_DE.ISO-8859-1: de_DE.ISO8859-1 de_DE.ISO_8859-1: de_DE.ISO8859-1 de_DE.iso885915: de_DE.ISO8859-15 de_DE.ISO-8859-15: de_DE.ISO8859-15 de_DE.ISO_8859-15: de_DE.ISO8859-15 de_DE.8859-15: de_DE.ISO8859-15 de_DE.8859-15@euro: de_DE.ISO8859-15 de_DE.ISO-8859-15@euro: de_DE.ISO8859-15 de_DE.UTF-8@euro: de_DE.UTF-8 de_DE.utf8: de_DE.UTF-8 de_IT: de_IT.UTF-8 de_IT.utf8: de_IT.UTF-8 de_LI: de_LI.ISO8859-1 de_LI.iso88591: de_LI.ISO8859-1 de_LI.ISO_8859-1: de_LI.ISO8859-1 de_LI.ISO-8859-1: de_LI.ISO8859-1 de_LI.iso885915: de_LI.ISO8859-15 de_LI.ISO_8859-15: de_LI.ISO8859-15 de_LI.ISO-8859-15: de_LI.ISO8859-15 de_LI.utf8: de_LI.UTF-8 de_LU: de_LU.ISO8859-1 de_LU@euro: de_LU.ISO8859-15 de_LU.iso88591: de_LU.ISO8859-1 de_LU.ISO_8859-1: de_LU.ISO8859-1 de_LU.ISO-8859-1: de_LU.ISO8859-1 de_LU.iso885915: de_LU.ISO8859-15 de_LU.ISO_8859-15: de_LU.ISO8859-15 de_LU.ISO-8859-15: de_LU.ISO8859-15 de_LU.ISO-8859-15@euro: de_LU.ISO8859-15 de_LU.UTF-8@euro: de_LU.UTF-8 de_LU.utf8: de_LU.UTF-8 GER_DE.8859: de_DE.ISO8859-1 GER_DE.8859.in: de_DE.ISO8859-1 ee: ee_EE.ISO8859-4 ee_EE: ee_EE.ISO8859-4 ee_EE.iso88594: ee_EE.ISO8859-4 el: el_GR.ISO8859-7 el_GR: el_GR.ISO8859-7 el_GR.iso88597: el_GR.ISO8859-7 el_GR.ISO-8859-7: el_GR.ISO8859-7 el_GR@euro: el_GR.ISO8859-15 el_GR.utf8: el_GR.UTF-8 en: en_US.ISO8859-1 en.ISO-8859-1: en_US.ISO8859-1 en_AU: en_AU.ISO8859-1 en_AU.iso88591: en_AU.ISO8859-1 en_AU.ISO-8859-1: en_AU.ISO8859-1 en_AU.ISO_8859-1: en_AU.ISO8859-1 en_AU.utf8: en_AU.UTF-8 en_BE: en_BE.ISO8859-1 en_BE@euro: en_BE.ISO8859-15 en_BE.utf8: en_BE.UTF-8 en_BW: en_BW.ISO8859-1 en_BW.utf8: en_BW.UTF-8 en_BW.iso88591: en_BW.ISO8859-1 en_BW.ISO-8859-1: en_BW.ISO8859-1 en_CA: en_CA.ISO8859-1 en_CA.iso88591: en_CA.ISO8859-1 en_CA.ISO-8859-1: en_CA.ISO8859-1 en_CA.ISO_8859-1: en_CA.ISO8859-1 en_CA.utf8: en_CA.UTF-8 en_DL.utf8: en_DL.UTF-8 en_GB: en_GB.ISO8859-1 en_GB.88591: en_GB.ISO8859-1 en_GB.88591.en: en_GB.ISO8859-1 en_GB.iso88591: en_GB.ISO8859-1 en_GB.ISO-8859-1: en_GB.ISO8859-1 en_GB.ISO_8859-1: en_GB.ISO8859-1 en_GB.iso885915: en_GB.ISO8859-15 en_GB.ISO-8859-15: en_GB.ISO8859-15 en_GB.utf8: en_GB.UTF-8 en_UK: en_GB.ISO8859-1 ENG_GB.8859: en_GB.ISO8859-1 ENG_GB.8859.in: en_GB.ISO8859-1 en_HK: en_HK.ISO8859-1 en_HK.iso88591: en_HK.ISO8859-1 en_HK.ISO-8859-1: en_HK.ISO8859-1 en_HK.utf8: en_HK.UTF-8 en_IE: en_IE.ISO8859-1 en_IE.iso88591: en_IE.ISO8859-1 en_IE.ISO-8859-1: en_IE.ISO8859-1 en_IE.iso885915: en_IE.ISO8859-15 en_IE.ISO-8859-15: en_IE.ISO8859-15 en_IE.ISO-8859-15@euro: en_IE.ISO8859-15 en_IE@euro: en_IE.ISO8859-15 en_IE.UTF-8@euro: en_IE.UTF-8 en_IE.utf8: en_IE.UTF-8 en_IN.utf8: en_IN.UTF-8 en_IN: en_IN.ISO8859-1 en_NZ: en_NZ.ISO8859-1 en_NZ.iso88591: en_NZ.ISO8859-1 en_NZ.ISO-8859-1: en_NZ.ISO8859-1 en_NZ.utf8: en_NZ.UTF-8 en_PH: en_PH.ISO8859-1 en_PH.utf8: en_PH.UTF-8 en_PH.iso88591: en_PH.ISO8859-1 en_PH.ISO-8859-1: en_PH.ISO8859-1 en_SG: en_SG.ISO8859-1 en_SG.utf8: en_SG.UTF-8 en_SG.iso88591: en_SG.ISO8859-1 en_SG.ISO-8859-1: en_SG.ISO8859-1 en_US: en_US.ISO8859-1 EN_US: en_US.ISO8859-1 en_US.88591: en_US.ISO8859-1 en_US.88591.en: en_US.ISO8859-1 en_US.iso88591: en_US.ISO8859-1 en_US.ISO-8859-1: en_US.ISO8859-1 en_US.ISO_8859-1: en_US.ISO8859-1 en_US.iso885915: en_US.ISO8859-15 en_US.ISO-8859-15: en_US.ISO8859-15 en_US.8859-15: en_US.ISO8859-15 en_US.ISO8859-15@euro: en_US.ISO8859-15 en_US.utf8: en_US.UTF-8 EN_US.UTF-8: en_US.UTF-8 en_ZA: en_ZA.ISO8859-1 en_ZA.88591: en_ZA.ISO8859-1 en_ZA.88591.en: en_ZA.ISO8859-1 en_ZA.iso88591: en_ZA.ISO8859-1 en_ZA.ISO-8859-1: en_ZA.ISO8859-1 en_ZA.ISO_8859-1: en_ZA.ISO8859-1 en_ZA.iso885915: en_ZA.ISO8859-15 en_ZA.ISO-8859-15: en_ZA.ISO8859-15 en_ZA.utf8: en_ZA.UTF-8 en_ZW: en_ZW.ISO8859-1 en_ZW.utf8: en_ZS.UTF-8 en_ZW.iso88591: en_ZW.ISO8859-1 en_ZW.ISO-8859-1: en_ZW.ISO8859-1 eo: eo_XX.ISO8859-3 eo_EO: eo_EO.ISO8859-3 eo_XX: eo_XX.ISO8859-3 es: es_ES.ISO8859-1 es.UTF-8: es_ES.UTF-8 es_AR: es_AR.ISO8859-1 es_AR.iso88591: es_AR.ISO8859-1 es_AR.ISO-8859-1: es_AR.ISO8859-1 es_AR.utf8: es_AR.UTF-8 es_BO: es_BO.ISO8859-1 es_BO.iso88591: es_BO.ISO8859-1 es_BO.ISO-8859-1: es_BO.ISO8859-1 es_BO.utf8: es_BO.UTF-8 es_CL: es_CL.ISO8859-1 es_CL.iso88591: es_CL.ISO8859-1 es_CL.ISO-8859-1: es_CL.ISO8859-1 es_CL.utf8: es_CL.UTF-8 es_CO: es_CO.ISO8859-1 es_CO.iso88591: es_CO.ISO8859-1 es_CO.ISO-8859-1: es_CO.ISO8859-1 es_CO.utf8: es_CO.UTF-8 es_CR: es_CR.ISO8859-1 es_CR.iso88591: es_CR.ISO8859-1 es_CR.ISO-8859-1: es_CR.ISO8859-1 es_CR.utf8: es_CR.UTF-8 es_DO: es_DO.ISO8859-1 es_DO.iso88591: es_DO.ISO8859-1 es_DO.ISO-8859-1: es_DO.ISO8859-1 es_DO.utf8: es_DO.UTF-8 es_EC: es_EC.ISO8859-1 es_EC.iso88591: es_EC.ISO8859-1 es_EC.ISO-8859-1: es_EC.ISO8859-1 es_EC.utf8: es_EC.UTF-8 es_ES: es_ES.ISO8859-1 es_ES.88591: es_ES.ISO8859-1 es_ES.88591.en: es_ES.ISO8859-1 es_ES.iso88591: es_ES.ISO8859-1 es_ES.ISO-8859-1: es_ES.ISO8859-1 es_ES.ISO_8859-1: es_ES.ISO8859-1 es_ES.iso885915: es_ES.ISO8859-15 es_ES.ISO-8859-15: es_ES.ISO8859-15 es_ES.ISO-8859-15@euro: es_ES.ISO8859-15 es_ES@euro: es_ES.ISO8859-15 es_ES.UTF-8@euro: es_ES.UTF-8 es_ES.utf8: es_ES.UTF-8 es_GT: es_GT.ISO8859-1 es_GT.iso88591: es_GT.ISO8859-1 es_GT.ISO-8859-1: es_GT.ISO8859-1 es_GT.utf8: es_GT.UTF-8 es_HN: es_HN.ISO8859-1 es_HN.iso88591: es_HN.ISO8859-1 es_HN.ISO-8859-1: es_HN.ISO8859-1 es_HN.utf8: es_HN.UTF-8 es_MX: es_MX.ISO8859-1 es_MX.iso88591: es_MX.ISO8859-1 es_MX.ISO-8859-1: es_MX.ISO8859-1 es_MX.utf8: es_MX.UTF-8 es_NI: es_NI.ISO8859-1 es_NI.iso88591: es_NI.ISO8859-1 es_NI.ISO-8859-1: es_NI.ISO8859-1 es_NI.utf8: es_NI.UTF-8 es_PA: es_PA.ISO8859-1 es_PA.iso88591: es_PA.ISO8859-1 es_PA.ISO-8859-1: es_PA.ISO8859-1 es_PA.iso885915: es_PA.ISO8859-15 es_PA.utf8: es_PA.UTF-8 es_PE: es_PE.ISO8859-1 es_PE.iso88591: es_PE.ISO8859-1 es_PE.ISO-8859-1: es_PE.ISO8859-1 es_PE.iso885915: es_PE.ISO8859-15 es_PE.utf8: es_PE.UTF-8 es_PR: es_PR.ISO8859-1 es_PR.iso88591: es_PR.ISO8859-1 es_PR.ISO-8859-1: es_PR.ISO8859-1 es_PR.utf8: es_PR.UTF-8 es_PY: es_PY.ISO8859-1 es_PY.iso88591: es_PY.ISO8859-1 es_PY.ISO-8859-1: es_PY.ISO8859-1 es_PY.iso885915: es_PY.ISO8859-15 es_PY.utf8: es_PY.UTF-8 es_SV: es_SV.ISO8859-1 es_SV.iso88591: es_SV.ISO8859-1 es_SV.ISO-8859-1: es_SV.ISO8859-1 es_SV.iso885915: es_SV.ISO8859-15 es_SV.utf8: es_SV.UTF-8 es_US: es_US.ISO8859-1 es_US.iso88591: es_US.ISO8859-1 es_US.ISO-8859-1: es_US.ISO8859-1 es_UY: es_UY.ISO8859-1 es_UY.iso88591: es_UY.ISO8859-1 es_UY.ISO-8859-1: es_UY.ISO8859-1 es_UY.iso885915: es_UY.ISO8859-15 es_UY.utf8: es_UY.UTF-8 es_VE: es_VE.ISO8859-1 es_VE.iso88591: es_VE.ISO8859-1 es_VE.ISO-8859-1: es_VE.ISO8859-1 es_VE.iso885915: es_VE.ISO8859-15 es_VE.utf8: es_VE.UTF-8 # According to Estonian local standards, ISO8859-4 is not a recommended # charset. EVS8:2000 specifies ISO8859-15 as the base charset. et: et_EE.ISO8859-15 et_EE: et_EE.ISO8859-15 et_EE.iso88591: et_EE.ISO8859-1 et_EE.ISO-8859-1: et_EE.ISO8859-1 et_EE.iso88594: et_EE.ISO8859-4 et_EE.ISO-8859-4: et_EE.ISO8859-4 et_EE.iso885913: et_EE.ISO8859-13 et_EE.ISO-8859-13: et_EE.ISO8859-13 et_EE.iso885915: et_EE.ISO8859-15 et_EE.ISO-8859-15: et_EE.ISO8859-15 et_EE.utf8: et_EE.UTF-8 eu: eu_ES.ISO8859-1 eu_ES: eu_ES.ISO8859-1 eu_ES.iso88591: eu_ES.ISO8859-1 eu_ES.ISO-8859-1: eu_ES.ISO8859-1 eu_ES.iso885915: eu_ES.ISO8859-15 eu_ES.ISO-8859-15: eu_ES.ISO8859-15 eu_ES.ISO-8859-15@euro: eu_ES.ISO8859-15 eu_ES@euro: eu_ES.ISO8859-15 eu_ES.UTF-8@euro: eu_ES.UTF-8 fa: fa_IR.UTF-8 fa_IR: fa_IR.UTF-8 fa_IR.isiri3342: fa_IR.ISIRI-3342 fa_IR.utf8: fa_IR.UTF-8 fi: fi_FI.ISO8859-15 fi.ISO8859-15: fi_FI.ISO8859-15 fi_FI: fi_FI.ISO8859-15 fi_FI.88591: fi_FI.ISO8859-1 fi_FI.88591.en: fi_FI.ISO8859-1 fi_FI.iso88591: fi_FI.ISO8859-1 fi_FI.ISO-8859-1: fi_FI.ISO8859-1 fi_FI.ISO_8859-1: fi_FI.ISO8859-1 fi_FI.iso885915: fi_FI.ISO8859-15 fi_FI.ISO-8859-15: fi_FI.ISO8859-15 fi_FI.ISO-8859-15@euro: fi_FI.ISO8859-15 fi_FI@euro: fi_FI.ISO8859-15 fi_FI.utf8: fi_FI.UTF-8 fi_FI.UTF-8@euro: fi_FI.UTF-8 fo: fo_FO.ISO8859-1 fo_FO: fo_FO.ISO8859-1 fo_FO.iso88591: fo_FO.ISO8859-1 fo_FO.ISO-8859-1: fo_FO.ISO8859-1 fo_FO.iso885915: fo_FO.ISO8859-15 fo_FO.ISO-8859-15: fo_FO.ISO8859-15 fo_FO.utf8: fo_FO.UTF-8 fr: fr_FR.ISO8859-1 fr.ISO8859-15: fr_FR.ISO8859-15 fr.UTF-8: fr_FR.UTF-8 fr_BE: fr_BE.ISO8859-1 fr_BE.88591: fr_BE.ISO8859-1 fr_BE.88591.en: fr_BE.ISO8859-1 fr_BE.ISO-8859-1: fr_BE.ISO8859-1 fr_BE.ISO_8859-1: fr_BE.ISO8859-1 fr_BE.iso885915: fr_BE.ISO8859-15 fr_BE.ISO-8859-15: fr_BE.ISO8859-15 fr_BE.ISO-8859-15@euro: fr_BE.ISO8859-15 fr_BE@euro: fr_BE.ISO8859-15 fr_BE.utf8: fr_BE.UTF-8 fr_BE.UTF-8@euro: fr_BE.UTF-8 fr_CA: fr_CA.ISO8859-1 fr_CA.88591: fr_CA.ISO8859-1 fr_CA.88591.en: fr_CA.ISO8859-1 fr_CA.iso88591: fr_CA.ISO8859-1 fr_CA.ISO-8859-1: fr_CA.ISO8859-1 fr_CA.ISO_8859-1: fr_CA.ISO8859-1 fr_CA.iso885915: fr_CA.ISO8859-15 fr_CA.ISO-8859-15: fr_CA.ISO8859-15 fr_CA.utf8: fr_CA.UTF-8 fr_CH: fr_CH.ISO8859-1 fr_CH.88591: fr_CH.ISO8859-1 fr_CH.88591.en: fr_CH.ISO8859-1 fr_CH.ISO-8859-1: fr_CH.ISO8859-1 fr_CH.ISO_8859-1: fr_CH.ISO8859-1 fr_CH.iso885915: fr_CH.ISO8859-15 fr_CH.ISO-8859-15: fr_CH.ISO8859-15 fr_CH.utf8: fr_CH.UTF-8 fr_FR: fr_FR.ISO8859-1 fr_FR.88591: fr_FR.ISO8859-1 fr_FR.88591.en: fr_FR.ISO8859-1 fr_FR.iso88591: fr_FR.ISO8859-1 fr_FR.ISO-8859-1: fr_FR.ISO8859-1 fr_FR.ISO_8859-1: fr_FR.ISO8859-1 fr_FR.iso885915: fr_FR.ISO8859-15 fr_FR.ISO-8859-15: fr_FR.ISO8859-15 fr_FR.ISO-8859-15@euro: fr_FR.ISO8859-15 fr_FR@euro: fr_FR.ISO8859-15 fr_FR.UTF-8@euro: fr_FR.UTF-8 fr_FR.utf8: fr_FR.UTF-8 fr_LU: fr_LU.ISO8859-1 fr_LU.88591: fr_LU.ISO8859-1 fr_LU.88591.en: fr_LU.ISO8859-1 fr_LU.iso88591: fr_LU.ISO8859-1 fr_LU.ISO-8859-1: fr_LU.ISO8859-1 fr_LU.ISO_8859-1: fr_LU.ISO8859-1 fr_LU.iso885915: fr_LU.ISO8859-15 fr_LU.ISO-8859-15: fr_LU.ISO8859-15 fr_LU.ISO-8859-15@euro: fr_LU.ISO8859-15 fr_LU@euro: fr_LU.ISO8859-15 fr_LU.UTF-8@euro: fr_LU.UTF-8 fr_LU.utf8: fr_LU.UTF-8 FRE_FR.8859: fr_FR.ISO8859-1 FRE_FR.8859.in: fr_FR.ISO8859-1 ga: ga_IE.ISO8859-1 ga_IE: ga_IE.ISO8859-1 ga_IE.iso88591: ga_IE.ISO8859-1 ga_IE.ISO-8859-1: ga_IE.ISO8859-1 ga_IE.iso885914: ga_IE.ISO8859-14 ga_IE.ISO-8859-14: ga_IE.ISO8859-14 ga_IE.iso885915: ga_IE.ISO8859-15 ga_IE.ISO-8859-15: ga_IE.ISO8859-15 ga_IE.ISO-8859-15@euro: ga_IE.ISO8859-15 ga_IE@euro: ga_IE.ISO8859-15 ga_IE.UTF-8@euro: ga_IE.UTF-8 ga_IE.utf8: ga_IE.UTF-8 gd: gd_GB.ISO8859-1 gd_GB: gd_GB.ISO8859-1 gd_GB.iso88591: gd_GB.ISO8859-1 gd_GB.ISO-8859-1: gd_GB.ISO8859-1 gd_GB.iso885914: gd_GB.ISO8859-14 gd_GB.ISO-8859-14: gd_GB.ISO8859-14 gd_GB.iso885915: gd_GB.ISO8859-15 gd_GB.ISO-8859-15: gd_GB.ISO8859-15 gl: gl_ES.ISO8859-1 gl_ES: gl_ES.ISO8859-1 gl_ES.iso88591: gl_ES.ISO8859-1 gl_ES.ISO-8859-1: gl_ES.ISO8859-1 gl_ES.iso885915: gl_ES.ISO8859-15 gl_ES.ISO-8859-15: gl_ES.ISO8859-15 gl_ES.ISO-8859-15@euro: gl_ES.ISO8859-15 gl_ES@euro: gl_ES.ISO8859-15 gl_ES.UTF-8@euro: gl_ES.UTF-8 gl_ES.utf8: gl_ES.UTF-8 gu_IN: gu_IN.UTF-8 gu_IN.utf8: gu_IN.UTF-8 gv: gv_GB.ISO8859-1 gv_GB: gv_GB.ISO8859-1 gv_GB.iso88591: gv_GB.ISO8859-1 gv_GB.ISO-8859-1: gv_GB.ISO8859-1 gv_GB.iso885914: gv_GB.ISO8859-14 gv_GB.ISO-8859-14: gv_GB.ISO8859-14 gv_GB.iso885915: gv_GB.ISO8859-15 gv_GB.ISO-8859-15: gv_GB.ISO8859-15 he: he_IL.ISO8859-8 he_IL: he_IL.ISO8859-8 HE_IL: he_IL.ISO8859-8 he_IL.iso88598: he_IL.ISO8859-8 he_IL.ISO-8859-8: he_IL.ISO8859-8 he_IL.cp1255: he_IL.CP1255 he_IL.microsoftcp1255: he_IL.CP1255 he_IL.microsoft-cp1255: he_IL.CP1255 he_IL.MICROSOFT-CP1255: he_IL.CP1255 he_IL.utf8: he_IL.UTF-8 HE_IL.UTF-8: he_IL.UTF-8 hi: hi_IN.ISCII-DEV hi_IN: hi_IN.ISCII-DEV HI_IN: hi_IN.ISCII-DEV hi_IN.isciidev: hi_IN.ISCII-DEV hi_IN.utf8: hi_IN.UTF-8 HI_IN.UTF-8: hi_IN.UTF-8 hne: hne_IN.UTF-8 hne_IN: hne_IN.UTF-8 hne_IN.utf8: hne_IN.UTF-8 hr: hr_HR.ISO8859-2 hr_HR: hr_HR.ISO8859-2 hr_HR.iso88592: hr_HR.ISO8859-2 hr_HR.ISO-8859-2: hr_HR.ISO8859-2 hr_HR.ISO_8859-2: hr_HR.ISO8859-2 hr_HR.utf8: hr_HR.UTF-8 hu: hu_HU.ISO8859-2 hu_HU: hu_HU.ISO8859-2 hu_HU.iso88592: hu_HU.ISO8859-2 hu_HU.ISO-8859-2: hu_HU.ISO8859-2 hu_HU.utf8: hu_HU.UTF-8 ia: ia.UTF-8 ia.utf8: ia.UTF-8 ie: ie.UTF-8 ie.utf8: ie.UTF-8 is: is_IS.ISO8859-1 is_IS: is_IS.ISO8859-1 is_IS.iso88591: is_IS.ISO8859-1 is_IS.ISO-8859-1: is_IS.ISO8859-1 is_IS.ISO_8859-1: is_IS.ISO8859-1 is_IS.iso885915: is_IS.ISO8859-15 is_IS.ISO-8859-15: is_IS.ISO8859-15 is_IS.utf8: is_IS.UTF-8 it: it_IT.ISO8859-1 it.ISO8859-15: it_IT.ISO8859-15 it.UTF-8: it_IT.UTF-8 it_CH: it_CH.ISO8859-1 it_CH.iso88591: it_CH.ISO8859-1 it_CH.ISO_8859-1: it_CH.ISO8859-1 it_CH.ISO-8859-1: it_CH.ISO8859-1 it_CH.iso885915: it_CH.ISO8859-15 it_CH.utf8: it_CH.UTF-8 it_IT: it_IT.ISO8859-1 it_IT.88591: it_IT.ISO8859-1 it_IT.88591.en: it_IT.ISO8859-1 it_IT.iso88591: it_IT.ISO8859-1 it_IT.ISO-8859-1: it_IT.ISO8859-1 it_IT.ISO_8859-1: it_IT.ISO8859-1 it_IT.iso885915: it_IT.ISO8859-15 it_IT.ISO-8859-15: it_IT.ISO8859-15 it_IT.ISO-8859-15@euro: it_IT.ISO8859-15 it_IT@euro: it_IT.ISO8859-15 it_IT.utf8: it_IT.UTF-8 it_IT.UTF-8@euro: it_IT.UTF-8 # NUNACOM is an encoding for the Inuktitut syllabics # we have little else on this encoding. iu: iu_CA.NUNACOM-8 iu_CA: iu_CA.NUNACOM-8 iu_CA.nunacom8: iu_CA.NUNACOM-8 ja_JP: ja_JP.eucJP ja: ja_JP.eucJP ja.JIS: ja_JP.JIS7 ja.SJIS: ja_JP.SJIS ja_JP.ujis: ja_JP.eucJP Jp_JP: ja_JP.eucJP ja_JP.AJEC: ja_JP.eucJP ja_JP.EUC: ja_JP.eucJP ja_JP.EUC-JP: ja_JP.eucJP ja_JP.EUC_JP: ja_JP.eucJP ja_JP.eucjp: ja_JP.eucJP ja_JP.ISO-2022-JP: ja_JP.JIS7 ja_JP.JIS: ja_JP.JIS7 ja_JP.jis7: ja_JP.JIS7 ja_JP.mscode: ja_JP.SJIS ja_JP.PCK: ja_JP.SJIS ja_JP.sjis: ja_JP.SJIS ja_JP.utf8: ja_JP.UTF-8 JA_JP.utf8: ja_JP.UTF-8 ka: ka_GE.GEORGIAN-ACADEMY ka_GE: ka_GE.GEORGIAN-ACADEMY ka_GE.georgianacademy: ka_GE.GEORGIAN-ACADEMY ka_GE.georgianrs: ka_GE.GEORGIAN-ACADEMY ka_GE.georgianps: ka_GE.GEORGIAN-PS kl: kl_GL.ISO8859-1 kl_GL: kl_GL.ISO8859-1 kl_GL.iso88591: kl_GL.ISO8859-1 kl_GL.ISO-8859-1: kl_GL.ISO8859-1 kl_GL.iso885915: kl_GL.ISO8859-15 kl_GL.utf8: kl_GL.UTF-8 km_KH: km_KH.UTF-8 km_KH.utf8: km_KH.UTF-8 kn: kn_IN.UTF-8 kn_IN: kn_IN.UTF-8 kn_IN.utf8: kn_IN.UTF-8 ko: ko_KR.eucKR ko.UTF-8: ko_KR.UTF-8 ko_KR: ko_KR.eucKR KO_KR: ko_KR.eucKR ko_KR.EUC: ko_KR.eucKR ko_KR.EUC-KR: ko_KR.eucKR ko_KR.euc: ko_KR.eucKR ko_KR.euckr: ko_KR.eucKR ko_KR.utf8: ko_KR.UTF-8 KO_KR.UTF-8: ko_KR.UTF-8 ks: ks_IN.UTF-8 ks_IN: ks_IN.UTF-8 ks_IN.utf8: ks_IN.UTF-8 ks_IN@devanagari: ks_IN.UTF-8@devanagari ks_IN.utf8@devanagari: ks_IN.UTF-8@devanagari kw: kw_GB.ISO8859-1 kw_GB: kw_GB.ISO8859-1 kw_GB.iso88591: kw_GB.ISO8859-1 kw_GB.ISO-8859-1: kw_GB.ISO8859-1 kw_GB.iso885914: kw_GB.ISO8859-14 kw_GB.ISO-8859-14: kw_GB.ISO8859-14 kw_GB.iso885915: kw_GB.ISO8859-15 kw_GB.ISO-8859-15: kw_GB.ISO8859-15 ky: ky_KG.UTF-8 ky_KG: ky_KG.UTF-8 ky_KG.utf8: ky_KG.UTF-8 lo: lo_LA.MULELAO-1 lo_LA: lo_LA.MULELAO-1 lo_LA.cp1133: lo_LA.IBM-CP1133 lo_LA.ibmcp1133: lo_LA.IBM-CP1133 lo_LA.mulelao1: lo_LA.MULELAO-1 lt: lt_LT.ISO8859-13 lt_LT: lt_LT.ISO8859-13 lt_LT.iso88594: lt_LT.ISO8859-4 lt_LT.ISO-8859-4: lt_LT.ISO8859-4 lt_LT.ISO_8859-4: lt_LT.ISO8859-4 lt_LT.iso885913: lt_LT.ISO8859-13 lt_LT.ISO-8859-13: lt_LT.ISO8859-13 lt_LT.ISO_8859-13: lt_LT.ISO8859-13 lt_LT.utf8: lt_LT.UTF-8 lv: lv_LV.ISO8859-13 lv_LV: lv_LV.ISO8859-13 lv_LV.iso88594: lv_LV.ISO8859-4 lv_LV.ISO-8859-4: lv_LV.ISO8859-4 lv_LV.iso885913: lv_LV.ISO8859-13 lv_LV.ISO-8859-13: lv_LV.ISO8859-13 lv_LV.ISO_8859-13: lv_LV.ISO8859-13 lv_LV.utf8: lv_LV.UTF-8 mai: mai_IN.UTF-8 mai_IN: mai_IN.UTF-8 mai_IN.utf8: mai_IN.UTF-8 mi: mi_NZ.ISO8859-1 mi_NZ: mi_NZ.ISO8859-1 mi_NZ.iso88591: mi_NZ.ISO8859-1 mk: mk_MK.ISO8859-5 mk_MK: mk_MK.ISO8859-5 mk_MK.iso88595: mk_MK.ISO8859-5 mk_MK.ISO-8859-5: mk_MK.ISO8859-5 mk_MK.cp1251: mk_MK.CP1251 mk_MK.microsoftcp1251: mk_MK.CP1251 mk_MK.microsoft-cp1251: mk_MK.CP1251 mk_MK.MICROSOFT-CP1251: mk_MK.CP1251 mk_MK.utf8: mk_MK.UTF-8 ml: ml_IN.UTF-8 ml_IN: ml_IN.UTF-8 ml_IN.utf8: ml_IN.UTF-8 mr: mr_IN.UTF-8 mr_IN: mr_IN.UTF-8 mr_IN.utf8: mr_IN.UTF-8 ms: ms_MY.ISO8859-1 ms_MY: ms_MY.ISO8859-1 ms_MY.iso88591: ms_MY.ISO8859-1 ms_MY.ISO-8859-1: ms_MY.ISO8859-1 mt: mt_MT.ISO8859-3 mt_MT: mt_MT.ISO8859-3 mt_MT.ISO-8859-3: mt_MT.ISO8859-3 nb: nb_NO.ISO8859-1 nb_NO: nb_NO.ISO8859-1 nb_NO.88591: nb_NO.ISO8859-1 nb_NO.iso88591: nb_NO.ISO8859-1 nb_NO.ISO-8859-1: nb_NO.ISO8859-1 nb_NO.iso885915: nb_NO.ISO8859-15 nb_NO.ISO-8859-15: nb_NO.ISO8859-15 nb_NO.utf8: nb_NO.UTF-8 ne_NP: ne_NP.UTF-8 ne_NP.utf8: ne_NP.UTF-8 nl: nl_NL.ISO8859-1 nl.ISO8859-15: nl_NL.ISO8859-15 nl_BE: nl_BE.ISO8859-1 nl_BE.88591: nl_BE.ISO8859-1 nl_BE.88591.en: nl_BE.ISO8859-1 nl_BE.iso88591: nl_BE.ISO8859-1 nl_BE.ISO-8859-1: nl_BE.ISO8859-1 nl_BE.ISO_8859-1: nl_BE.ISO8859-1 nl_BE.iso885915: nl_BE.ISO8859-15 nl_BE.ISO-8859-15: nl_BE.ISO8859-15 nl_BE.ISO-8859-15@euro: nl_BE.ISO8859-15 nl_BE@euro: nl_BE.ISO8859-15 nl_BE.utf8: nl_BE.UTF-8 nl_BE.UTF-8@euro: nl_BE.UTF-8 nl_NL: nl_NL.ISO8859-1 nl_NL.88591: nl_NL.ISO8859-1 nl_NL.88591.en: nl_NL.ISO8859-1 nl_NL.iso88591: nl_NL.ISO8859-1 nl_NL.ISO-8859-1: nl_NL.ISO8859-1 nl_NL.ISO_8859-1: nl_NL.ISO8859-1 nl_NL.iso885915: nl_NL.ISO8859-15 nl_NL.ISO-8859-15: nl_NL.ISO8859-15 nl_NL.ISO-8859-15@euro: nl_NL.ISO8859-15 nl_NL@euro: nl_NL.ISO8859-15 nl_NL.utf8: nl_NL.UTF-8 nl_NL.UTF-8@euro: nl_NL.UTF-8 nn: nn_NO.ISO8859-1 nn_NO: nn_NO.ISO8859-1 nn_NO.88591: nn_NO.ISO8859-1 nn_NO.ISO-8859-1: nn_NO.ISO8859-1 nn_NO.ISO_8859-1: nn_NO.ISO8859-1 nn_NO.iso885915: nn_NO.ISO8859-15 nn_NO.ISO-8859-15: nn_NO.ISO8859-15 nn_NO.utf8: nn_NO.UTF-8 no: no_NO.ISO8859-1 no_NO: no_NO.ISO8859-1 no_NO.88591: no_NO.ISO8859-1 no_NO.88591.en: no_NO.ISO8859-1 no_NO.iso88591: no_NO.ISO8859-1 no_NO.ISO-8859-1: no_NO.ISO8859-1 no_NO.ISO8859-1@bokmal: no_NO.ISO8859-1 no_NO.ISO8859-1@nynorsk: no_NO.ISO8859-1 no_NO.iso885915: no_NO.ISO8859-15 no_NO.ISO-8859-15: no_NO.ISO8859-15 no_NO.utf8: no_NO.UTF-8 nr: nr_ZA.ISO8859-1 nr_ZA: nr_ZA.ISO8859-1 nr_ZA.iso88591: nr_ZA.ISO8859-1 nr_ZA.utf8: nr_ZA.UTF-8 nso: nso_ZA.ISO8859-15 nso_ZA: nso_ZA.ISO8859-15 nso_ZA.iso885915: nso_ZA.ISO8859-15 nso_ZA.utf8: nso_ZA.UTF-8 ny: ny_NO.ISO8859-1 ny_NO: ny_NO.ISO8859-1 ny_NO.88591: ny_NO.ISO8859-1 ny_NO.ISO_8859-1: ny_NO.ISO8859-1 ny_NO.iso885915: ny_NO.ISO8859-15 no@nynorsk: ny_NO.ISO8859-1 nynorsk: nn_NO.ISO8859-1 oc: oc_FR.ISO8859-1 oc_FR: oc_FR.ISO8859-1 oc_FR.iso88591: oc_FR.ISO8859-1 oc_FR.ISO-8859-1: oc_FR.ISO8859-1 oc_FR.iso885915: oc_FR.ISO8859-15 oc_FR.ISO-8859-15: oc_FR.ISO8859-15 oc_FR@euro: oc_FR.ISO8859-15 or: or_IN.UTF-8 or_IN: or_IN.UTF-8 or_IN.utf8: or_IN.UTF-8 pa: pa_IN.UTF-8 pa_IN: pa_IN.UTF-8 pa_IN.utf8: pa_IN.UTF-8 pa_PK.utf8: pa_PK.UTF-8 pd: pd_US.ISO8859-1 pd_DE: pd_DE.ISO8859-1 pd_US: pd_US.ISO8859-1 pd_DE.iso88591: pd_DE.ISO8859-1 pd_US.iso88591: pd_US.ISO8859-1 pd_DE.iso885915: pd_DE.ISO8859-15 pd_US.iso885915: pd_US.ISO8859-15 ph: ph_PH.ISO8859-1 ph_PH: ph_PH.ISO8859-1 ph_PH.iso88591: ph_PH.ISO8859-1 pl: pl_PL.ISO8859-2 pl.UTF-8: pl_PL.UTF-8 pl_PL: pl_PL.ISO8859-2 pl_PL.iso88592: pl_PL.ISO8859-2 pl_PL.ISO-8859-2: pl_PL.ISO8859-2 pl_PL.utf8: pl_PL.UTF-8 pp: pp_AN.ISO8859-1 pp_AN: pp_AN.ISO8859-1 pp_AN.iso88591: pp_AN.ISO8859-1 pt: pt_PT.ISO8859-1 pt.ISO8859-15: pt_PT.ISO8859-15 pt_BR: pt_BR.ISO8859-1 pt_BR.88591: pt_BR.ISO8859-1 pt_BR.88591.en: pt_BR.ISO8859-1 pt_BR.iso88591: pt_BR.ISO8859-1 pt_BR.ISO-8859-1: pt_BR.ISO8859-1 pt_BR.ISO_8859-1: pt_BR.ISO8859-1 pt_BR.iso885915: pt_BR.ISO8859-15 pt_BR.utf8: pt_BR.UTF-8 pt_PT: pt_PT.ISO8859-1 pt_PT.88591: pt_PT.ISO8859-1 pt_PT.88591.en: pt_PT.ISO8859-1 pt_PT.iso88591: pt_PT.ISO8859-1 pt_PT.ISO-8859-1: pt_PT.ISO8859-1 pt_PT.ISO_8859-1: pt_PT.ISO8859-1 pt_PT.iso885915: pt_PT.ISO8859-15 pt_PT.ISO-8859-15: pt_PT.ISO8859-15 pt_PT.ISO-8859-15@euro: pt_PT.ISO8859-15 pt_PT@euro: pt_PT.ISO8859-15 pt_PT.utf8: pt_PT.UTF-8 pt_PT.UTF-8@euro: pt_PT.UTF-8 ro: ro_RO.ISO8859-2 ro_RO: ro_RO.ISO8859-2 ro_RO.iso88592: ro_RO.ISO8859-2 ro_RO.ISO-8859-2: ro_RO.ISO8859-2 ro_RO.utf8: ro_RO.UTF-8 ru: ru_RU.UTF-8 ru.koi8-r: ru_RU.KOI8-R ru.UTF-8: ru_RU.UTF-8 ru_RU: ru_RU.UTF-8 ru_RU.utf8: ru_RU.UTF-8 ru_RU.iso88595: ru_RU.ISO8859-5 ru_RU.ISO-8859-5: ru_RU.ISO8859-5 ru_RU.koi8r: ru_RU.KOI8-R ru_RU.cp1251: ru_RU.CP1251 ru_RU.microsoftcp1251: ru_RU.CP1251 ru_RU.microsoft-cp1251: ru_RU.CP1251 ru_RU.MICROSOFT-CP1251: ru_RU.CP1251 ru_UA: ru_UA.KOI8-U ru_UA.koi8u: ru_UA.KOI8-U ru_UA.cp1251: ru_UA.CP1251 ru_UA.microsoftcp1251: ru_UA.CP1251 ru_UA.microsoft-cp1251: ru_UA.CP1251 ru_UA.MICROSOFT-CP1251: ru_UA.CP1251 rw: rw_RW.ISO8859-1 rw_RW: rw_RW.ISO8859-1 rw_RW.iso8859-1: rw_RW.ISO8859-1 rw_RW.ISO-8859-1: rw_RW.ISO8859-1 rw_RW.utf8: rw_RW.UTF-8 sd: sd_IN.UTF-8 sd_IN.utf8: sd_IN.UTF-8 sd@devanagari: sd_IN.UTF-8@devanagari sd_IN@devanagari: sd_IN.UTF-8@devanagari sd_IN.utf8@devanagari: sd_IN.UTF-8@devanagari se_NO: se_NO.UTF-8 se_NO.utf8: se_NO.UTF-8 si: si_LK.UTF-8 si_LK: si_LK.UTF-8 sk: sk_SK.ISO8859-2 sk_SK: sk_SK.ISO8859-2 sk_SK.iso88592: sk_SK.ISO8859-2 sk_SK.ISO-8859-2: sk_SK.ISO8859-2 sk_SK.utf8: sk_SK.UTF-8 sl: sl_SI.ISO8859-2 sl_SI: sl_SI.ISO8859-2 sl_SI.iso88592: sl_SI.ISO8859-2 sl_SI.ISO-8859-2: sl_SI.ISO8859-2 sl_SI.utf8: sl_SI.UTF-8 sq: sq_AL.ISO8859-2 sq_AL: sq_AL.ISO8859-2 sq_AL.iso88592: sq_AL.ISO8859-2 sq_AL.ISO-8859-2: sq_AL.ISO8859-2 sq_AL.utf8: sq_AL.UTF-8 sr: sr_RS.UTF-8 sr@cyrillic: sr_RS.UTF-8 sr@latin: sr_RS.UTF-8@latin sr@Latn: sr_RS.UTF-8@latin sr_RS: sr_RS.UTF-8 sr_RS@latin: sr_RS.UTF-8@latin sr_RS@Latn: sr_RS.UTF-8@latin sr_RS.UTF-8@Latn: sr_RS.UTF-8@latin sr_RS.utf8: sr_RS.UTF-8 sr_ME: sr_ME.UTF-8 sr_ME.utf8: sr_ME.UTF-8 ss: ss_ZA.ISO8859-1 ss_ZA: ss_ZA.ISO8859-1 ss_ZA.iso88591: ss_ZA.ISO8859-1 ss_ZA.utf8: ss_ZA.UTF-8 st: st_ZA.ISO8859-1 st_ZA: st_ZA.ISO8859-1 st_ZA.iso88591: st_ZA.ISO8859-1 st_ZA.utf8: st_ZA.UTF-8 sv: sv_SE.ISO8859-1 sv.ISO8859-15: sv_SE.ISO8859-15 sv.UTF-8: sv_SE.UTF-8 sv_FI: sv_FI.ISO8859-1 sv_FI.iso88591: sv_FI.ISO8859-1 sv_FI.ISO-8859-1: sv_FI.ISO8859-1 sv_FI.iso885915: sv_FI.ISO8859-15 sv_FI.ISO-8859-15: sv_FI.ISO8859-15 sv_FI.ISO-8859-15@euro: sv_FI.ISO8859-15 sv_FI@euro: sv_FI.ISO8859-15 sv_FI.UTF-8@euro: sv_FI.UTF-8 sv_FI.utf8: sv_FI.UTF-8 sv_SE: sv_SE.ISO8859-1 sv_SE.88591: sv_SE.ISO8859-1 sv_SE.88591.en: sv_SE.ISO8859-1 sv_SE.iso88591: sv_SE.ISO8859-1 sv_SE.ISO-8859-1: sv_SE.ISO8859-1 sv_SE.ISO_8859-1: sv_SE.ISO8859-1 sv_SE.iso885915: sv_SE.ISO8859-15 sv_SE.ISO-8859-15: sv_SE.ISO8859-15 sv_SE@euro: sv_SE.ISO8859-15 sv_SE.utf8: sv_SE.UTF-8 ta: ta_IN.TSCII-0 ta_IN: ta_IN.TSCII-0 ta_IN.tscii: ta_IN.TSCII-0 ta_IN.tscii0: ta_IN.TSCII-0 te: te_IN.UTF-8 te.UTF-8: te_IN.UTF-8 te_IN.utf8: te_IN.UTF-8 tg: tg_TJ.KOI8-C tg_TJ: tg_TJ.KOI8-C tg_TJ.koi8c: tg_TJ.KOI8-C th: th_TH.ISO8859-11 th_TH: th_TH.ISO8859-11 th_TH.ISO-8859-11: th_TH.ISO8859-11 th_TH.tis620: th_TH.TIS620 th_TH.TIS-620: th_TH.TIS620 th_TH.TACTIS: th_TH.TIS620 th_TH.utf8: th_TH.UTF-8 tl: tl_PH.ISO8859-1 tl_PH: tl_PH.ISO8859-1 tl_PH.iso88591: tl_PH.ISO8859-1 tl_PH.ISO-8859-1: tl_PH.ISO8859-1 tn: tn_ZA.ISO8859-15 tn_ZA: tn_ZA.ISO8859-15 tn_ZA.iso8859-15: tn_ZA.ISO8859-15 tn_ZA.utf8: tn_ZA.UTF-8 tr: tr_TR.ISO8859-9 tr_TR: tr_TR.ISO8859-9 TR_TR: tr_TR.ISO8859-9 tr_TR.iso88599: tr_TR.ISO8859-9 tr_TR.ISO-8859-9: tr_TR.ISO8859-9 tr_TR.utf8: tr_TR.UTF-8 TR_TR.utf8: tr_TR.UTF-8 ts: ts_ZA.ISO8859-1 ts_ZA: ts_ZA.ISO8859-1 ts_ZA.iso88591: ts_ZA.ISO8859-1 ts_ZA.utf8: ts_ZA.UTF-8 tt: tt_RU.TATAR-CYR tt_RU: tt_RU.TATAR-CYR tt_RU.tatarcyr: tt_RU.TATAR-CYR tt_RU.koi8c: tt_RU.KOI8-C uk: uk_UA.KOI8-U uk_UA: uk_UA.KOI8-U uk_UA.iso88595: uk_UA.ISO8859-5 uk_UA.koi8u: uk_UA.KOI8-U uk_UA.cp1251: uk_UA.CP1251 uk_UA.microsoftcp1251: uk_UA.CP1251 uk_UA.microsoft-cp1251: uk_UA.CP1251 uk_UA.MICROSOFT-CP1251: uk_UA.CP1251 uk_UA.utf8: uk_UA.UTF-8 ur: ur_IN.UTF-8 ur_IN: ur_IN.UTF-8 ur_IN.utf8: ur_IN.UTF-8 ur: ur_PK.CP1256 ur_PK: ur_PK.CP1256 ur_PK.cp1256: ur_PK.CP1256 ur_PK.microsoftcp1256: ur_PK.CP1256 ur_PK.microsoft-cp1256: ur_PK.CP1256 ur_PK.MICROSOFT-CP1256: ur_PK.CP1256 uz: uz_UZ.UTF-8 uz_UZ: uz_UZ.UTF-8 uz_UZ.ISO-8859-1: uz_UZ.ISO8859-1 uz_UZ@cyrillic: uz_UZ.UTF-8 uz_UZ.UTF-8@cyrillic: uz_UZ.UTF-8 ve: ve_ZA.UTF-8 ve_ZA: ve_ZA.UTF-8 ve_ZA.utf8: ve_ZA.UTF-8 vi: vi_VN.TCVN vi_VN: vi_VN.TCVN Vi_VN: vi_VN.TCVN VI_VN: vi_VN.TCVN vi_VN.tcvn: vi_VN.TCVN vi_VN.tcvn5712: vi_VN.TCVN vi_VN.viscii: vi_VN.VISCII vi_VN.viscii111: vi_VN.VISCII vi_VN.utf8: vi_VN.UTF-8 VI_VN.UTF-8: vi_VN.UTF-8 wa: wa_BE.ISO8859-1 wa_BE: wa_BE.ISO8859-1 wa_BE.iso88591: wa_BE.ISO8859-1 wa_BE.ISO-8859-1: wa_BE.ISO8859-1 wa_BE.iso885915: wa_BE.ISO8859-15 wa_BE.ISO-8859-15: wa_BE.ISO8859-15 wa_BE.ISO-8859-15@euro: wa_BE.ISO8859-15 wa_BE@euro: wa_BE.ISO8859-15 xh: xh_ZA.ISO8859-1 xh_ZA: xh_ZA.ISO8859-1 xh_ZA.iso88591: xh_ZA.ISO8859-1 xh_ZA.utf8: xh_ZA.UTF-8 yi: yi_US.CP1255 yi_US: yi_US.CP1255 yi_US.cp1255: yi_US.CP1255 yi_US.microsoftcp1255: yi_US.CP1255 yi_US.microsoft-cp1255: yi_US.CP1255 yi_US.MICROSOFT-CP1255: yi_US.CP1255 zh_CN: zh_CN.gb2312 zh_CN.Big5: zh_TW.big5 zh_CN.EUC: zh_CN.eucCN zh_CN.GB2312: zh_CN.gb2312 zh_CN.GBK: zh_CN.gbk zh_CN.GB18030: zh_CN.gb18030 zh_CN.big5: zh_TW.big5 zh_CN.euc: zh_CN.eucCN zh_CN.utf8: zh_CN.UTF-8 ZH_CN.UTF-8: zh_CN.UTF-8 zh_HK: zh_HK.big5hkscs zh_HK.BIG5HK: zh_HK.big5hkscs zh_HK.Big5hkscs: zh_HK.big5hkscs zh_HK.Big5-hkscs: zh_HK.big5hkscs zh_HK.Big5_hkscs: zh_HK.big5hkscs zh_HK.Big5HKSCS: zh_HK.big5hkscs zh_HK.BIG5-HKSCS: zh_HK.big5hkscs zh_HK.BIG5_HKSCS: zh_HK.big5hkscs zh_HK.Big5-HKSCS: zh_HK.big5hkscs zh_HK.big5-hkscs: zh_HK.big5hkscs zh_HK.Big5-HKSCS: zh_HK.big5hkscs zh_HK.Big5HKSCS: zh_HK.big5hkscs zh_HK.Big5: zh_HK.big5 zh_HK.utf8: zh_HK.UTF-8 ZH_HK.UTF-8: zh_HK.UTF-8 ZH_SG.UTF-8: zh_SG.UTF-8 zh_TW: zh_TW.big5 zh_TW.Big5: zh_TW.big5 zh_TW.BIG5: zh_TW.big5 Zh_TW.big5: zh_TW.big5 zh_TW.EUC: zh_TW.eucTW zh_TW.EUC-TW: zh_TW.eucTW zh_TW.utf8: zh_TW.UTF-8 ZH_TW.UTF-8: zh_TW.UTF-8 zu: zu_ZA.ISO8859-1 zu_ZA: zu_ZA.ISO8859-1 zu_ZA.iso88591: zu_ZA.ISO8859-1 zu_ZA.utf8: zu_ZA.UTF-8 # The following locale names are used in SCO 3.0 english_uk.8859: en_GB.ISO8859-1 english_us.8859: en_US.ISO8859-1 english_us.ascii: en_US.ISO8859-1 french_france.8859: fr_FR.ISO8859-1 german_germany.8859: de_DE.ISO8859-1 portuguese_brazil.8859: pt_BR.ISO8859-1 spanish_spain.8859: es_ES.ISO8859-1 # The following locale names are used in HPUX 9.x american.iso88591: en_US.ISO8859-1 arabic.iso88596: ar_AA.ISO8859-6 bokmal: nb_NO.ISO8859-1 bokml: nb_NO.ISO8859-1 bulgarian: bg_BG.CP1251 c-french.iso88591: fr_CA.ISO8859-1 catalan: ca_ES.ISO8859-1 chinese-s: zh_CN.eucCN chinese-t: zh_TW.eucTW croatian: hr_HR.ISO8859-2 czech: cs_CZ.ISO8859-2 danish: da_DK.ISO8859-1 dansk: da_DK.ISO8859-1 danish.iso88591: da_DK.ISO8859-1 deutsch: de_DE.ISO8859-1 dutch: nl_NL.ISO8859-1 dutch.iso88591: nl_BE.ISO8859-1 eesti: et_EE.ISO8859-1 english.iso88591: en_EN.ISO8859-1 estonian: et_EE.ISO8859-1 finnish: fi_FI.ISO8859-1 finnish.iso88591: fi_FI.ISO8859-1 franais: fr_FR.ISO8859-1 french: fr_FR.ISO8859-1 french.iso88591: fr_CH.ISO8859-1 galego: gl_ES.ISO8859-1 galician: gl_ES.ISO8859-1 german: de_DE.ISO8859-1 german.iso88591: de_CH.ISO8859-1 greek: el_GR.ISO8859-7 greek.iso88597: el_GR.ISO8859-7 hebrew: he_IL.ISO8859-8 hebrew.iso88598: he_IL.ISO8859-8 hrvatski: hr_HR.ISO8859-2 hungarian: hu_HU.ISO8859-2 icelandic.iso88591: is_IS.ISO8859-1 icelandic: is_IS.ISO8859-1 italian: it_IT.ISO8859-1 italian.iso88591: it_IT.ISO8859-1 japanese: ja_JP.eucJP japanese.euc: ja_JP.eucJP japanese.sjis: ja_JP.SJIS korean: ko_KR.eucKR korean.euc: ko_KR.eucKR lithuanian: lt_LT.ISO8859-13 norwegian: no_NO.ISO8859-1 norwegian.iso88591: no_NO.ISO8859-1 polish: pl_PL.ISO8859-2 portuguese: pt_PT.ISO8859-1 portuguese.iso88591: pt_PT.ISO8859-1 romanian: ro_RO.ISO8859-2 rumanian: ro_RO.ISO8859-2 russian: ru_RU.ISO8859-5 serbocroatian: sr_RS.UTF-8@latin sinhala: si_LK.UTF-8 slovak: sk_SK.ISO8859-2 slovene: sl_SI.ISO8859-2 slovenian: sl_SI.ISO8859-2 spanish: es_ES.ISO8859-1 spanish.iso88591: es_ES.ISO8859-1 swedish: sv_SE.ISO8859-1 swedish.iso88591: sv_SE.ISO8859-1 turkish: tr_TR.ISO8859-9 turkish.iso88599: tr_TR.ISO8859-9 thai: th_TH.ISO8859-11 univ.utf8: en_US.UTF-8 # Digital Unix utf universal.utf8@ucs4: en_US.UTF-8 # Solaris and SunOS have iso_8859_1 and iso_8859_15 LC_CTYPES # to augment LANG=C iso_8859_1: en_US.ISO8859-1 iso_8859_15: en_US.ISO8859-15 # Other miscellaneous locale names ISO8859-1: en_US.ISO8859-1 ISO-8859-1: en_US.ISO8859-1 japan: ja_JP.eucJP Japanese-EUC: ja_JP.eucJP xkbcommon-libxkbcommon-54ee7ac/test/data/locale/locale.dir000066400000000000000000001102171510033435100237530ustar00rootroot00000000000000# # This file contains locale database file names # The first word is the locale database file name and # the second word is the full locale name. # # C/XLC_LOCALE C iso8859-1/XLC_LOCALE af_ZA.ISO8859-1 iso8859-6/XLC_LOCALE ar_AA.ISO8859-6 iso8859-6/XLC_LOCALE ar_BH.ISO8859-6 iso8859-6/XLC_LOCALE ar_DZ.ISO8859-6 iso8859-6/XLC_LOCALE ar_EG.ISO8859-6 iso8859-6/XLC_LOCALE ar_IQ.ISO8859-6 iso8859-6/XLC_LOCALE ar_JO.ISO8859-6 iso8859-6/XLC_LOCALE ar_KW.ISO8859-6 iso8859-6/XLC_LOCALE ar_LB.ISO8859-6 iso8859-6/XLC_LOCALE ar_LY.ISO8859-6 iso8859-6/XLC_LOCALE ar_MA.ISO8859-6 iso8859-6/XLC_LOCALE ar_OM.ISO8859-6 iso8859-6/XLC_LOCALE ar_QA.ISO8859-6 iso8859-6/XLC_LOCALE ar_SA.ISO8859-6 iso8859-6/XLC_LOCALE ar_SD.ISO8859-6 iso8859-6/XLC_LOCALE ar_SY.ISO8859-6 iso8859-6/XLC_LOCALE ar_TN.ISO8859-6 iso8859-6/XLC_LOCALE ar_YE.ISO8859-6 iso8859-6/XLC_LOCALE ar_AE.ISO8859-6 iso8859-9e/XLC_LOCALE az_AZ.ISO8859-9E koi8-c/XLC_LOCALE az_AZ.KOI8-C iso8859-5/XLC_LOCALE be_BY.ISO8859-5 microsoft-cp1251/XLC_LOCALE be_BY.CP1251 iso8859-5/XLC_LOCALE bg_BG.ISO8859-5 microsoft-cp1251/XLC_LOCALE bg_BG.CP1251 koi8-r/XLC_LOCALE bg_BG.KOI8-R iso8859-2/XLC_LOCALE bs_BA.ISO8859-2 iso8859-1/XLC_LOCALE br_FR.ISO8859-1 iso8859-14/XLC_LOCALE br_FR.ISO8859-14 iso8859-15/XLC_LOCALE br_FR.ISO8859-15 iso8859-1/XLC_LOCALE ca_AD.ISO8859-1 iso8859-15/XLC_LOCALE ca_AD.ISO8859-15 iso8859-1/XLC_LOCALE ca_ES.ISO8859-1 iso8859-15/XLC_LOCALE ca_ES.ISO8859-15 iso8859-1/XLC_LOCALE ca_FR.ISO8859-1 iso8859-15/XLC_LOCALE ca_FR.ISO8859-15 iso8859-1/XLC_LOCALE ca_IT.ISO8859-1 iso8859-15/XLC_LOCALE ca_IT.ISO8859-15 iso8859-2/XLC_LOCALE cs_CZ.ISO8859-2 iso8859-1/XLC_LOCALE cy_GB.ISO8859-1 iso8859-14/XLC_LOCALE cy_GB.ISO8859-14 iso8859-15/XLC_LOCALE cy_GB.ISO8859-15 iso8859-1/XLC_LOCALE da_DK.ISO8859-1 iso8859-15/XLC_LOCALE da_DK.ISO8859-15 iso8859-1/XLC_LOCALE de_AT.ISO8859-1 iso8859-15/XLC_LOCALE de_AT.ISO8859-15 iso8859-1/XLC_LOCALE de_BE.ISO8859-1 iso8859-15/XLC_LOCALE de_BE.ISO8859-15 iso8859-1/XLC_LOCALE de_CH.ISO8859-1 iso8859-15/XLC_LOCALE de_CH.ISO8859-15 iso8859-1/XLC_LOCALE de_DE.ISO8859-1 iso8859-15/XLC_LOCALE de_DE.ISO8859-15 iso8859-1/XLC_LOCALE de_LI.ISO8859-1 iso8859-15/XLC_LOCALE de_LI.ISO8859-15 iso8859-1/XLC_LOCALE de_LU.ISO8859-1 iso8859-15/XLC_LOCALE de_LU.ISO8859-15 iso8859-7/XLC_LOCALE el_GR.ISO8859-7 iso8859-4/XLC_LOCALE ee_EE.ISO8859-4 iso8859-15/XLC_LOCALE el_GR.ISO8859-15 iso8859-1/XLC_LOCALE en_AU.ISO8859-1 iso8859-1/XLC_LOCALE en_BE.ISO8859-1 iso8859-15/XLC_LOCALE en_BE.ISO8859-15 iso8859-1/XLC_LOCALE en_BZ.ISO8859-1 iso8859-1/XLC_LOCALE en_BW.ISO8859-1 iso8859-1/XLC_LOCALE en_CA.ISO8859-1 iso8859-1/XLC_LOCALE en_EN.ISO8859-1 iso8859-1/XLC_LOCALE en_GB.ISO8859-1 iso8859-15/XLC_LOCALE en_GB.ISO8859-15 iso8859-1/XLC_LOCALE en_HK.ISO8859-1 iso8859-1/XLC_LOCALE en_IE.ISO8859-1 iso8859-15/XLC_LOCALE en_IE.ISO8859-15 iso8859-15/XLC_LOCALE en_IN.ISO8859-15 iso8859-1/XLC_LOCALE en_JM.ISO8859-1 iso8859-1/XLC_LOCALE en_NZ.ISO8859-1 iso8859-1/XLC_LOCALE en_PH.ISO8859-1 iso8859-1/XLC_LOCALE en_SG.ISO8859-1 iso8859-1/XLC_LOCALE en_TT.ISO8859-1 iso8859-1/XLC_LOCALE en_UK.ISO8859-1 iso8859-15/XLC_LOCALE en_UK.ISO8859-15 iso8859-1/XLC_LOCALE en_US.ISO8859-1 iso8859-15/XLC_LOCALE en_US.ISO8859-15 iso8859-1/XLC_LOCALE en_ZA.ISO8859-1 iso8859-15/XLC_LOCALE en_ZA.ISO8859-15 iso8859-1/XLC_LOCALE en_ZW.ISO8859-1 iso8859-3/XLC_LOCALE eo_EO.ISO8859-3 iso8859-3/XLC_LOCALE eo_XX.ISO8859-3 iso8859-1/XLC_LOCALE es_AR.ISO8859-1 iso8859-1/XLC_LOCALE es_BO.ISO8859-1 iso8859-1/XLC_LOCALE es_CL.ISO8859-1 iso8859-1/XLC_LOCALE es_CO.ISO8859-1 iso8859-1/XLC_LOCALE es_CR.ISO8859-1 iso8859-1/XLC_LOCALE es_DO.ISO8859-1 iso8859-1/XLC_LOCALE es_EC.ISO8859-1 iso8859-1/XLC_LOCALE es_ES.ISO8859-1 iso8859-15/XLC_LOCALE es_ES.ISO8859-15 iso8859-1/XLC_LOCALE es_GT.ISO8859-1 iso8859-1/XLC_LOCALE es_HN.ISO8859-1 iso8859-1/XLC_LOCALE es_MX.ISO8859-1 iso8859-1/XLC_LOCALE es_NI.ISO8859-1 iso8859-1/XLC_LOCALE es_PA.ISO8859-1 iso8859-15/XLC_LOCALE es_PA.ISO8859-15 iso8859-1/XLC_LOCALE es_PE.ISO8859-1 iso8859-15/XLC_LOCALE es_PE.ISO8859-15 iso8859-1/XLC_LOCALE es_PR.ISO8859-1 iso8859-1/XLC_LOCALE es_PY.ISO8859-1 iso8859-15/XLC_LOCALE es_PY.ISO8859-15 iso8859-1/XLC_LOCALE es_SV.ISO8859-1 iso8859-15/XLC_LOCALE es_SV.ISO8859-15 iso8859-1/XLC_LOCALE es_US.ISO8859-1 iso8859-1/XLC_LOCALE es_UY.ISO8859-1 iso8859-15/XLC_LOCALE es_UY.ISO8859-15 iso8859-1/XLC_LOCALE es_VE.ISO8859-1 iso8859-15/XLC_LOCALE es_VE.ISO8859-15 iso8859-1/XLC_LOCALE et_EE.ISO8859-1 iso8859-4/XLC_LOCALE et_EE.ISO8859-4 iso8859-13/XLC_LOCALE et_EE.ISO8859-13 iso8859-15/XLC_LOCALE et_EE.ISO8859-15 iso8859-1/XLC_LOCALE eu_ES.ISO8859-1 iso8859-15/XLC_LOCALE eu_ES.ISO8859-15 isiri-3342/XLC_LOCALE fa_IR.ISIRI-3342 iso8859-1/XLC_LOCALE fi_FI.ISO8859-1 iso8859-15/XLC_LOCALE fi_FI.ISO8859-15 iso8859-1/XLC_LOCALE fo_FO.ISO8859-1 iso8859-15/XLC_LOCALE fo_FO.ISO8859-15 iso8859-1/XLC_LOCALE fr_BE.ISO8859-1 iso8859-15/XLC_LOCALE fr_BE.ISO8859-15 iso8859-1/XLC_LOCALE fr_CA.ISO8859-1 iso8859-15/XLC_LOCALE fr_CA.ISO8859-15 iso8859-1/XLC_LOCALE fr_CH.ISO8859-1 iso8859-15/XLC_LOCALE fr_CH.ISO8859-15 iso8859-1/XLC_LOCALE fr_FR.ISO8859-1 iso8859-15/XLC_LOCALE fr_FR.ISO8859-15 iso8859-1/XLC_LOCALE fr_LU.ISO8859-1 iso8859-15/XLC_LOCALE fr_LU.ISO8859-15 iso8859-1/XLC_LOCALE ga_IE.ISO8859-1 iso8859-14/XLC_LOCALE ga_IE.ISO8859-14 iso8859-15/XLC_LOCALE ga_IE.ISO8859-15 iso8859-1/XLC_LOCALE gd_GB.ISO8859-1 iso8859-14/XLC_LOCALE gd_GB.ISO8859-14 iso8859-15/XLC_LOCALE gd_GB.ISO8859-15 iso8859-1/XLC_LOCALE gl_ES.ISO8859-1 iso8859-15/XLC_LOCALE gl_ES.ISO8859-15 iso8859-1/XLC_LOCALE gv_GB.ISO8859-1 iso8859-14/XLC_LOCALE gv_GB.ISO8859-14 iso8859-15/XLC_LOCALE gv_GB.ISO8859-15 iso8859-8/XLC_LOCALE he_IL.ISO8859-8 microsoft-cp1255/XLC_LOCALE he_IL.CP1255 iscii-dev/XLC_LOCALE hi_IN.ISCII-DEV iso8859-2/XLC_LOCALE hr_HR.ISO8859-2 iso8859-2/XLC_LOCALE hu_HU.ISO8859-2 armscii-8/XLC_LOCALE hy_AM.ARMSCII-8 iso8859-1/XLC_LOCALE id_ID.ISO8859-1 iso8859-1/XLC_LOCALE id_ID.ISO8859-15 iso8859-1/XLC_LOCALE is_IS.ISO8859-1 iso8859-15/XLC_LOCALE is_IS.ISO8859-15 iso8859-1/XLC_LOCALE it_CH.ISO8859-1 iso8859-15/XLC_LOCALE it_CH.ISO8859-15 iso8859-1/XLC_LOCALE it_IT.ISO8859-1 iso8859-15/XLC_LOCALE it_IT.ISO8859-15 ja/XLC_LOCALE ja_JP.eucJP ja.SJIS/XLC_LOCALE ja_JP.SJIS ja.JIS/XLC_LOCALE ja_JP.JIS7 georgian-academy/XLC_LOCALE ka_GE.GEORGIAN-ACADEMY georgian-ps/XLC_LOCALE ka_GE.GEORGIAN-PS iso8859-1/XLC_LOCALE kl_GL.ISO8859-1 iso8859-15/XLC_LOCALE kl_GL.ISO8859-15 ko/XLC_LOCALE ko_KR.eucKR iso8859-1/XLC_LOCALE kw_GB.ISO8859-1 iso8859-14/XLC_LOCALE kw_GB.ISO8859-14 iso8859-15/XLC_LOCALE kw_GB.ISO8859-15 ibm-cp1133/XLC_LOCALE lo_LA.IBM-CP1133 mulelao-1/XLC_LOCALE lo_LA.MULELAO-1 iso8859-4/XLC_LOCALE lt_LT.ISO8859-4 iso8859-13/XLC_LOCALE lt_LT.ISO8859-13 iso8859-4/XLC_LOCALE lv_LV.ISO8859-4 iso8859-13/XLC_LOCALE lv_LV.ISO8859-13 iso8859-13/XLC_LOCALE mi_NZ.ISO8859-13 iso8859-5/XLC_LOCALE mk_MK.ISO8859-5 microsoft-cp1251/XLC_LOCALE mk_MK.CP1251 iso8859-1/XLC_LOCALE ms_MY.ISO8859-1 iso8859-3/XLC_LOCALE mt_MT.ISO8859-3 iso8859-1/XLC_LOCALE nb_NO.ISO8859-1 iso8859-1/XLC_LOCALE nb_NO.ISO8859-15 iso8859-1/XLC_LOCALE nl_BE.ISO8859-1 iso8859-15/XLC_LOCALE nl_BE.ISO8859-15 iso8859-1/XLC_LOCALE nl_NL.ISO8859-1 iso8859-15/XLC_LOCALE nl_NL.ISO8859-15 iso8859-1/XLC_LOCALE nn_NO.ISO8859-1 iso8859-1/XLC_LOCALE nn_NO.ISO8859-15 iso8859-1/XLC_LOCALE no_NO.ISO8859-1 iso8859-1/XLC_LOCALE no_NO.ISO8859-15 iso8859-1/XLC_LOCALE nr_ZA.ISO8859-1 iso8859-15/XLC_LOCALE nso_ZA.ISO8859-15 iso8859-1/XLC_LOCALE ny_NO.ISO8859-1 iso8859-1/XLC_LOCALE ny_NO.ISO8859-15 iso8859-1/XLC_LOCALE oc_FR.ISO8859-1 iso8859-15/XLC_LOCALE oc_FR.ISO8859-15 iso8859-1/XLC_LOCALE pd_DE.ISO8859-1 iso8859-15/XLC_LOCALE pd_DE.ISO8859-15 iso8859-1/XLC_LOCALE pd_US.ISO8859-1 iso8859-15/XLC_LOCALE pd_US.ISO8859-15 iso8859-1/XLC_LOCALE ph_PH.ISO8859-1 iso8859-2/XLC_LOCALE pl_PL.ISO8859-2 iso8859-1/XLC_LOCALE pp_AN.ISO8859-1 iso8859-1/XLC_LOCALE pt_BR.ISO8859-1 iso8859-15/XLC_LOCALE pt_BR.ISO8859-15 iso8859-1/XLC_LOCALE pt_PT.ISO8859-1 iso8859-15/XLC_LOCALE pt_PT.ISO8859-15 iso8859-2/XLC_LOCALE ro_RO.ISO8859-2 iso8859-5/XLC_LOCALE ru_RU.ISO8859-5 microsoft-cp1251/XLC_LOCALE ru_RU.CP1251 koi8-r/XLC_LOCALE ru_RU.KOI8-R microsoft-cp1251/XLC_LOCALE ru_UA.CP1251 koi8-u/XLC_LOCALE ru_UA.KOI8-U iso8859-1/XLC_LOCALE rw_RW.ISO8859-1 iso8859-2/XLC_LOCALE sh_YU.ISO8859-2 iso8859-2/XLC_LOCALE sk_SK.ISO8859-2 iso8859-2/XLC_LOCALE sl_SI.ISO8859-2 iso8859-2/XLC_LOCALE sq_AL.ISO8859-2 iso8859-2/XLC_LOCALE sr_YU.ISO8859-2 iso8859-5/XLC_LOCALE sr_YU.ISO8859-5 microsoft-cp1251/XLC_LOCALE sr_YU.CP1251 iso8859-1/XLC_LOCALE ss_ZA.ISO8859-1 iso8859-1/XLC_LOCALE st_ZA.ISO8859-1 iso8859-1/XLC_LOCALE sv_FI.ISO8859-1 iso8859-15/XLC_LOCALE sv_FI.ISO8859-15 iso8859-1/XLC_LOCALE sv_SE.ISO8859-1 iso8859-15/XLC_LOCALE sv_SE.ISO8859-15 tscii-0/XLC_LOCALE ta_IN.TSCII-0 koi8-c/XLC_LOCALE tg_TJ.KOI8-C th_TH/XLC_LOCALE th_TH.TIS620 iso8859-11/XLC_LOCALE th_TH.ISO8859-11 iso8859-1/XLC_LOCALE tl_PH.ISO8859-1 iso8859-15/XLC_LOCALE tn_ZA.ISO8859-15 iso8859-9/XLC_LOCALE tr_TR.ISO8859-9 iso8859-1/XLC_LOCALE ts_ZA.ISO8859-1 tatar-cyr/XLC_LOCALE tt_RU.TATAR-CYR koi8-c/XLC_LOCALE tt_RU.KOI8-C iso8859-5/XLC_LOCALE uk_UA.ISO8859-5 microsoft-cp1251/XLC_LOCALE uk_UA.CP1251 koi8-u/XLC_LOCALE uk_UA.KOI8-U microsoft-cp1256/XLC_LOCALE ur_PK.CP1256 iso8859-1/XLC_LOCALE uz_UZ.ISO8859-1 vi_VN.tcvn/XLC_LOCALE vi_VN.TCVN vi_VN.viscii/XLC_LOCALE vi_VN.VISCII iso8859-1/XLC_LOCALE wa_BE.ISO8859-1 iso8859-15/XLC_LOCALE wa_BE.ISO8859-15 iso8859-1/XLC_LOCALE xh_ZA.ISO8859-1 microsoft-cp1255/XLC_LOCALE yi_US.CP1255 zh_CN/XLC_LOCALE zh_CN.eucCN zh_CN/XLC_LOCALE zh_CN.gb2312 zh_CN.gbk/XLC_LOCALE zh_CN.gbk zh_CN.gb18030/XLC_LOCALE zh_CN.gb18030 zh_HK.big5/XLC_LOCALE zh_HK.big5 zh_HK.big5hkscs/XLC_LOCALE zh_HK.big5hkscs zh_TW.big5/XLC_LOCALE zh_TW.big5 zh_TW/XLC_LOCALE zh_TW.eucTW iso8859-1/XLC_LOCALE zu_ZA.ISO8859-1 # Note: The UTF-8 locales don't work correctly yet. Work in progress. en_US.UTF-8/XLC_LOCALE af_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE am_ET.UTF-8 en_US.UTF-8/XLC_LOCALE ar_AA.UTF-8 en_US.UTF-8/XLC_LOCALE ar_AE.UTF-8 en_US.UTF-8/XLC_LOCALE ar_BH.UTF-8 en_US.UTF-8/XLC_LOCALE ar_DZ.UTF-8 en_US.UTF-8/XLC_LOCALE ar_EG.UTF-8 en_US.UTF-8/XLC_LOCALE ar_IN.UTF-8 en_US.UTF-8/XLC_LOCALE ar_IQ.UTF-8 en_US.UTF-8/XLC_LOCALE ar_JO.UTF-8 en_US.UTF-8/XLC_LOCALE ar_KW.UTF-8 en_US.UTF-8/XLC_LOCALE ar_LB.UTF-8 en_US.UTF-8/XLC_LOCALE ar_LY.UTF-8 en_US.UTF-8/XLC_LOCALE ar_MA.UTF-8 en_US.UTF-8/XLC_LOCALE ar_OM.UTF-8 en_US.UTF-8/XLC_LOCALE bs_BA.UTF-8 en_US.UTF-8/XLC_LOCALE ar_QA.UTF-8 en_US.UTF-8/XLC_LOCALE ar_SA.UTF-8 en_US.UTF-8/XLC_LOCALE ar_SD.UTF-8 en_US.UTF-8/XLC_LOCALE ar_SY.UTF-8 en_US.UTF-8/XLC_LOCALE ar_TN.UTF-8 en_US.UTF-8/XLC_LOCALE ar_YE.UTF-8 en_US.UTF-8/XLC_LOCALE as_IN.UTF-8 en_US.UTF-8/XLC_LOCALE ast_ES.UTF-8 en_US.UTF-8/XLC_LOCALE az_AZ.UTF-8 en_US.UTF-8/XLC_LOCALE be_BY.UTF-8 en_US.UTF-8/XLC_LOCALE be_BY.UTF-8@latin en_US.UTF-8/XLC_LOCALE bg_BG.UTF-8 en_US.UTF-8/XLC_LOCALE bn_BD.UTF-8 en_US.UTF-8/XLC_LOCALE bn_IN.UTF-8 en_US.UTF-8/XLC_LOCALE bo_IN.UTF-8 en_US.UTF-8/XLC_LOCALE br_FR.UTF-8 en_US.UTF-8/XLC_LOCALE ca_AD.UTF-8 en_US.UTF-8/XLC_LOCALE ca_ES.UTF-8 en_US.UTF-8/XLC_LOCALE ca_FR.UTF-8 en_US.UTF-8/XLC_LOCALE ca_IT.UTF-8 en_US.UTF-8/XLC_LOCALE cs_CZ.UTF-8 en_US.UTF-8/XLC_LOCALE cy_GB.UTF-8 en_US.UTF-8/XLC_LOCALE da_DK.UTF-8 en_US.UTF-8/XLC_LOCALE de_AT.UTF-8 en_US.UTF-8/XLC_LOCALE de_BE.UTF-8 en_US.UTF-8/XLC_LOCALE de_CH.UTF-8 en_US.UTF-8/XLC_LOCALE de_DE.UTF-8 en_US.UTF-8/XLC_LOCALE de_IT.UTF-8 en_US.UTF-8/XLC_LOCALE de_LI.UTF-8 en_US.UTF-8/XLC_LOCALE de_LU.UTF-8 en_US.UTF-8/XLC_LOCALE el_CY.UTF-8 en_US.UTF-8/XLC_LOCALE el_GR.UTF-8 en_US.UTF-8/XLC_LOCALE en_AU.UTF-8 en_US.UTF-8/XLC_LOCALE en_BE.UTF-8 en_US.UTF-8/XLC_LOCALE en_BW.UTF-8 en_US.UTF-8/XLC_LOCALE en_BZ.UTF-8 en_US.UTF-8/XLC_LOCALE en_CA.UTF-8 en_US.UTF-8/XLC_LOCALE en_DK.UTF-8 en_US.UTF-8/XLC_LOCALE en_GB.UTF-8 en_US.UTF-8/XLC_LOCALE en_EN.UTF-8 en_US.UTF-8/XLC_LOCALE en_HK.UTF-8 en_US.UTF-8/XLC_LOCALE en_IE.UTF-8 en_US.UTF-8/XLC_LOCALE en_IN.UTF-8 en_US.UTF-8/XLC_LOCALE en_JM.UTF-8 en_US.UTF-8/XLC_LOCALE en_MT.UTF-8 en_US.UTF-8/XLC_LOCALE en_NZ.UTF-8 en_US.UTF-8/XLC_LOCALE en_PH.UTF-8 en_US.UTF-8/XLC_LOCALE en_SG.UTF-8 en_US.UTF-8/XLC_LOCALE en_TT.UTF-8 en_US.UTF-8/XLC_LOCALE en_UK.UTF-8 en_US.UTF-8/XLC_LOCALE en_US.UTF-8 en_US.UTF-8/XLC_LOCALE en_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE en_ZW.UTF-8 en_US.UTF-8/XLC_LOCALE eo_EO.UTF-8 en_US.UTF-8/XLC_LOCALE eo_XX.UTF-8 en_US.UTF-8/XLC_LOCALE es_AR.UTF-8 en_US.UTF-8/XLC_LOCALE es_BO.UTF-8 en_US.UTF-8/XLC_LOCALE es_CL.UTF-8 en_US.UTF-8/XLC_LOCALE es_CO.UTF-8 en_US.UTF-8/XLC_LOCALE es_CR.UTF-8 en_US.UTF-8/XLC_LOCALE es_DO.UTF-8 en_US.UTF-8/XLC_LOCALE es_EC.UTF-8 en_US.UTF-8/XLC_LOCALE es_ES.UTF-8 en_US.UTF-8/XLC_LOCALE es_GT.UTF-8 en_US.UTF-8/XLC_LOCALE es_HN.UTF-8 en_US.UTF-8/XLC_LOCALE es_MX.UTF-8 en_US.UTF-8/XLC_LOCALE es_NI.UTF-8 en_US.UTF-8/XLC_LOCALE es_PA.UTF-8 en_US.UTF-8/XLC_LOCALE es_PE.UTF-8 en_US.UTF-8/XLC_LOCALE es_PR.UTF-8 en_US.UTF-8/XLC_LOCALE es_PY.UTF-8 en_US.UTF-8/XLC_LOCALE es_SV.UTF-8 en_US.UTF-8/XLC_LOCALE es_US.UTF-8 en_US.UTF-8/XLC_LOCALE es_UY.UTF-8 en_US.UTF-8/XLC_LOCALE es_VE.UTF-8 en_US.UTF-8/XLC_LOCALE et_EE.UTF-8 en_US.UTF-8/XLC_LOCALE eu_ES.UTF-8 en_US.UTF-8/XLC_LOCALE fa_IR.UTF-8 en_US.UTF-8/XLC_LOCALE fi_FI.UTF-8 en_US.UTF-8/XLC_LOCALE fo_FO.UTF-8 en_US.UTF-8/XLC_LOCALE fr_BE.UTF-8 en_US.UTF-8/XLC_LOCALE fr_CA.UTF-8 en_US.UTF-8/XLC_LOCALE fr_CH.UTF-8 en_US.UTF-8/XLC_LOCALE fr_FR.UTF-8 en_US.UTF-8/XLC_LOCALE fr_LU.UTF-8 en_US.UTF-8/XLC_LOCALE ga_IE.UTF-8 en_US.UTF-8/XLC_LOCALE gd_GB.UTF-8 en_US.UTF-8/XLC_LOCALE gl_ES.UTF-8 en_US.UTF-8/XLC_LOCALE gu_IN.UTF-8 en_US.UTF-8/XLC_LOCALE gv_GB.UTF-8 en_US.UTF-8/XLC_LOCALE he_IL.UTF-8 en_US.UTF-8/XLC_LOCALE hi_IN.UTF-8 en_US.UTF-8/XLC_LOCALE hne_IN.UTF-8 en_US.UTF-8/XLC_LOCALE hr_HR.UTF-8 en_US.UTF-8/XLC_LOCALE hu_HU.UTF-8 en_US.UTF-8/XLC_LOCALE hy_AM.UTF-8 en_US.UTF-8/XLC_LOCALE ia.UTF-8 en_US.UTF-8/XLC_LOCALE id_ID.UTF-8 en_US.UTF-8/XLC_LOCALE ie.UTF-8 en_US.UTF-8/XLC_LOCALE is_IS.UTF-8 en_US.UTF-8/XLC_LOCALE it_CH.UTF-8 en_US.UTF-8/XLC_LOCALE it_IT.UTF-8 en_US.UTF-8/XLC_LOCALE iu_CA.UTF-8 ja_JP.UTF-8/XLC_LOCALE ja_JP.UTF-8 en_US.UTF-8/XLC_LOCALE ka_GE.UTF-8 en_US.UTF-8/XLC_LOCALE kk_KZ.UTF-8 en_US.UTF-8/XLC_LOCALE kl_GL.UTF-8 en_US.UTF-8/XLC_LOCALE km_KH.UTF-8 en_US.UTF-8/XLC_LOCALE kn_IN.UTF-8 en_US.UTF-8/XLC_LOCALE ks_IN.UTF-8 en_US.UTF-8/XLC_LOCALE ks_IN.UTF-8@devanagari ko_KR.UTF-8/XLC_LOCALE ko_KR.UTF-8 en_US.UTF-8/XLC_LOCALE ku_TR.UTF-8 en_US.UTF-8/XLC_LOCALE kw_GB.UTF-8 en_US.UTF-8/XLC_LOCALE ky_KG.UTF-8 en_US.UTF-8/XLC_LOCALE lo_LA.UTF-8 en_US.UTF-8/XLC_LOCALE lt_LT.UTF-8 en_US.UTF-8/XLC_LOCALE lv_LV.UTF-8 en_US.UTF-8/XLC_LOCALE mai_IN.UTF-8 en_US.UTF-8/XLC_LOCALE mi_NZ.UTF-8 en_US.UTF-8/XLC_LOCALE mk_MK.UTF-8 en_US.UTF-8/XLC_LOCALE ml_IN.UTF-8 en_US.UTF-8/XLC_LOCALE mr_IN.UTF-8 en_US.UTF-8/XLC_LOCALE ms_MY.UTF-8 en_US.UTF-8/XLC_LOCALE mt_MT.UTF-8 en_US.UTF-8/XLC_LOCALE nl_BE.UTF-8 en_US.UTF-8/XLC_LOCALE nl_NL.UTF-8 en_US.UTF-8/XLC_LOCALE nb_NO.UTF-8 en_US.UTF-8/XLC_LOCALE nn_NO.UTF-8 en_US.UTF-8/XLC_LOCALE no_NO.UTF-8 en_US.UTF-8/XLC_LOCALE nr_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE nso_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE ny_NO.UTF-8 en_US.UTF-8/XLC_LOCALE oc_FR.UTF-8 en_US.UTF-8/XLC_LOCALE or_IN.UTF-8 en_US.UTF-8/XLC_LOCALE pa_IN.UTF-8 en_US.UTF-8/XLC_LOCALE pa_PK.UTF-8 en_US.UTF-8/XLC_LOCALE pd_DE.UTF-8 en_US.UTF-8/XLC_LOCALE pd_US.UTF-8 en_US.UTF-8/XLC_LOCALE ph_PH.UTF-8 en_US.UTF-8/XLC_LOCALE pl_PL.UTF-8 en_US.UTF-8/XLC_LOCALE pp_AN.UTF-8 pt_BR.UTF-8/XLC_LOCALE pt_BR.UTF-8 pt_PT.UTF-8/XLC_LOCALE pt_PT.UTF-8 en_US.UTF-8/XLC_LOCALE ro_RO.UTF-8 ru_RU.UTF-8/XLC_LOCALE ru_RU.UTF-8 en_US.UTF-8/XLC_LOCALE ru_UA.UTF-8 en_US.UTF-8/XLC_LOCALE rw_RW.UTF-8 en_US.UTF-8/XLC_LOCALE sa_IN.UTF-8 en_US.UTF-8/XLC_LOCALE sd_IN.UTF-8 en_US.UTF-8/XLC_LOCALE sd_IN.UTF-8@devanagari en_US.UTF-8/XLC_LOCALE se_NO.UTF-8 en_US.UTF-8/XLC_LOCALE sh_BA.UTF-8 en_US.UTF-8/XLC_LOCALE sh_YU.UTF-8 en_US.UTF-8/XLC_LOCALE si_LK.UTF-8 en_US.UTF-8/XLC_LOCALE sk_SK.UTF-8 en_US.UTF-8/XLC_LOCALE sl_SI.UTF-8 en_US.UTF-8/XLC_LOCALE sq_AL.UTF-8 en_US.UTF-8/XLC_LOCALE sr_ME.UTF-8 en_US.UTF-8/XLC_LOCALE sr_RS.UTF-8 en_US.UTF-8/XLC_LOCALE sr_RS.UTF-8@latin en_US.UTF-8/XLC_LOCALE sr_YU.UTF-8 en_US.UTF-8/XLC_LOCALE ss_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE st_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE sv_FI.UTF-8 en_US.UTF-8/XLC_LOCALE sv_SE.UTF-8 en_US.UTF-8/XLC_LOCALE ta_IN.UTF-8 en_US.UTF-8/XLC_LOCALE te_IN.UTF-8 en_US.UTF-8/XLC_LOCALE tg_TJ.UTF-8 th_TH.UTF-8/XLC_LOCALE th_TH.UTF-8 en_US.UTF-8/XLC_LOCALE ti_ER.UTF-8 en_US.UTF-8/XLC_LOCALE ti_ET.UTF-8 en_US.UTF-8/XLC_LOCALE tl_PH.UTF-8 en_US.UTF-8/XLC_LOCALE tn_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE tr_TR.UTF-8 en_US.UTF-8/XLC_LOCALE ts_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE tt_RU.UTF-8 en_US.UTF-8/XLC_LOCALE uk_UA.UTF-8 en_US.UTF-8/XLC_LOCALE ur_IN.UTF-8 en_US.UTF-8/XLC_LOCALE ur_PK.UTF-8 en_US.UTF-8/XLC_LOCALE uz_UZ.UTF-8 en_US.UTF-8/XLC_LOCALE ve_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE vi_VN.UTF-8 en_US.UTF-8/XLC_LOCALE wa_BE.UTF-8 en_US.UTF-8/XLC_LOCALE xh_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE yi_US.UTF-8 en_US.UTF-8/XLC_LOCALE ne_NP.UTF-8 zh_CN.UTF-8/XLC_LOCALE zh_CN.UTF-8 zh_HK.UTF-8/XLC_LOCALE zh_HK.UTF-8 zh_CN.UTF-8/XLC_LOCALE zh_SG.UTF-8 zh_TW.UTF-8/XLC_LOCALE zh_TW.UTF-8 en_US.UTF-8/XLC_LOCALE zu_ZA.UTF-8 # # This file contains locale database file names # The first word is the locale database file name and # the second word is the full locale name. # # C/XLC_LOCALE: C iso8859-1/XLC_LOCALE: af_ZA.ISO8859-1 iso8859-6/XLC_LOCALE: ar_AA.ISO8859-6 iso8859-6/XLC_LOCALE: ar_BH.ISO8859-6 iso8859-6/XLC_LOCALE: ar_DZ.ISO8859-6 iso8859-6/XLC_LOCALE: ar_EG.ISO8859-6 iso8859-6/XLC_LOCALE: ar_IQ.ISO8859-6 iso8859-6/XLC_LOCALE: ar_JO.ISO8859-6 iso8859-6/XLC_LOCALE: ar_KW.ISO8859-6 iso8859-6/XLC_LOCALE: ar_LB.ISO8859-6 iso8859-6/XLC_LOCALE: ar_LY.ISO8859-6 iso8859-6/XLC_LOCALE: ar_MA.ISO8859-6 iso8859-6/XLC_LOCALE: ar_OM.ISO8859-6 iso8859-6/XLC_LOCALE: ar_QA.ISO8859-6 iso8859-6/XLC_LOCALE: ar_SA.ISO8859-6 iso8859-6/XLC_LOCALE: ar_SD.ISO8859-6 iso8859-6/XLC_LOCALE: ar_SY.ISO8859-6 iso8859-6/XLC_LOCALE: ar_TN.ISO8859-6 iso8859-6/XLC_LOCALE: ar_YE.ISO8859-6 iso8859-6/XLC_LOCALE: ar_AE.ISO8859-6 iso8859-9e/XLC_LOCALE: az_AZ.ISO8859-9E koi8-c/XLC_LOCALE: az_AZ.KOI8-C iso8859-5/XLC_LOCALE: be_BY.ISO8859-5 microsoft-cp1251/XLC_LOCALE: be_BY.CP1251 iso8859-5/XLC_LOCALE: bg_BG.ISO8859-5 microsoft-cp1251/XLC_LOCALE: bg_BG.CP1251 koi8-r/XLC_LOCALE: bg_BG.KOI8-R iso8859-2/XLC_LOCALE: bs_BA.ISO8859-2 iso8859-1/XLC_LOCALE: br_FR.ISO8859-1 iso8859-14/XLC_LOCALE: br_FR.ISO8859-14 iso8859-15/XLC_LOCALE: br_FR.ISO8859-15 iso8859-1/XLC_LOCALE: ca_AD.ISO8859-1 iso8859-15/XLC_LOCALE: ca_AD.ISO8859-15 iso8859-1/XLC_LOCALE: ca_ES.ISO8859-1 iso8859-15/XLC_LOCALE: ca_ES.ISO8859-15 iso8859-1/XLC_LOCALE: ca_FR.ISO8859-1 iso8859-15/XLC_LOCALE: ca_FR.ISO8859-15 iso8859-1/XLC_LOCALE: ca_IT.ISO8859-1 iso8859-15/XLC_LOCALE: ca_IT.ISO8859-15 iso8859-2/XLC_LOCALE: cs_CZ.ISO8859-2 iso8859-1/XLC_LOCALE: cy_GB.ISO8859-1 iso8859-14/XLC_LOCALE: cy_GB.ISO8859-14 iso8859-15/XLC_LOCALE: cy_GB.ISO8859-15 iso8859-1/XLC_LOCALE: da_DK.ISO8859-1 iso8859-15/XLC_LOCALE: da_DK.ISO8859-15 iso8859-1/XLC_LOCALE: de_AT.ISO8859-1 iso8859-15/XLC_LOCALE: de_AT.ISO8859-15 iso8859-1/XLC_LOCALE: de_BE.ISO8859-1 iso8859-15/XLC_LOCALE: de_BE.ISO8859-15 iso8859-1/XLC_LOCALE: de_CH.ISO8859-1 iso8859-15/XLC_LOCALE: de_CH.ISO8859-15 iso8859-1/XLC_LOCALE: de_DE.ISO8859-1 iso8859-15/XLC_LOCALE: de_DE.ISO8859-15 iso8859-1/XLC_LOCALE: de_LI.ISO8859-1 iso8859-15/XLC_LOCALE: de_LI.ISO8859-15 iso8859-1/XLC_LOCALE: de_LU.ISO8859-1 iso8859-15/XLC_LOCALE: de_LU.ISO8859-15 iso8859-7/XLC_LOCALE: el_GR.ISO8859-7 iso8859-4/XLC_LOCALE: ee_EE.ISO8859-4 iso8859-15/XLC_LOCALE: el_GR.ISO8859-15 iso8859-1/XLC_LOCALE: en_AU.ISO8859-1 iso8859-1/XLC_LOCALE: en_BE.ISO8859-1 iso8859-15/XLC_LOCALE: en_BE.ISO8859-15 iso8859-1/XLC_LOCALE: en_BZ.ISO8859-1 iso8859-1/XLC_LOCALE: en_BW.ISO8859-1 iso8859-1/XLC_LOCALE: en_CA.ISO8859-1 iso8859-1/XLC_LOCALE: en_EN.ISO8859-1 iso8859-1/XLC_LOCALE: en_GB.ISO8859-1 iso8859-15/XLC_LOCALE: en_GB.ISO8859-15 iso8859-1/XLC_LOCALE: en_HK.ISO8859-1 iso8859-1/XLC_LOCALE: en_IE.ISO8859-1 iso8859-15/XLC_LOCALE: en_IE.ISO8859-15 iso8859-15/XLC_LOCALE: en_IN.ISO8859-15 iso8859-1/XLC_LOCALE: en_JM.ISO8859-1 iso8859-1/XLC_LOCALE: en_NZ.ISO8859-1 iso8859-1/XLC_LOCALE: en_PH.ISO8859-1 iso8859-1/XLC_LOCALE: en_SG.ISO8859-1 iso8859-1/XLC_LOCALE: en_TT.ISO8859-1 iso8859-1/XLC_LOCALE: en_UK.ISO8859-1 iso8859-15/XLC_LOCALE: en_UK.ISO8859-15 iso8859-1/XLC_LOCALE: en_US.ISO8859-1 iso8859-15/XLC_LOCALE: en_US.ISO8859-15 iso8859-1/XLC_LOCALE: en_ZA.ISO8859-1 iso8859-15/XLC_LOCALE: en_ZA.ISO8859-15 iso8859-1/XLC_LOCALE: en_ZW.ISO8859-1 iso8859-3/XLC_LOCALE: eo_EO.ISO8859-3 iso8859-3/XLC_LOCALE: eo_XX.ISO8859-3 iso8859-1/XLC_LOCALE: es_AR.ISO8859-1 iso8859-1/XLC_LOCALE: es_BO.ISO8859-1 iso8859-1/XLC_LOCALE: es_CL.ISO8859-1 iso8859-1/XLC_LOCALE: es_CO.ISO8859-1 iso8859-1/XLC_LOCALE: es_CR.ISO8859-1 iso8859-1/XLC_LOCALE: es_DO.ISO8859-1 iso8859-1/XLC_LOCALE: es_EC.ISO8859-1 iso8859-1/XLC_LOCALE: es_ES.ISO8859-1 iso8859-15/XLC_LOCALE: es_ES.ISO8859-15 iso8859-1/XLC_LOCALE: es_GT.ISO8859-1 iso8859-1/XLC_LOCALE: es_HN.ISO8859-1 iso8859-1/XLC_LOCALE: es_MX.ISO8859-1 iso8859-1/XLC_LOCALE: es_NI.ISO8859-1 iso8859-1/XLC_LOCALE: es_PA.ISO8859-1 iso8859-15/XLC_LOCALE: es_PA.ISO8859-15 iso8859-1/XLC_LOCALE: es_PE.ISO8859-1 iso8859-15/XLC_LOCALE: es_PE.ISO8859-15 iso8859-1/XLC_LOCALE: es_PR.ISO8859-1 iso8859-1/XLC_LOCALE: es_PY.ISO8859-1 iso8859-15/XLC_LOCALE: es_PY.ISO8859-15 iso8859-1/XLC_LOCALE: es_SV.ISO8859-1 iso8859-15/XLC_LOCALE: es_SV.ISO8859-15 iso8859-1/XLC_LOCALE: es_US.ISO8859-1 iso8859-1/XLC_LOCALE: es_UY.ISO8859-1 iso8859-15/XLC_LOCALE: es_UY.ISO8859-15 iso8859-1/XLC_LOCALE: es_VE.ISO8859-1 iso8859-15/XLC_LOCALE: es_VE.ISO8859-15 iso8859-1/XLC_LOCALE: et_EE.ISO8859-1 iso8859-4/XLC_LOCALE: et_EE.ISO8859-4 iso8859-13/XLC_LOCALE: et_EE.ISO8859-13 iso8859-15/XLC_LOCALE: et_EE.ISO8859-15 iso8859-1/XLC_LOCALE: eu_ES.ISO8859-1 iso8859-15/XLC_LOCALE: eu_ES.ISO8859-15 isiri-3342/XLC_LOCALE: fa_IR.ISIRI-3342 iso8859-1/XLC_LOCALE: fi_FI.ISO8859-1 iso8859-15/XLC_LOCALE: fi_FI.ISO8859-15 iso8859-1/XLC_LOCALE: fo_FO.ISO8859-1 iso8859-15/XLC_LOCALE: fo_FO.ISO8859-15 iso8859-1/XLC_LOCALE: fr_BE.ISO8859-1 iso8859-15/XLC_LOCALE: fr_BE.ISO8859-15 iso8859-1/XLC_LOCALE: fr_CA.ISO8859-1 iso8859-15/XLC_LOCALE: fr_CA.ISO8859-15 iso8859-1/XLC_LOCALE: fr_CH.ISO8859-1 iso8859-15/XLC_LOCALE: fr_CH.ISO8859-15 iso8859-1/XLC_LOCALE: fr_FR.ISO8859-1 iso8859-15/XLC_LOCALE: fr_FR.ISO8859-15 iso8859-1/XLC_LOCALE: fr_LU.ISO8859-1 iso8859-15/XLC_LOCALE: fr_LU.ISO8859-15 iso8859-1/XLC_LOCALE: ga_IE.ISO8859-1 iso8859-14/XLC_LOCALE: ga_IE.ISO8859-14 iso8859-15/XLC_LOCALE: ga_IE.ISO8859-15 iso8859-1/XLC_LOCALE: gd_GB.ISO8859-1 iso8859-14/XLC_LOCALE: gd_GB.ISO8859-14 iso8859-15/XLC_LOCALE: gd_GB.ISO8859-15 iso8859-1/XLC_LOCALE: gl_ES.ISO8859-1 iso8859-15/XLC_LOCALE: gl_ES.ISO8859-15 iso8859-1/XLC_LOCALE: gv_GB.ISO8859-1 iso8859-14/XLC_LOCALE: gv_GB.ISO8859-14 iso8859-15/XLC_LOCALE: gv_GB.ISO8859-15 iso8859-8/XLC_LOCALE: he_IL.ISO8859-8 microsoft-cp1255/XLC_LOCALE: he_IL.CP1255 iscii-dev/XLC_LOCALE: hi_IN.ISCII-DEV iso8859-2/XLC_LOCALE: hr_HR.ISO8859-2 iso8859-2/XLC_LOCALE: hu_HU.ISO8859-2 armscii-8/XLC_LOCALE: hy_AM.ARMSCII-8 iso8859-1/XLC_LOCALE: id_ID.ISO8859-1 iso8859-1/XLC_LOCALE: id_ID.ISO8859-15 iso8859-1/XLC_LOCALE: is_IS.ISO8859-1 iso8859-15/XLC_LOCALE: is_IS.ISO8859-15 iso8859-1/XLC_LOCALE: it_CH.ISO8859-1 iso8859-15/XLC_LOCALE: it_CH.ISO8859-15 iso8859-1/XLC_LOCALE: it_IT.ISO8859-1 iso8859-15/XLC_LOCALE: it_IT.ISO8859-15 ja/XLC_LOCALE: ja_JP.eucJP ja.SJIS/XLC_LOCALE: ja_JP.SJIS ja.JIS/XLC_LOCALE: ja_JP.JIS7 georgian-academy/XLC_LOCALE: ka_GE.GEORGIAN-ACADEMY georgian-ps/XLC_LOCALE: ka_GE.GEORGIAN-PS iso8859-1/XLC_LOCALE: kl_GL.ISO8859-1 iso8859-15/XLC_LOCALE: kl_GL.ISO8859-15 ko/XLC_LOCALE: ko_KR.eucKR iso8859-1/XLC_LOCALE: kw_GB.ISO8859-1 iso8859-14/XLC_LOCALE: kw_GB.ISO8859-14 iso8859-15/XLC_LOCALE: kw_GB.ISO8859-15 ibm-cp1133/XLC_LOCALE: lo_LA.IBM-CP1133 mulelao-1/XLC_LOCALE: lo_LA.MULELAO-1 iso8859-4/XLC_LOCALE: lt_LT.ISO8859-4 iso8859-13/XLC_LOCALE: lt_LT.ISO8859-13 iso8859-4/XLC_LOCALE: lv_LV.ISO8859-4 iso8859-13/XLC_LOCALE: lv_LV.ISO8859-13 iso8859-13/XLC_LOCALE: mi_NZ.ISO8859-13 iso8859-5/XLC_LOCALE: mk_MK.ISO8859-5 microsoft-cp1251/XLC_LOCALE: mk_MK.CP1251 iso8859-1/XLC_LOCALE: ms_MY.ISO8859-1 iso8859-3/XLC_LOCALE: mt_MT.ISO8859-3 iso8859-1/XLC_LOCALE: nb_NO.ISO8859-1 iso8859-1/XLC_LOCALE: nb_NO.ISO8859-15 iso8859-1/XLC_LOCALE: nl_BE.ISO8859-1 iso8859-15/XLC_LOCALE: nl_BE.ISO8859-15 iso8859-1/XLC_LOCALE: nl_NL.ISO8859-1 iso8859-15/XLC_LOCALE: nl_NL.ISO8859-15 iso8859-1/XLC_LOCALE: nn_NO.ISO8859-1 iso8859-1/XLC_LOCALE: nn_NO.ISO8859-15 iso8859-1/XLC_LOCALE: no_NO.ISO8859-1 iso8859-1/XLC_LOCALE: no_NO.ISO8859-15 iso8859-1/XLC_LOCALE: nr_ZA.ISO8859-1 iso8859-15/XLC_LOCALE: nso_ZA.ISO8859-15 iso8859-1/XLC_LOCALE: ny_NO.ISO8859-1 iso8859-1/XLC_LOCALE: ny_NO.ISO8859-15 iso8859-1/XLC_LOCALE: oc_FR.ISO8859-1 iso8859-15/XLC_LOCALE: oc_FR.ISO8859-15 iso8859-1/XLC_LOCALE: pd_DE.ISO8859-1 iso8859-15/XLC_LOCALE: pd_DE.ISO8859-15 iso8859-1/XLC_LOCALE: pd_US.ISO8859-1 iso8859-15/XLC_LOCALE: pd_US.ISO8859-15 iso8859-1/XLC_LOCALE: ph_PH.ISO8859-1 iso8859-2/XLC_LOCALE: pl_PL.ISO8859-2 iso8859-1/XLC_LOCALE: pp_AN.ISO8859-1 iso8859-1/XLC_LOCALE: pt_BR.ISO8859-1 iso8859-15/XLC_LOCALE: pt_BR.ISO8859-15 iso8859-1/XLC_LOCALE: pt_PT.ISO8859-1 iso8859-15/XLC_LOCALE: pt_PT.ISO8859-15 iso8859-2/XLC_LOCALE: ro_RO.ISO8859-2 iso8859-5/XLC_LOCALE: ru_RU.ISO8859-5 microsoft-cp1251/XLC_LOCALE: ru_RU.CP1251 koi8-r/XLC_LOCALE: ru_RU.KOI8-R microsoft-cp1251/XLC_LOCALE: ru_UA.CP1251 koi8-u/XLC_LOCALE: ru_UA.KOI8-U iso8859-1/XLC_LOCALE: rw_RW.ISO8859-1 iso8859-2/XLC_LOCALE: sh_YU.ISO8859-2 iso8859-2/XLC_LOCALE: sk_SK.ISO8859-2 iso8859-2/XLC_LOCALE: sl_SI.ISO8859-2 iso8859-2/XLC_LOCALE: sq_AL.ISO8859-2 iso8859-2/XLC_LOCALE: sr_YU.ISO8859-2 iso8859-5/XLC_LOCALE: sr_YU.ISO8859-5 microsoft-cp1251/XLC_LOCALE: sr_YU.CP1251 iso8859-1/XLC_LOCALE: ss_ZA.ISO8859-1 iso8859-1/XLC_LOCALE: st_ZA.ISO8859-1 iso8859-1/XLC_LOCALE: sv_FI.ISO8859-1 iso8859-15/XLC_LOCALE: sv_FI.ISO8859-15 iso8859-1/XLC_LOCALE: sv_SE.ISO8859-1 iso8859-15/XLC_LOCALE: sv_SE.ISO8859-15 tscii-0/XLC_LOCALE: ta_IN.TSCII-0 koi8-c/XLC_LOCALE: tg_TJ.KOI8-C th_TH/XLC_LOCALE: th_TH.TIS620 iso8859-11/XLC_LOCALE: th_TH.ISO8859-11 iso8859-1/XLC_LOCALE: tl_PH.ISO8859-1 iso8859-15/XLC_LOCALE: tn_ZA.ISO8859-15 iso8859-9/XLC_LOCALE: tr_TR.ISO8859-9 iso8859-1/XLC_LOCALE: ts_ZA.ISO8859-1 tatar-cyr/XLC_LOCALE: tt_RU.TATAR-CYR koi8-c/XLC_LOCALE: tt_RU.KOI8-C iso8859-5/XLC_LOCALE: uk_UA.ISO8859-5 microsoft-cp1251/XLC_LOCALE: uk_UA.CP1251 koi8-u/XLC_LOCALE: uk_UA.KOI8-U microsoft-cp1256/XLC_LOCALE: ur_PK.CP1256 iso8859-1/XLC_LOCALE: uz_UZ.ISO8859-1 vi_VN.tcvn/XLC_LOCALE: vi_VN.TCVN vi_VN.viscii/XLC_LOCALE: vi_VN.VISCII iso8859-1/XLC_LOCALE: wa_BE.ISO8859-1 iso8859-15/XLC_LOCALE: wa_BE.ISO8859-15 iso8859-1/XLC_LOCALE: xh_ZA.ISO8859-1 microsoft-cp1255/XLC_LOCALE: yi_US.CP1255 zh_CN/XLC_LOCALE: zh_CN.eucCN zh_CN/XLC_LOCALE: zh_CN.gb2312 zh_CN.gbk/XLC_LOCALE: zh_CN.gbk zh_CN.gb18030/XLC_LOCALE: zh_CN.gb18030 zh_HK.big5/XLC_LOCALE: zh_HK.big5 zh_HK.big5hkscs/XLC_LOCALE: zh_HK.big5hkscs zh_TW.big5/XLC_LOCALE: zh_TW.big5 zh_TW/XLC_LOCALE: zh_TW.eucTW iso8859-1/XLC_LOCALE: zu_ZA.ISO8859-1 # Note: The UTF-8 locales don't work correctly yet. Work in progress. en_US.UTF-8/XLC_LOCALE: af_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: am_ET.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_AA.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_AE.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_BH.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_DZ.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_EG.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_IQ.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_JO.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_KW.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_LB.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_LY.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_MA.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_OM.UTF-8 en_US.UTF-8/XLC_LOCALE: bs_BA.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_QA.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_SA.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_SD.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_SY.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_TN.UTF-8 en_US.UTF-8/XLC_LOCALE: ar_YE.UTF-8 en_US.UTF-8/XLC_LOCALE: as_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: ast_ES.UTF-8 en_US.UTF-8/XLC_LOCALE: az_AZ.UTF-8 en_US.UTF-8/XLC_LOCALE: be_BY.UTF-8 en_US.UTF-8/XLC_LOCALE: be_BY.UTF-8@latin en_US.UTF-8/XLC_LOCALE: bg_BG.UTF-8 en_US.UTF-8/XLC_LOCALE: bn_BD.UTF-8 en_US.UTF-8/XLC_LOCALE: bn_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: bo_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: br_FR.UTF-8 en_US.UTF-8/XLC_LOCALE: ca_AD.UTF-8 en_US.UTF-8/XLC_LOCALE: ca_ES.UTF-8 en_US.UTF-8/XLC_LOCALE: ca_FR.UTF-8 en_US.UTF-8/XLC_LOCALE: ca_IT.UTF-8 en_US.UTF-8/XLC_LOCALE: cs_CZ.UTF-8 en_US.UTF-8/XLC_LOCALE: cy_GB.UTF-8 en_US.UTF-8/XLC_LOCALE: da_DK.UTF-8 en_US.UTF-8/XLC_LOCALE: de_AT.UTF-8 en_US.UTF-8/XLC_LOCALE: de_BE.UTF-8 en_US.UTF-8/XLC_LOCALE: de_CH.UTF-8 en_US.UTF-8/XLC_LOCALE: de_DE.UTF-8 en_US.UTF-8/XLC_LOCALE: de_IT.UTF-8 en_US.UTF-8/XLC_LOCALE: de_LI.UTF-8 en_US.UTF-8/XLC_LOCALE: de_LU.UTF-8 en_US.UTF-8/XLC_LOCALE: el_CY.UTF-8 en_US.UTF-8/XLC_LOCALE: el_GR.UTF-8 en_US.UTF-8/XLC_LOCALE: en_AU.UTF-8 en_US.UTF-8/XLC_LOCALE: en_BE.UTF-8 en_US.UTF-8/XLC_LOCALE: en_BW.UTF-8 en_US.UTF-8/XLC_LOCALE: en_BZ.UTF-8 en_US.UTF-8/XLC_LOCALE: en_CA.UTF-8 en_US.UTF-8/XLC_LOCALE: en_DK.UTF-8 en_US.UTF-8/XLC_LOCALE: en_GB.UTF-8 en_US.UTF-8/XLC_LOCALE: en_EN.UTF-8 en_US.UTF-8/XLC_LOCALE: en_HK.UTF-8 en_US.UTF-8/XLC_LOCALE: en_IE.UTF-8 en_US.UTF-8/XLC_LOCALE: en_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: en_JM.UTF-8 en_US.UTF-8/XLC_LOCALE: en_MT.UTF-8 en_US.UTF-8/XLC_LOCALE: en_NZ.UTF-8 en_US.UTF-8/XLC_LOCALE: en_PH.UTF-8 en_US.UTF-8/XLC_LOCALE: en_SG.UTF-8 en_US.UTF-8/XLC_LOCALE: en_TT.UTF-8 en_US.UTF-8/XLC_LOCALE: en_UK.UTF-8 en_US.UTF-8/XLC_LOCALE: en_US.UTF-8 en_US.UTF-8/XLC_LOCALE: en_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: en_ZW.UTF-8 en_US.UTF-8/XLC_LOCALE: eo_EO.UTF-8 en_US.UTF-8/XLC_LOCALE: eo_XX.UTF-8 en_US.UTF-8/XLC_LOCALE: es_AR.UTF-8 en_US.UTF-8/XLC_LOCALE: es_BO.UTF-8 en_US.UTF-8/XLC_LOCALE: es_CL.UTF-8 en_US.UTF-8/XLC_LOCALE: es_CO.UTF-8 en_US.UTF-8/XLC_LOCALE: es_CR.UTF-8 en_US.UTF-8/XLC_LOCALE: es_DO.UTF-8 en_US.UTF-8/XLC_LOCALE: es_EC.UTF-8 en_US.UTF-8/XLC_LOCALE: es_ES.UTF-8 en_US.UTF-8/XLC_LOCALE: es_GT.UTF-8 en_US.UTF-8/XLC_LOCALE: es_HN.UTF-8 en_US.UTF-8/XLC_LOCALE: es_MX.UTF-8 en_US.UTF-8/XLC_LOCALE: es_NI.UTF-8 en_US.UTF-8/XLC_LOCALE: es_PA.UTF-8 en_US.UTF-8/XLC_LOCALE: es_PE.UTF-8 en_US.UTF-8/XLC_LOCALE: es_PR.UTF-8 en_US.UTF-8/XLC_LOCALE: es_PY.UTF-8 en_US.UTF-8/XLC_LOCALE: es_SV.UTF-8 en_US.UTF-8/XLC_LOCALE: es_US.UTF-8 en_US.UTF-8/XLC_LOCALE: es_UY.UTF-8 en_US.UTF-8/XLC_LOCALE: es_VE.UTF-8 en_US.UTF-8/XLC_LOCALE: et_EE.UTF-8 en_US.UTF-8/XLC_LOCALE: eu_ES.UTF-8 en_US.UTF-8/XLC_LOCALE: fa_IR.UTF-8 en_US.UTF-8/XLC_LOCALE: fi_FI.UTF-8 en_US.UTF-8/XLC_LOCALE: fo_FO.UTF-8 en_US.UTF-8/XLC_LOCALE: fr_BE.UTF-8 en_US.UTF-8/XLC_LOCALE: fr_CA.UTF-8 en_US.UTF-8/XLC_LOCALE: fr_CH.UTF-8 en_US.UTF-8/XLC_LOCALE: fr_FR.UTF-8 en_US.UTF-8/XLC_LOCALE: fr_LU.UTF-8 en_US.UTF-8/XLC_LOCALE: ga_IE.UTF-8 en_US.UTF-8/XLC_LOCALE: gd_GB.UTF-8 en_US.UTF-8/XLC_LOCALE: gl_ES.UTF-8 en_US.UTF-8/XLC_LOCALE: gu_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: gv_GB.UTF-8 en_US.UTF-8/XLC_LOCALE: he_IL.UTF-8 en_US.UTF-8/XLC_LOCALE: hi_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: hne_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: hr_HR.UTF-8 en_US.UTF-8/XLC_LOCALE: hu_HU.UTF-8 en_US.UTF-8/XLC_LOCALE: hy_AM.UTF-8 en_US.UTF-8/XLC_LOCALE: ia.UTF-8 en_US.UTF-8/XLC_LOCALE: id_ID.UTF-8 en_US.UTF-8/XLC_LOCALE: ie.UTF-8 en_US.UTF-8/XLC_LOCALE: is_IS.UTF-8 en_US.UTF-8/XLC_LOCALE: it_CH.UTF-8 en_US.UTF-8/XLC_LOCALE: it_IT.UTF-8 en_US.UTF-8/XLC_LOCALE: iu_CA.UTF-8 ja_JP.UTF-8/XLC_LOCALE: ja_JP.UTF-8 en_US.UTF-8/XLC_LOCALE: ka_GE.UTF-8 en_US.UTF-8/XLC_LOCALE: kk_KZ.UTF-8 en_US.UTF-8/XLC_LOCALE: kl_GL.UTF-8 en_US.UTF-8/XLC_LOCALE: km_KH.UTF-8 en_US.UTF-8/XLC_LOCALE: kn_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: ks_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: ks_IN.UTF-8@devanagari ko_KR.UTF-8/XLC_LOCALE: ko_KR.UTF-8 en_US.UTF-8/XLC_LOCALE: ku_TR.UTF-8 en_US.UTF-8/XLC_LOCALE: kw_GB.UTF-8 en_US.UTF-8/XLC_LOCALE: ky_KG.UTF-8 en_US.UTF-8/XLC_LOCALE: lo_LA.UTF-8 en_US.UTF-8/XLC_LOCALE: lt_LT.UTF-8 en_US.UTF-8/XLC_LOCALE: lv_LV.UTF-8 en_US.UTF-8/XLC_LOCALE: mai_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: mi_NZ.UTF-8 en_US.UTF-8/XLC_LOCALE: mk_MK.UTF-8 en_US.UTF-8/XLC_LOCALE: ml_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: mr_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: ms_MY.UTF-8 en_US.UTF-8/XLC_LOCALE: mt_MT.UTF-8 en_US.UTF-8/XLC_LOCALE: nl_BE.UTF-8 en_US.UTF-8/XLC_LOCALE: nl_NL.UTF-8 en_US.UTF-8/XLC_LOCALE: nb_NO.UTF-8 en_US.UTF-8/XLC_LOCALE: nn_NO.UTF-8 en_US.UTF-8/XLC_LOCALE: no_NO.UTF-8 en_US.UTF-8/XLC_LOCALE: nr_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: nso_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: ny_NO.UTF-8 en_US.UTF-8/XLC_LOCALE: oc_FR.UTF-8 en_US.UTF-8/XLC_LOCALE: or_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: pa_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: pa_PK.UTF-8 en_US.UTF-8/XLC_LOCALE: pd_DE.UTF-8 en_US.UTF-8/XLC_LOCALE: pd_US.UTF-8 en_US.UTF-8/XLC_LOCALE: ph_PH.UTF-8 en_US.UTF-8/XLC_LOCALE: pl_PL.UTF-8 en_US.UTF-8/XLC_LOCALE: pp_AN.UTF-8 pt_BR.UTF-8/XLC_LOCALE: pt_BR.UTF-8 pt_PT.UTF-8/XLC_LOCALE: pt_PT.UTF-8 en_US.UTF-8/XLC_LOCALE: ro_RO.UTF-8 ru_RU.UTF-8/XLC_LOCALE: ru_RU.UTF-8 en_US.UTF-8/XLC_LOCALE: ru_UA.UTF-8 en_US.UTF-8/XLC_LOCALE: rw_RW.UTF-8 en_US.UTF-8/XLC_LOCALE: sa_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: sd_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: sd_IN.UTF-8@devanagari en_US.UTF-8/XLC_LOCALE: se_NO.UTF-8 en_US.UTF-8/XLC_LOCALE: sh_BA.UTF-8 en_US.UTF-8/XLC_LOCALE: sh_YU.UTF-8 en_US.UTF-8/XLC_LOCALE: si_LK.UTF-8 en_US.UTF-8/XLC_LOCALE: sk_SK.UTF-8 en_US.UTF-8/XLC_LOCALE: sl_SI.UTF-8 en_US.UTF-8/XLC_LOCALE: sq_AL.UTF-8 en_US.UTF-8/XLC_LOCALE: sr_ME.UTF-8 en_US.UTF-8/XLC_LOCALE: sr_RS.UTF-8 en_US.UTF-8/XLC_LOCALE: sr_RS.UTF-8@latin en_US.UTF-8/XLC_LOCALE: sr_YU.UTF-8 en_US.UTF-8/XLC_LOCALE: ss_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: st_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: sv_FI.UTF-8 en_US.UTF-8/XLC_LOCALE: sv_SE.UTF-8 en_US.UTF-8/XLC_LOCALE: ta_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: te_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: tg_TJ.UTF-8 th_TH.UTF-8/XLC_LOCALE: th_TH.UTF-8 en_US.UTF-8/XLC_LOCALE: ti_ER.UTF-8 en_US.UTF-8/XLC_LOCALE: ti_ET.UTF-8 en_US.UTF-8/XLC_LOCALE: tl_PH.UTF-8 en_US.UTF-8/XLC_LOCALE: tn_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: tr_TR.UTF-8 en_US.UTF-8/XLC_LOCALE: ts_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: tt_RU.UTF-8 en_US.UTF-8/XLC_LOCALE: uk_UA.UTF-8 en_US.UTF-8/XLC_LOCALE: ur_IN.UTF-8 en_US.UTF-8/XLC_LOCALE: ur_PK.UTF-8 en_US.UTF-8/XLC_LOCALE: uz_UZ.UTF-8 en_US.UTF-8/XLC_LOCALE: ve_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: vi_VN.UTF-8 en_US.UTF-8/XLC_LOCALE: wa_BE.UTF-8 en_US.UTF-8/XLC_LOCALE: xh_ZA.UTF-8 en_US.UTF-8/XLC_LOCALE: yi_US.UTF-8 en_US.UTF-8/XLC_LOCALE: ne_NP.UTF-8 zh_CN.UTF-8/XLC_LOCALE: zh_CN.UTF-8 zh_HK.UTF-8/XLC_LOCALE: zh_HK.UTF-8 zh_CN.UTF-8/XLC_LOCALE: zh_SG.UTF-8 zh_TW.UTF-8/XLC_LOCALE: zh_TW.UTF-8 en_US.UTF-8/XLC_LOCALE: zu_ZA.UTF-8 xkbcommon-libxkbcommon-54ee7ac/test/data/rules/000077500000000000000000000000001510033435100217055ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/rules/all_qualifier000066400000000000000000000031671510033435100244500ustar00rootroot00000000000000! model = keycodes my_model = my_keycodes * = default_keycodes ! layout variant = symbols layout_a my_variant = symbols_a+extra_variant ! layout = symbols layout_a = symbols_a layout_b = symbols_b * = default_symbols ! layout[1] = symbols layout_a = symbols_a:1 layout_b = symbols_b:1 layout_x = base:all // strange but valid * = default_symbols:1 ! layout[2] = symbols layout_a = +symbols_a:2 layout_b = +symbols_b:2 * = +default_symbols:2 ! layout[3] = symbols layout_a = +symbols_a:3 layout_b = +symbols_b:3 * = +default_symbols:3 ! layout[4] = symbols layout_a = +symbols_a:4 layout_b = +symbols_b:4 * = +default_symbols:4 // WARNING: Invalid at the moment. Here for future test ! layout[5] = symbols layout_a = +symbols_a:5 layout_b = +symbols_b:5 layout_c = +symbols_c:5 * = +default_symbols:5 // Combine with special indices ! layout[first] variant[first] = symbols * extra1 = +extra_symbols:all // Combine with special indices (valid but raises a warning) ! layout[any] variant[any] = symbols * extra2 = +extra_symbols1:%i+extra_symbols2:all * extra3 = +extra_symbols2:all+extra_symbols1:%i ! model = types my_model = my_types * = default_types ! model = compat my_model = my_compat * = default_compat ! option = symbols my_option = +extra_option:all xkbcommon-libxkbcommon-54ee7ac/test/data/rules/all_qualifier-limit000066400000000000000000000006441510033435100255610ustar00rootroot00000000000000! model = keycodes * = default_keycodes ! layout[1] = symbols * = x:all // force x on all groups ! layout[later] = symbols // skipped, as it has no explicit merge mode and // thus is not appended to previous * = skip ! model = types * = default_types ! model = compat * = default_compat ! option = symbols xkbcommon-libxkbcommon-54ee7ac/test/data/rules/base000066400000000000000000001373471510033435100225610ustar00rootroot00000000000000// DO NOT EDIT THIS FILE - IT WAS AUTOGENERATED BY merge.py FROM rules/*.part // // // Rules for resolving XKB components for use with XFree86 // Copyright 1996 by Joseph Moss // // 2002 Modifier: Ivan Pascal The XFree86 Project // // If you want non-latin layouts implicitly include the en_US layout // uncomment lines below //! $nonlatin = am ara ben bd bg bt by cs deva ge gh gr guj guru il \ // in ir iku jp kan kh kr la lao lk mk mm mn mv mal olck \ // ori pk ru scc sy syr tel th tj tam ua uz // PC models ! $pcmodels = pc86 pc101 pc102 pc104 pc104alt pc105 // Jolla devices and keyboards ! $jollamodels = jollasbj // Microsoft models (using MS geometry) ! $msmodels = microsoft microsoft4000 microsoft7000 microsoftpro microsoftprousb microsoftprose microsoftsurface // Nokia devices and keyboards ! $nokiamodels = nokiasu8w nokiarx44 nokiarx51 // TypeMatrix geometries ! $tmgeometries = tm2020 tm2030PS2 tm2030USB tm2030USB-102 tm2030USB-106 // Layouts that provide further specializations for the OLPC ! $olpclayouts = af am ara br ca es et fr it kh kz in mn np ru th tr us ! $macbooks = macbook78 macbook79 ! $maclaptop = ibook powerbook macbook78 macbook79 ! $applealu = applealu_ansi applealu_iso applealu_jis ! $macs = macintosh macintosh_old ibook powerbook macbook78 macbook79 ! $macvendorlayouts = ch de dk fi fr gb is it latam nl no pt se us ! $azerty = be fr ! $qwertz = al cz de hr hu ro si sk // all layouts with 3rd and 4th groups ! $threelevellayouts = al az \ be br bt \ ca ch cs cz \ de dk \ ee es \ fi fo fr \ gb gr \ hu \ ie ir is it \ latam \ lk lt \ mn mt \ nl no \ pl pt \ ro \ se sk \ tr \ us \ vn \ za ! $thinkpads = thinkpad thinkpad60 thinkpadz60 ! $sun = sun_type6_jp sun_type6_usb sun_type6_euro_usb \ sun_type6_jp_usb sun_type6_unix_usb sun_type7_jp_usb \ sun_type7_usb sun_type7_euro_usb sun_type7_unix_usb ! $sun_jp = sun_type6_jp sun_type6_jp_usb sun_type7_jp_usb // Sun Type_6_7 keyboards with custom layouts ! $sun_custom = ara be br ca ch cz de dk \ ee es fi fr gb gr it jp \ kr lt lv nl no pl pt ro \ ru se sk tr tw ua us ! $sun_var = sun_type6 sun_type6_suncompat sun_type6_de sun_type6_fr \ sun_type7 sun_type7_suncompat suncompat ! $sun_compat = sun_type6 sun_type6_suncompat sun_type7_suncompat suncompat ! $inetkbds = acer_c300 acer_ferrari4k acer_laptop \ airkey \ apple armada azonaRF2300 \ benqx brother \ btc5113rf btc9000 btc9000a btc9001ah btc5090 btc9019u \ cherryblue cherrybluea cherryblueb \ cherrycyboard cherrycmexpert \ chicony chicony0108 chicony0420 chicony9885 \ compalfl90 \ compaqeak8 compaqik7 compaqik13 compaqik18 \ creativedw7000 \ cymotionlinux \ dell dellm65 inspiron dellusbmm \ emachines ennyah_dkb1008 evdev \ genius geniuscomfy2 \ gyration honeywell_euroboard \ hp250x hp5xx hp500fa hpdv5 \ hpi6 hpxe3gc hpxe3gf hpxe4xxx hpxt1000 hpzt11xx \ ibm_spacesaver ipaq inspiron intel \ logiaccess logicda logicink \ logiex110 logiclx300 \ logiinkse logiinkseusb logiitc logiik \ logitech_base itouch logiultrax \ logitech_g15 \ logidinovo logidinovoedge \ microsoft4000 microsoft7000 microsoftinet microsoftprousb microsoftprooem microsoftprose \ microsoftoffice microsoftmult \ mx1998 mx2500 mx2750 \ oretec \ pc105 \ presario propeller \ qtronix \ rapidaccess rapidaccess2 thinkpad60 \ samsung4500 samsung4510 \ silvercrest \ sk1300 sk2500 sk6200 sk7100 \ sven sven303 symplon \ teck227 teck229 \ toshiba_s3000 trust trustda \ unitekkb1925 yahoo \ apex300 ! $inetmediakbds = acer_ferrari4k acer_laptop btc5090 btc9019u cherryblueb \ cherrybluea herrycyboard chicony042 compaqik13 compaqik18 \ armada presario dellm65 inspiron dellusbmm diamond \ ennyah_dkb1008 genius geniuscomfy2 hpi6 hpxe3gc hpxe3gf \ hpxt1000 hpzt11xx hpdv5 hpxe4xxx hp5xx thinkpad60 ogitech_base \ logidinovo logidinovoedge logitech_g15 mx1998 mx2500 mx2750 \ microsoft4000 microsoft7000 microsoftprooem microsoftmult \ propeller samsung4500 samsung4510 sk1300 sk2500 sk7100 \ toshiba_s3000 trust trustda cymotionlinux silvercrest \ emachines benqx unitekkb1925 creativedw7000 compalfl90 \ pc105 a4techKB21 a4techKBS8 a4_rfkb23 asus_laptop btc6301urf \ dexxa dtk2000 fscaa1667g geniuskb19e geniuscomfy latitude \ microsoftpro precision_m scorpius sp_inet targa_v811 thinkpad \ tm2030USB-102 tm2030USB-106 trust_slimline ! $dvoraklayouts = br ca de ee es fr gb no pl se us ! model = keycodes amiga = amiga(de) ataritt = ataritt(de) empty = empty $sun_jp = sun(type6_jp_usb) $sun = sun(type6_usb) pc98 = xfree98(pc98) $applealu = macintosh(alukbd) macintosh_hhk = macintosh(hhk) macintosh_old = macintosh(old) $macs = macintosh thinkpadz60 = xfree86(thinkpadz60) * = xfree86 ! layout[1] = keycodes $azerty = +aliases(azerty) $qwertz = +aliases(qwertz) * = +aliases(qwerty) ! layout = keycodes $azerty = +aliases(azerty) $qwertz = +aliases(qwertz) * = +aliases(qwerty) ! option = keycodes ! model layout = geometry thinkpad us = thinkpad(us) ! model = geometry microsoftelite = microsoft(elite) $msmodels = microsoft(natural) dell101 = dell(dell101) dellm65 = dell(dellm65) latitude = dell(latitude) flexpro = keytronic(FlexPro) hp6000 = hp(omnibook) hpmini110 = hp(mini110) hpdv5 = hp(dv5) omnikey101 = northgate(omnikey101) sanwaskbkg3 = sanwa(sanwaskbkg3) $pcmodels = pc(%m) everex = everex(STEPnote) thinkpad = thinkpad(intl) thinkpad60 = thinkpad(60) thinkpadz60 = thinkpad(60) apex300 = steelseries(apex300) $tmgeometries = typematrix(%m) winbook = winbook(XP5) pc98 = nec(pc98) $applealu = macintosh(%m) $macbooks = macintosh(%m) $macs = macintosh(macintosh) hhk = hhk(basic) kinesis = kinesis(model100) $nokiamodels = nokia(%m) sun_type6_jp = sun(type6jp) sun_type6_usb = sun(type6) sun_type6_euro_usb = sun(type6tuv) sun_type6_jp_usb = sun(type6jp) sun_type6_unix_usb = sun(type6unix) sun_type7_jp_usb = sun(type6jp) sun_type7_usb = sun(type7) sun_type7_euro_usb = sun(type7tuv) sun_type7_unix_usb = sun(type7unix) * = pc(pc104) ! model layout variant = symbols * ben basic = pc+in(ben) * ben probhat = pc+in(ben_probhat) * dev basic = pc+in(deva) * dvorak $dvoraklayouts = pc+%v(dvorak) * dvorak basic = pc+us(dvorak) * dvorak pl_basic = pc+pl(dvorak) * dvorak pl = pc+pl(dvorak_quotes) * dvorak pl_altquotes = pc+pl(dvorak_altquotes) * dzdwi basic = pc+bt(basic) * fi basic = pc+fi(classic) * ge azerty_tskapo = pc+fr(geo) * guj basic = pc+in(guj) * gur basic = pc+in(guru) * ie laptop = pc+ie(basic) * ie CloGaelachLaptop = pc+ie(CloGaelach) * in urd = pc+in(urd-phonetic) * iu basic = pc+ca(ike) * lo basic = pc+la(basic) * kan basic = pc+in(kan) * mal basic = pc+in(mal) * mal mlplusnum = pc+in(mal) * ogham basic = pc+ie(ogam) * ogham laptop = pc+ie(ogam) * ogham is434 = pc+ie(ogam_is434) * ogham is434laptop = pc+ie(ogam_is434) * ori basic = pc+in(ori) * ro de = pc+ro(winkeys) * ro us = pc+ro(std) * ro academic = pc+ro(std) * ro std_comma = pc+ro(std) * ro comma = pc+ro(basic) * ru os = pc+ru(os_legacy) * pk urd = pc+pk(urd-phonetic) * sapmi basic = pc+no(smi) * sapmi nodeadkeys = pc+no(smi_nodeadkeys) * sapmi sefi = pc+fi(smi) * sin phonetic-static = pc+in(sin_phonetic) * syr basic = pc+sy(syc) * syr phonetic = pc+sy(syc_phonetic) * tam INSCRIPT = pc+in(tam) * tam UNI = pc+in(tam_unicode) * tam NUMERAL-KEYBOARD = pc+in(tam_keyboard_with_numerals) * tam TAB = pc+in(tam_TAB) * tam TSCII = pc+in(tam_TSCII) * tel basic = pc+in(tel) * yu basic = pc+srp(latin) * yu unicode = pc+srp(latinunicode) * yu yz = pc+srp(latinyz) * yu unicodeyz = pc+srp(latinunicodeyz) classmate us intl = pc+us(classmate-intl) classmate us alt-intl = pc+us(classmate-alt-intl) classmate us altgr-intl = pc+us(classmate-altgr-intl) nokiarx51 cz qwerty = nokia_vndr/rx-51(cz_qwerty) * $sun_custom $sun_var = pc+sun_vndr/%l%(v) ! model layout = symbols * ar = pc+ara * ben = pc+in(ben) * bs = pc+ba * cs = pc+rs * cz_qwerty = pc+cz(qwerty) * dev = pc+in(deva) * dvorak = pc+us(dvorak) * dzdwi = pc+bt * el = pc+gr * en_US = pc+latin * guj = pc+in(guj) * gur = pc+in(guru) * iu = pc+ca(ike) * lo = pc+la * kan = pc+in(kan) * mi = pc+mao * ogham = pc+ie(ogam) * ori = pc+ie(ori) * sapmi = pc+no(smi) * sr = pc+srp * syr = pc+sy(syc) * tel = pc+in(tel) * tml = pc+in(tam) * yu = pc+srp * fr-latin9 = pc+fr(latin9) * us_intl = pc+us(alt-intl) * ben(basic) = pc+in(ben) * ben(probhat) = pc+in(ben_probhat) * dev(basic) = pc+in(deva) * dvorak($dvoraklayouts) = pc+%v(dvorak) * dvorak(basic) = pc+us(dvorak) * dvorak(pl_basic) = pc+pl(dvorak) * dvorak(pl) = pc+pl(dvorak_quotes) * dvorak(pl_altquotes) = pc+pl(dvorak_altquotes) * dzdwi(basic) = pc+bt(basic) * fi(basic) = pc+fi(classic) * ge(azerty_tskapo) = pc+fr(geo) * guj(basic) = pc+in(guj) * gur(basic) = pc+in(guru) * ie(laptop) = pc+ie(basic) * ie(CloGaelachLaptop) = pc+ie(CloGaelach) * in(urd) = pc+in(urd-phonetic) * iu(basic) = pc+ca(ike) * lo(basic) = pc+la(basic) * kan(basic) = pc+in(kan) * mal(basic) = pc+in(mal) * mal(mlplusnum) = pc+in(mal) * ogham(basic) = pc+ie(ogam) * ogham(laptop) = pc+ie(ogam) * ogham(is434) = pc+ie(ogam_is434) * ogham(is434laptop) = pc+ie(ogam_is434) * ori(basic) = pc+in(ori) * ro(de) = pc+ro(winkeys) * ro(us) = pc+ro(std) * ro(academic) = pc+ro(std) * ro(std_comma) = pc+ro(std) * ro(comma) = pc+ro(basic) * ru(os) = pc+ru(os_legacy) * pk(urd) = pc+pk(urd-phonetic) * sapmi(basic) = pc+no(smi) * sapmi(nodeadkeys) = pc+no(smi_nodeadkeys) * sapmi(sefi) = pc+fi(smi) * sin(phonetic-static) = pc+in(sin_phonetic) * syr(basic) = pc+sy(syc) * syr(phonetic) = pc+sy(syc_phonetic) * tam(INSCRIPT) = pc+in(tam) * tam(UNI) = pc+in(tam_unicode) * tam(NUMERAL-KEYBOARD) = pc+in(tam_keyboard_with_numerals) * tam(TAB) = pc+in(tam_TAB) * tam(TSCII) = pc+in(tam_TSCII) * tel(basic) = pc+in(tel) * yu(basic) = pc+srp(latin) * yu(unicode) = pc+srp(latinunicode) * yu(yz) = pc+srp(latinyz) * yu(unicodeyz) = pc+srp(latinunicodeyz) ataritt $nonlatin = xfree68_vndr/ataritt(us)+%l%(v):2 ataritt * = xfree68_vndr/ataritt(us)+%l%(v) amiga $nonlatin = xfree68_vndr/amiga(usa1)+%l%(v):2 amiga * = xfree68_vndr/amiga(usa1)+%l%(v) classmate us = pc+%l(classmate) empty * = empty(basic) * empty = empty(basic) jollasbj $nonlatin = jolla_vndr/sbj(common)+us+%l%(v):2 jollasbj * = jolla_vndr/sbj(common)+%l%(v) $sun $sun_custom = pc+sun_vndr/%l%(v) pc98 nec_vndr/jp = nec_vndr/jp(pc98) macintosh_old us = macintosh_vndr/us(oldmac) macintosh_old en_US = macintosh_vndr/us(oldmac) macintosh_old $macvendorlayouts = macintosh_vndr/us(oldmac)+macintosh_vndr/%l%(v) macintosh_old $nonlatin = macintosh_vndr/us(oldmac)+%l%(v):2 macintosh_old * = macintosh_vndr/us(oldmac)+%l%(v) applealu_jis jp = macintosh_vndr/apple(alukbd)+macintosh_vndr/jp(usmac)+macintosh_vndr/jp(mac):2 applealu_jis * = macintosh_vndr/apple(alukbd)+%l%(v)+macintosh_vndr/jp(mac):2 $applealu $macvendorlayouts = macintosh_vndr/apple(alukbd)+macintosh_vndr/%l%(v) $applealu * = macintosh_vndr/apple(alukbd)+%l%(v) $macs en_US = pc+macintosh_vndr/us(extended) $macs $macvendorlayouts = pc+macintosh_vndr/%l%(v) nokiarx44 * = nokia_vndr/rx-44(%l) nokiarx51 cz(qwerty) = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(cz_qwerty) nokiarx51 * = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(%l%_v) nokiasu8w * = nokia_vndr/su-8w(%l) olpc $olpclayouts = olpc+%l%(m) olpc * = olpc+%l%(v) olpcm $olpclayouts = olpc+%l%(m) olpcm * = olpc+%l%(v) $thinkpads br = pc+br(thinkpad) sl-c3x00 * = pc+sharp_vndr/sl-c3x00(basic) ws003sh * = pc+sharp_vndr/ws003sh(basic) ws007sh * = pc+sharp_vndr/ws007sh(basic) ws011sh * = pc+sharp_vndr/ws011sh(basic) ws020sh * = pc+sharp_vndr/ws020sh(basic) * $nonlatin = pc+us+%l%(v):2 * * = pc+%l%(v) ! model layout[1] = symbols * ar = pc+ara%(v[1]) * ben = pc+in(ben) * bs = pc+ba%(v[1]) * cs = pc+rs%(v[1]) * cz_qwerty = pc+cz(qwerty) * dev = pc+in(deva) * dvorak = pc+us(dvorak) * dzdwi = pc+bt%(v[1]) * el = pc+gr%(v[1]) * en_US = pc+latin%(v[1]) * guj = pc+in(guj) * gur = pc+in(guru) * iu = pc+ca(ike) * lo = pc+la%(v[1]) * kan = pc+in(kan) * mi = pc+mao%(v[1]) * ogham = pc+ie(ogam) * ori = pc+ie(ori) * sapmi = pc+no(smi) * sr = pc+srp%(v[1]) * syr = pc+sy(syc) * tel = pc+in(tel) * tml = pc+in(tam) * yu = pc+srp%(v[1]) * fr-latin9 = pc+fr(latin9) * us_intl = pc+us(alt-intl) * ben(basic) = pc+in(ben) * ben(probhat) = pc+in(ben_probhat) * dev(basic) = pc+in(deva) * dvorak($dvoraklayouts) = pc+%v(dvorak) * dvorak(basic) = pc+us(dvorak) * dvorak(pl_basic) = pc+pl(dvorak) * dvorak(pl) = pc+pl(dvorak_quotes) * dvorak(pl_altquotes) = pc+pl(dvorak_altquotes) * dzdwi(basic) = pc+bt(basic) * fi(basic) = pc+fi(classic) * ge(azerty_tskapo) = pc+fr(geo) * guj(basic) = pc+in(guj) * gur(basic) = pc+in(guru) * ie(laptop) = pc+ie(basic) * ie(CloGaelachLaptop) = pc+ie(CloGaelach) * in(urd) = pc+in(urd-phonetic) * iu(basic) = pc+ca(ike) * lo(basic) = pc+la(basic) * kan(basic) = pc+in(kan) * mal(basic) = pc+in(mal) * mal(mlplusnum) = pc+in(mal) * ogham(basic) = pc+ie(ogam) * ogham(laptop) = pc+ie(ogam) * ogham(is434) = pc+ie(ogam_is434) * ogham(is434laptop) = pc+ie(ogam_is434) * ori(basic) = pc+in(ori) * ro(de) = pc+ro(winkeys) * ro(us) = pc+ro(std) * ro(academic) = pc+ro(std) * ro(std_comma) = pc+ro(std) * ro(comma) = pc+ro(basic) * ru(os) = pc+ru(os_legacy) * pk(urd) = pc+pk(urd-phonetic) * sapmi(basic) = pc+no(smi) * sapmi(nodeadkeys) = pc+no(smi_nodeadkeys) * sapmi(sefi) = pc+fi(smi) * sin(phonetic-static) = pc+in(sin_phonetic) * syr(basic) = pc+sy(syc) * syr(phonetic) = pc+sy(syc_phonetic) * tam(INSCRIPT) = pc+in(tam) * tam(UNI) = pc+in(tam_unicode) * tam(NUMERAL-KEYBOARD) = pc+in(tam_keyboard_with_numerals) * tam(TAB) = pc+in(tam_TAB) * tam(TSCII) = pc+in(tam_TSCII) * tel(basic) = pc+in(tel) * yu(basic) = pc+srp(latin) * yu(unicode) = pc+srp(latinunicode) * yu(yz) = pc+srp(latinyz) * yu(unicodeyz) = pc+srp(latinunicodeyz) ataritt * = xfree68_vndr/ataritt(us)+%l[1]%(v[1]) amiga * = xfree68_vndr/amiga(usa1)+%l[1]%(v[1]) jollasbj * = jolla_vndr/sbj(common)+%l[1]%(v[1]) $sun $sun_custom = pc+sun_vndr/%l[1]%(v[1]) macintosh_old us = macintosh_vndr/us(oldmac) macintosh_old $macvendorlayouts = macintosh_vndr/us(oldmac)+macintosh_vndr/%l[1]%(v[1]) macintosh_old * = macintosh_vndr/us(oldmac)+%l[1]%(v[1]) applealu_jis us = macintosh_vndr/apple(alukbd)+macintosh_vndr/jp(usmac) $applealu $macvendorlayouts = macintosh_vndr/apple(alukbd)+macintosh_vndr/%l[1]%(v[1]) $applealu * = macintosh_vndr/apple(alukbd)+%l[1]%(v[1]) $macs $macvendorlayouts = pc+macintosh_vndr/%l[1]%(v[1]) nokiarx51 cz(qwerty) = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(cz_qwerty) nokiarx51 * = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(%l[1]%_v[1]) $thinkpads br = pc+%l[1](thinkpad) * * = pc+%l[1]%(v[1]) ! model layout[1] variant[1] = symbols * ben basic = pc+in(ben) * ben probhat = pc+in(ben_probhat) * dev basic = pc+in(deva) * dvorak $dvoraklayouts = pc+%v(dvorak) * dvorak basic = pc+us(dvorak) * dvorak pl_basic = pc+pl(dvorak) * dvorak pl = pc+pl(dvorak_quotes) * dvorak pl_altquotes = pc+pl(dvorak_altquotes) * dzdwi basic = pc+bt(basic) * fi basic = pc+fi(classic) * ge azerty_tskapo = pc+fr(geo) * guj basic = pc+in(guj) * gur basic = pc+in(guru) * ie laptop = pc+ie(basic) * ie CloGaelachLaptop = pc+ie(CloGaelach) * in urd = pc+in(urd-phonetic) * iu basic = pc+ca(ike) * lo basic = pc+la(basic) * kan basic = pc+in(kan) * mal basic = pc+in(mal) * mal mlplusnum = pc+in(mal) * ogham basic = pc+ie(ogam) * ogham laptop = pc+ie(ogam) * ogham is434 = pc+ie(ogam_is434) * ogham is434laptop = pc+ie(ogam_is434) * ori basic = pc+in(ori) * ro de = pc+ro(winkeys) * ro us = pc+ro(std) * ro academic = pc+ro(std) * ro std_comma = pc+ro(std) * ro comma = pc+ro(basic) * ru os = pc+ru(os_legacy) * pk urd = pc+pk(urd-phonetic) * sapmi basic = pc+no(smi) * sapmi nodeadkeys = pc+no(smi_nodeadkeys) * sapmi sefi = pc+fi(smi) * sin phonetic-static = pc+in(sin_phonetic) * syr basic = pc+sy(syc) * syr phonetic = pc+sy(syc_phonetic) * tam INSCRIPT = pc+in(tam) * tam UNI = pc+in(tam_unicode) * tam NUMERAL-KEYBOARD = pc+in(tam_keyboard_with_numerals) * tam TAB = pc+in(tam_TAB) * tam TSCII = pc+in(tam_TSCII) * tel basic = pc+in(tel) * yu basic = pc+srp(latin) * yu unicode = pc+srp(latinunicode) * yu yz = pc+srp(latinyz) * yu unicodeyz = pc+srp(latinunicodeyz) ! model layout[2] = symbols * ar = +ara%(v[2]):2 * ben = +in(ben):2 * bs = +ba%(v[2]):2 * cs = +rs%(v[2]):2 * cz_qwerty = +cz(qwerty):2 * dev = +in(deva):2 * dvorak = +us(dvorak):2 * dzdwi = +bt%(v[2]):2 * el = +gr%(v[2]):2 * en_US = +latin%(v[2]):2 * guj = +in(guj):2 * gur = +in(guru):2 * iu = +ca(ike):2 * lo = +la%(v[2]):2 * kan = +in(kan):2 * mi = +mao%(v[2]):2 * ogham = +ie(ogam):2 * ori = +ie(ori):2 * sapmi = +no(smi):2 * sr = +srp%(v[2]):2 * syr = +sy(syc):2 * tel = +in(tel):2 * tml = +in(tam):2 * yu = +srp%(v[2]):2 * fr-latin9 = +fr(latin9):2 * us_intl = +us(alt-intl):2 * ben(basic) = +in(ben):2 * ben(probhat) = +in(ben_probhat):2 * dev(basic) = +in(deva):2 * dvorak($dvoraklayouts) = +%v(dvorak):2 * dvorak(basic) = +us(dvorak):2 * dvorak(pl_basic) = +pl(dvorak):2 * dvorak(pl) = +pl(dvorak_quotes):2 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):2 * dzdwi(basic) = +bt(basic):2 * fi(basic) = +fi(classic):2 * ge(azerty_tskapo) = +fr(geo):2 * guj(basic) = +in(guj):2 * gur(basic) = +in(guru):2 * ie(laptop) = +ie(basic):2 * ie(CloGaelachLaptop) = +ie(CloGaelach):2 * in(urd) = +in(urd-phonetic):2 * iu(basic) = +ca(ike):2 * lo(basic) = +la(basic):2 * kan(basic) = +in(kan):2 * mal(basic) = +in(mal):2 * mal(mlplusnum) = +in(mal):2 * ogham(basic) = +ie(ogam):2 * ogham(laptop) = +ie(ogam):2 * ogham(is434) = +ie(ogam_is434):2 * ogham(is434laptop) = +ie(ogam_is434):2 * ori(basic) = +in(ori):2 * ro(de) = +ro(winkeys):2 * ro(us) = +ro(std):2 * ro(academic) = +ro(std):2 * ro(std_comma) = +ro(std):2 * ro(comma) = +ro(basic):2 * ru(os) = +ru(os_legacy):2 * pk(urd) = +pk(urd-phonetic):2 * sapmi(basic) = +no(smi):2 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):2 * sapmi(sefi) = +fi(smi):2 * sin(phonetic-static) = +in(sin_phonetic):2 * syr(basic) = +sy(syc):2 * syr(phonetic) = +sy(syc_phonetic):2 * tam(INSCRIPT) = +in(tam):2 * tam(UNI) = +in(tam_unicode):2 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):2 * tam(TAB) = +in(tam_TAB):2 * tam(TSCII) = +in(tam_TSCII):2 * tel(basic) = +in(tel):2 * yu(basic) = +srp(latin):2 * yu(unicode) = +srp(latinunicode):2 * yu(yz) = +srp(latinyz):2 * yu(unicodeyz) = +srp(latinunicodeyz):2 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):2 nokiarx51 * = +nokia_vndr/rx-51(%l[2]%_v[2]):2 $sun $sun_custom = +sun_vndr/%l[2]%(v[2]):2 * * = +%l[2]%(v[2]):2 ! model layout[3] = symbols * ar = +ara%(v[3]):3 * ben = +in(ben):3 * bs = +ba%(v[3]):3 * cs = +rs%(v[3]):3 * cz_qwerty = +cz(qwerty):3 * dev = +in(deva):3 * dvorak = +us(dvorak):3 * dzdwi = +bt%(v[3]):3 * el = +gr%(v[3]):3 * en_US = +latin%(v[3]):3 * guj = +in(guj):3 * gur = +in(guru):3 * iu = +ca(ike):3 * lo = +la%(v[3]):3 * kan = +in(kan):3 * mi = +mao%(v[3]):3 * ogham = +ie(ogam):3 * ori = +ie(ori):3 * sapmi = +no(smi):3 * sr = +srp%(v[3]):3 * syr = +sy(syc):3 * tel = +in(tel):3 * tml = +in(tam):3 * yu = +srp%(v[3]):3 * fr-latin9 = +fr(latin9):3 * us_intl = +us(alt-intl):3 * ben(basic) = +in(ben):3 * ben(probhat) = +in(ben_probhat):3 * dev(basic) = +in(deva):3 * dvorak($dvoraklayouts) = +%v(dvorak):3 * dvorak(basic) = +us(dvorak):3 * dvorak(pl_basic) = +pl(dvorak):3 * dvorak(pl) = +pl(dvorak_quotes):3 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):3 * dzdwi(basic) = +bt(basic):3 * fi(basic) = +fi(classic):3 * ge(azerty_tskapo) = +fr(geo):3 * guj(basic) = +in(guj):3 * gur(basic) = +in(guru):3 * ie(laptop) = +ie(basic):3 * ie(CloGaelachLaptop) = +ie(CloGaelach):3 * in(urd) = +in(urd-phonetic):3 * iu(basic) = +ca(ike):3 * lo(basic) = +la(basic):3 * kan(basic) = +in(kan):3 * mal(basic) = +in(mal):3 * mal(mlplusnum) = +in(mal):3 * ogham(basic) = +ie(ogam):3 * ogham(laptop) = +ie(ogam):3 * ogham(is434) = +ie(ogam_is434):3 * ogham(is434laptop) = +ie(ogam_is434):3 * ori(basic) = +in(ori):3 * ro(de) = +ro(winkeys):3 * ro(us) = +ro(std):3 * ro(academic) = +ro(std):3 * ro(std_comma) = +ro(std):3 * ro(comma) = +ro(basic):3 * ru(os) = +ru(os_legacy):3 * pk(urd) = +pk(urd-phonetic):3 * sapmi(basic) = +no(smi):3 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):3 * sapmi(sefi) = +fi(smi):3 * sin(phonetic-static) = +in(sin_phonetic):3 * syr(basic) = +sy(syc):3 * syr(phonetic) = +sy(syc_phonetic):3 * tam(INSCRIPT) = +in(tam):3 * tam(UNI) = +in(tam_unicode):3 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):3 * tam(TAB) = +in(tam_TAB):3 * tam(TSCII) = +in(tam_TSCII):3 * tel(basic) = +in(tel):3 * yu(basic) = +srp(latin):3 * yu(unicode) = +srp(latinunicode):3 * yu(yz) = +srp(latinyz):3 * yu(unicodeyz) = +srp(latinunicodeyz):3 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):3 nokiarx51 * = +nokia_vndr/rx-51(%l[3]%_v[3]):3 $sun $sun_custom = +sun_vndr/%l[3]%(v[3]):3 * * = +%l[3]%(v[3]):3 ! model layout[4] = symbols * ar = +ara%(v[4]):4 * ben = +in(ben):4 * bs = +ba%(v[4]):4 * cs = +rs%(v[4]):4 * cz_qwerty = +cz(qwerty):4 * dev = +in(deva):4 * dvorak = +us(dvorak):4 * dzdwi = +bt%(v[4]):4 * el = +gr%(v[4]):4 * en_US = +latin%(v[4]):4 * guj = +in(guj):4 * gur = +in(guru):4 * iu = +ca(ike):4 * lo = +la%(v[4]):4 * kan = +in(kan):4 * mi = +mao%(v[4]):4 * ogham = +ie(ogam):4 * ori = +ie(ori):4 * sapmi = +no(smi):4 * sr = +srp%(v[4]):4 * syr = +sy(syc):4 * tel = +in(tel):4 * tml = +in(tam):4 * yu = +srp%(v[4]):4 * fr-latin9 = +fr(latin9):4 * us_intl = +us(alt-intl):4 * ben(basic) = +in(ben):4 * ben(probhat) = +in(ben_probhat):4 * dev(basic) = +in(deva):4 * dvorak($dvoraklayouts) = +%v(dvorak):4 * dvorak(basic) = +us(dvorak):4 * dvorak(pl_basic) = +pl(dvorak):4 * dvorak(pl) = +pl(dvorak_quotes):4 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):4 * dzdwi(basic) = +bt(basic):4 * fi(basic) = +fi(classic):4 * ge(azerty_tskapo) = +fr(geo):4 * guj(basic) = +in(guj):4 * gur(basic) = +in(guru):4 * ie(laptop) = +ie(basic):4 * ie(CloGaelachLaptop) = +ie(CloGaelach):4 * in(urd) = +in(urd-phonetic):4 * iu(basic) = +ca(ike):4 * lo(basic) = +la(basic):4 * kan(basic) = +in(kan):4 * mal(basic) = +in(mal):4 * mal(mlplusnum) = +in(mal):4 * ogham(basic) = +ie(ogam):4 * ogham(laptop) = +ie(ogam):4 * ogham(is434) = +ie(ogam_is434):4 * ogham(is434laptop) = +ie(ogam_is434):4 * ori(basic) = +in(ori):4 * ro(de) = +ro(winkeys):4 * ro(us) = +ro(std):4 * ro(academic) = +ro(std):4 * ro(std_comma) = +ro(std):4 * ro(comma) = +ro(basic):4 * ru(os) = +ru(os_legacy):4 * pk(urd) = +pk(urd-phonetic):4 * sapmi(basic) = +no(smi):4 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):4 * sapmi(sefi) = +fi(smi):4 * sin(phonetic-static) = +in(sin_phonetic):4 * syr(basic) = +sy(syc):4 * syr(phonetic) = +sy(syc_phonetic):4 * tam(INSCRIPT) = +in(tam):4 * tam(UNI) = +in(tam_unicode):4 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):4 * tam(TAB) = +in(tam_TAB):4 * tam(TSCII) = +in(tam_TSCII):4 * tel(basic) = +in(tel):4 * yu(basic) = +srp(latin):4 * yu(unicode) = +srp(latinunicode):4 * yu(yz) = +srp(latinyz):4 * yu(unicodeyz) = +srp(latinunicodeyz):4 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):4 nokiarx51 * = +nokia_vndr/rx-51(%l[4]%_v[4]):4 $sun $sun_custom = +sun_vndr/%l[4]%(v[4]):4 * * = +%l[4]%(v[4]):4 ! model layout[2] variant[2] = symbols * ben basic = +in(ben):2 * ben probhat = +in(ben_probhat):2 * dev basic = +in(deva):2 * dvorak $dvoraklayouts = +%v(dvorak):2 * dvorak basic = +us(dvorak):2 * dvorak pl_basic = +pl(dvorak):2 * dvorak pl = +pl(dvorak_quotes):2 * dvorak pl_altquotes = +pl(dvorak_altquotes):2 * dzdwi basic = +bt(basic):2 * fi basic = +fi(classic):2 * ge azerty_tskapo = +fr(geo):2 * guj basic = +in(guj):2 * gur basic = +in(guru):2 * ie laptop = +ie(basic):2 * ie CloGaelachLaptop = +ie(CloGaelach):2 * in urd = +in(urd-phonetic):2 * iu basic = +ca(ike):2 * lo basic = +la(basic):2 * kan basic = +in(kan):2 * mal basic = +in(mal):2 * mal mlplusnum = +in(mal):2 * ogham basic = +ie(ogam):2 * ogham laptop = +ie(ogam):2 * ogham is434 = +ie(ogam_is434):2 * ogham is434laptop = +ie(ogam_is434):2 * ori basic = +in(ori):2 * ro de = +ro(winkeys):2 * ro us = +ro(std):2 * ro academic = +ro(std):2 * ro std_comma = +ro(std):2 * ro comma = +ro(basic):2 * ru os = +ru(os_legacy):2 * pk urd = +pk(urd-phonetic):2 * sapmi basic = +no(smi):2 * sapmi nodeadkeys = +no(smi_nodeadkeys):2 * sapmi sefi = +fi(smi):2 * sin phonetic-static = +in(sin_phonetic):2 * syr basic = +sy(syc):2 * syr phonetic = +sy(syc_phonetic):2 * tam INSCRIPT = +in(tam):2 * tam UNI = +in(tam_unicode):2 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):2 * tam TAB = +in(tam_TAB):2 * tam TSCII = +in(tam_TSCII):2 * tel basic = +in(tel):2 * yu basic = +srp(latin):2 * yu unicode = +srp(latinunicode):2 * yu yz = +srp(latinyz):2 * yu unicodeyz = +srp(latinunicodeyz):2 ! model layout[3] variant[3] = symbols * ben basic = +in(ben):3 * ben probhat = +in(ben_probhat):3 * dev basic = +in(deva):3 * dvorak $dvoraklayouts = +%v(dvorak):3 * dvorak basic = +us(dvorak):3 * dvorak pl_basic = +pl(dvorak):3 * dvorak pl = +pl(dvorak_quotes):3 * dvorak pl_altquotes = +pl(dvorak_altquotes):3 * dzdwi basic = +bt(basic):3 * fi basic = +fi(classic):3 * ge azerty_tskapo = +fr(geo):3 * guj basic = +in(guj):3 * gur basic = +in(guru):3 * ie laptop = +ie(basic):3 * ie CloGaelachLaptop = +ie(CloGaelach):3 * in urd = +in(urd-phonetic):3 * iu basic = +ca(ike):3 * lo basic = +la(basic):3 * kan basic = +in(kan):3 * mal basic = +in(mal):3 * mal mlplusnum = +in(mal):3 * ogham basic = +ie(ogam):3 * ogham laptop = +ie(ogam):3 * ogham is434 = +ie(ogam_is434):3 * ogham is434laptop = +ie(ogam_is434):3 * ori basic = +in(ori):3 * ro de = +ro(winkeys):3 * ro us = +ro(std):3 * ro academic = +ro(std):3 * ro std_comma = +ro(std):3 * ro comma = +ro(basic):3 * ru os = +ru(os_legacy):3 * pk urd = +pk(urd-phonetic):3 * sapmi basic = +no(smi):3 * sapmi nodeadkeys = +no(smi_nodeadkeys):3 * sapmi sefi = +fi(smi):3 * sin phonetic-static = +in(sin_phonetic):3 * syr basic = +sy(syc):3 * syr phonetic = +sy(syc_phonetic):3 * tam INSCRIPT = +in(tam):3 * tam UNI = +in(tam_unicode):3 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):3 * tam TAB = +in(tam_TAB):3 * tam TSCII = +in(tam_TSCII):3 * tel basic = +in(tel):3 * yu basic = +srp(latin):3 * yu unicode = +srp(latinunicode):3 * yu yz = +srp(latinyz):3 * yu unicodeyz = +srp(latinunicodeyz):3 ! model layout[4] variant[4] = symbols * ben basic = +in(ben):4 * ben probhat = +in(ben_probhat):4 * dev basic = +in(deva):4 * dvorak $dvoraklayouts = +%v(dvorak):4 * dvorak basic = +us(dvorak):4 * dvorak pl_basic = +pl(dvorak):4 * dvorak pl = +pl(dvorak_quotes):4 * dvorak pl_altquotes = +pl(dvorak_altquotes):4 * dzdwi basic = +bt(basic):4 * fi basic = +fi(classic):4 * ge azerty_tskapo = +fr(geo):4 * guj basic = +in(guj):4 * gur basic = +in(guru):4 * ie laptop = +ie(basic):4 * ie CloGaelachLaptop = +ie(CloGaelach):4 * in urd = +in(urd-phonetic):4 * iu basic = +ca(ike):4 * lo basic = +la(basic):4 * kan basic = +in(kan):4 * mal basic = +in(mal):4 * mal mlplusnum = +in(mal):4 * ogham basic = +ie(ogam):4 * ogham laptop = +ie(ogam):4 * ogham is434 = +ie(ogam_is434):4 * ogham is434laptop = +ie(ogam_is434):4 * ori basic = +in(ori):4 * ro de = +ro(winkeys):4 * ro us = +ro(std):4 * ro academic = +ro(std):4 * ro std_comma = +ro(std):4 * ro comma = +ro(basic):4 * ru os = +ru(os_legacy):4 * pk urd = +pk(urd-phonetic):4 * sapmi basic = +no(smi):4 * sapmi nodeadkeys = +no(smi_nodeadkeys):4 * sapmi sefi = +fi(smi):4 * sin phonetic-static = +in(sin_phonetic):4 * syr basic = +sy(syc):4 * syr phonetic = +sy(syc_phonetic):4 * tam INSCRIPT = +in(tam):4 * tam UNI = +in(tam_unicode):4 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):4 * tam TAB = +in(tam_TAB):4 * tam TSCII = +in(tam_TSCII):4 * tel basic = +in(tel):4 * yu basic = +srp(latin):4 * yu unicode = +srp(latinunicode):4 * yu yz = +srp(latinyz):4 * yu unicodeyz = +srp(latinunicodeyz):4 ! model = symbols a4techKB21 = +inet(media_nav_common) a4techKBS8 = +inet(media_nav_acpi_common) a4_rfkb23 = +inet(media_nav_acpi_common) asus_laptop = +inet(media_common) acer_tm_800 = +inet(acer_laptop) benqx730 = +inet(benqx) benqx800 = +inet(benqx) btc5126t = +inet(nav_acpi_common) btc9116u = +inet(btc9019u) btc6301urf = +inet(media_nav_acpi_common) chromebook = +inet(chromebook) dellsk8125 = +inet(dell) dellsk8135 = +inet(dell) cherrybunlim = +inet(nav_common) dexxa = +inet(media_nav_common) dtk2000 = +inet(media_nav_acpi_common) fscaa1667g = +inet(media_nav_common) geniuskb19e = +inet(media_nav_acpi_common) geniuscomfy = +inet(media_nav_acpi_common) geniuskkb2050hs = +inet(dellusbmm) hpnx9020 = +inet(hpi6) latitude = +inet(media_common) logicd = +inet(logitech_base) logicd_it = +inet(logitech_base) logicd_nav = +inet(logitech_base) logicd_opt = +inet(logitech_base) logiultrax = +inet(logitech_base) logiclx300 = +inet(logiex110) logii350 = +inet(logiex110) logimel = +inet(logiex110) logicdit = +inet(logicd) logicdo = +inet(logicd) logicdp = +inet(logicd) logicdpa = +inet(logicda) logiciink = +inet(logicink) ltcd = +inet(logicda) microsoftccurve2k = +inet(microsoftprooem) microsoftpro = +inet(media_nav_acpi_common) precision_m = +inet(media_nav_common) scorpius = +inet(media_nav_acpi_common) sp_inet = +inet(media_nav_acpi_common) targa_v811 = +inet(media_nav_acpi_common) thinkpad = +inet(media_nav_common) thinkpadz60 = +inet(thinkpad60) tm2030USB-102 = +inet(media_nav_acpi_common) tm2030USB-106 = +inet(media_nav_acpi_common) trust_slimline = +inet(media_nav_acpi_common) vsonku306 = +inet(microsoftprooem) $inetkbds = +inet(%m) $maclaptop = +inet(apple)+level3(enter_switch) $applealu = +inet(apple) $macs = +inet(apple) sun_type7_jp_usb = +sun_vndr/solaris(defaults_type7jp) $sun = +sun_vndr/solaris(defaults) ! model layout = symbols $inetmediakbds jp = +jp(henkan) ! layout variant = compat de neo = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de adnw = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de koy = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de bone = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de bone_eszett_home = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de neo_qwertz = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de neo_qwerty = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) jp $sun_compat = complete+japan(kana_lock) ! layout[1] variant[1] = compat de neo = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de adnw = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de koy = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de bone = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de bone_eszett_home = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de neo_qwertz = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de neo_qwerty = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) jp $sun_compat = complete+japan(kana_lock) ! layout[2] variant[2] = compat de neo = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de adnw = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de koy = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de bone = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de bone_eszett_home = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de neo_qwertz = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de neo_qwerty = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 jp $sun_compat = +complete+japan(kana_lock):2 ! layout[3] variant[3] = compat de neo = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de adnw = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de koy = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de bone = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de bone_eszett_home = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de neo_qwertz = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de neo_qwerty = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 jp $sun_compat = +complete+japan(kana_lock):3 ! layout[4] variant[4] = compat de neo = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de adnw = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de koy = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de bone = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de bone_eszett_home = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de neo_qwertz = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de neo_qwerty = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 jp $sun_compat = +complete+japan(kana_lock):4 ! model layout = compat pc98 nec_vndr/jp = pc98(basic) * jp = complete+japan olpc * = olpc olpcm * = olpc * * = complete ! model layout[1] = compat * * = complete ! model = types $macs = complete+numpad(mac) $applealu = complete+numpad(mac) $nokiamodels = complete+nokia * = complete ! layout option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle) * misc:typo = +typo(base) * misc:apl = +apl(level3) ! layout[1] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):1 * misc:typo = +typo(base):1 * misc:apl = +apl(level3):1 ! layout[2] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):2 * misc:typo = +typo(base):2 * misc:apl = +apl(level3):2 ! layout[3] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):3 * misc:typo = +typo(base):3 * misc:apl = +apl(level3):3 ! layout[4] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):4 * misc:typo = +typo(base):4 * misc:apl = +apl(level3):4 ! option = symbols grp:shift_toggle = +group(shifts_toggle) altwin:menu = +altwin(menu) altwin:menu_win = +altwin(menu_win) altwin:meta_alt = +altwin(meta_alt) altwin:alt_win = +altwin(alt_win) altwin:ctrl_win = +altwin(ctrl_win) altwin:ctrl_alt_win = +altwin(ctrl_alt_win) altwin:meta_win = +altwin(meta_win) altwin:left_meta_win = +altwin(left_meta_win) altwin:hyper_win = +altwin(hyper_win) altwin:alt_super_win = +altwin(alt_super_win) altwin:swap_lalt_lwin = +altwin(swap_lalt_lwin) altwin:swap_alt_win = +altwin(swap_alt_win) altwin:prtsc_rwin = +altwin(prtsc_rwin) grab:debug = +srvr_ctrl(grab_debug) grp:switch = +group(switch) grp:lswitch = +group(lswitch) grp:win_switch = +group(win_switch) grp:lwin_switch = +group(lwin_switch) grp:rwin_switch = +group(rwin_switch) grp:menu_switch = +group(menu_switch) grp:toggle = +group(toggle) grp:shifts_toggle = +group(shifts_toggle) grp:ctrls_toggle = +group(ctrls_toggle) grp:alts_toggle = +group(alts_toggle) grp:caps_toggle = +capslock(grouplock) grp:caps_switch = +capslock(groupshift) grp:shift_caps_toggle = +group(shift_caps_toggle) grp:shift_caps_switch = +group(shift_caps_switch) grp:win_space_toggle = +group(win_space_toggle) grp:win_menu_switch = +group(win_menu_switch) grp:alt_caps_toggle = +group(alt_caps_toggle) grp:alt_space_toggle = +group(alt_space_toggle) grp:menu_toggle = +group(menu_toggle) grp:lwin_toggle = +group(lwin_toggle) grp:rwin_toggle = +group(rwin_toggle) grp:lshift_toggle = +group(lshift_toggle) grp:rshift_toggle = +group(rshift_toggle) grp:rctrl_switch = +group(rctrl_switch) grp:lctrl_toggle = +group(lctrl_toggle) grp:rctrl_toggle = +group(rctrl_toggle) grp:lalt_toggle = +group(lalt_toggle) grp:sclk_toggle = +group(sclk_toggle) grp:lctrl_rctrl_switch = +group(lctrl_rctrl_switch) grp:lctrl_lwin_rctrl_menu = +group(lctrl_lwin_rctrl_menu) grp:lctrl_lalt_toggle = +group(lctrl_lalt_toggle) grp:rctrl_ralt_toggle = +group(rctrl_ralt_toggle) grp:ctrl_alt_toggle = +group(ctrl_alt_toggle) grp:ctrl_alt_toggle_bidir = +group(ctrl_alt_toggle_bidir) grp:lctrl_lshift_toggle = +group(lctrl_lshift_toggle) grp:rctrl_rshift_toggle = +group(rctrl_rshift_toggle) grp:ctrl_shift_toggle = +group(ctrl_shift_toggle) grp:ctrl_shift_toggle_bidir = +group(ctrl_shift_toggle_bidir) grp:lalt_lshift_toggle = +group(lalt_lshift_toggle) grp:ralt_rshift_toggle = +group(ralt_rshift_toggle) grp:alt_shift_toggle = +group(alt_shift_toggle) grp:alt_shift_toggle_bidir = +group(alt_shift_toggle_bidir) grp:lctrl_lwin_toggle = +group(lctrl_lwin_toggle) lv3:switch = +level3(switch) lv3:ralt_switch = +level3(ralt_switch) lv3:ralt_switch_multikey = +level3(ralt_switch_multikey) lv3:ralt_alt = +level3(ralt_alt) lv3:lalt_switch = +level3(lalt_switch) lv3:alt_switch = +level3(alt_switch) lv3:menu_switch = +level3(menu_switch) lv3:win_switch = +level3(win_switch) lv3:lwin_switch = +level3(lwin_switch) lv3:rwin_switch = +level3(rwin_switch) lv3:enter_switch = +level3(enter_switch) lv3:4_switch_isolated = +level3(4_switch_isolated) lv3:9_switch_isolated = +level3(9_switch_isolated) caps:capslock = +capslock(capslock) caps:numlock = +capslock(numlock) caps:shiftlock = +capslock(shiftlock) caps:swapescape = +capslock(swapescape) caps:escape = +capslock(escape) caps:escape_shifted_capslock = +capslock(escape_shifted_capslock) caps:backspace = +capslock(backspace) caps:super = +capslock(super) caps:hyper = +capslock(hyper) caps:menu = +capslock(menu) caps:none = +capslock(none) caps:ctrl_modifier = +capslock(ctrl_modifier) ctrl:nocaps = +ctrl(nocaps) ctrl:lctrl_meta = +ctrl(lctrl_meta) ctrl:swapcaps = +ctrl(swapcaps) ctrl:swapcaps_hyper = +ctrl(swapcaps_hyper) ctrl:swapcaps_and_switch_layout = +ctrl(swapcaps_and_switch_layout) ctrl:ac_ctrl = +ctrl(ac_ctrl) ctrl:aa_ctrl = +ctrl(aa_ctrl) ctrl:rctrl_ralt = +ctrl(rctrl_ralt) ctrl:menu_rctrl = +ctrl(menu_rctrl) ctrl:ralt_rctrl = +ctrl(ralt_rctrl) ctrl:swap_lalt_lctl = +ctrl(swap_lalt_lctl) ctrl:swap_lwin_lctl = +ctrl(swap_lwin_lctl) ctrl:swap_rwin_rctl = +ctrl(swap_rwin_rctl) ctrl:swap_lalt_lctl_lwin = +ctrl(swap_lalt_lctl_lwin) compose:ralt = +compose(ralt) compose:lwin = +compose(lwin) compose:lwin-altgr = +compose(lwin-altgr) compose:rwin = +compose(rwin) compose:rwin-altgr = +compose(rwin-altgr) compose:menu = +compose(menu) compose:menu-altgr = +compose(menu-altgr) compose:lctrl = +compose(lctrl) compose:lctrl-altgr = +compose(lctrl-altgr) compose:rctrl = +compose(rctrl) compose:rctrl-altgr = +compose(rctrl-altgr) compose:caps = +compose(caps) compose:caps-altgr = +compose(caps-altgr) compose:102 = +compose(102) compose:102-altgr = +compose(102-altgr) compose:paus = +compose(paus) compose:prsc = +compose(prsc) compose:sclk = +compose(sclk) srvrkeys:none = +srvr_ctrl(no_srvr_keys) eurosign:e = +eurosign(e) eurosign:2 = +eurosign(2) eurosign:4 = +eurosign(4) eurosign:5 = +eurosign(5) rupeesign:4 = +rupeesign(4) keypad:oss = +keypad(oss) keypad:legacy = +keypad(legacy) keypad:legacy_wang = +keypad(legacy_wang) keypad:oss_wang = +keypad(oss_wang) keypad:future = +keypad(future) keypad:future_wang = +keypad(future_wang) keypad:hex = +keypad(ops)+keypad(hex) keypad:atm = +keypad(ops)+keypad(hex)+keypad(atm) nbsp:none = +nbsp(none) nbsp:level2 = +nbsp(level2) nbsp:level3 = +nbsp(level3) nbsp:level3s = +nbsp(level3s) nbsp:level3n = +nbsp(level3n) nbsp:level4 = +nbsp(level4) nbsp:level4n = +nbsp(level4n) nbsp:level4nl = +nbsp(level4nl) nbsp:zwnj2 = +nbsp(zwnj2) nbsp:zwnj2zwj3 = +nbsp(zwnj2zwj3) nbsp:zwnj2zwj3nb4 = +nbsp(zwnj2zwj3nb4) nbsp:zwnj2nb3 = +nbsp(zwnj2nb3) nbsp:zwnj2nb3s = +nbsp(zwnj2nb3s) nbsp:zwnj2nb3zwj4 = +nbsp(zwnj2nb3zwj4) nbsp:zwnj2nb3nnb4 = +nbsp(zwnj2nb3nnb4) nbsp:zwnj3zwj4 = +nbsp(zwnj3zwj4) japan:nicola_f_bs = +jp(nicola_f_bs) japan:hztg_escape = +jp(hztg_escape) korean:ralt_hangul = +kr(ralt_hangul) korean:rctrl_hangul = +kr(rctrl_hangul) korean:ralt_hanja = +kr(ralt_hanja) korean:rctrl_hanja = +kr(rctrl_hanja) kpdl:dot = +kpdl(dot) kpdl:comma = +kpdl(comma) kpdl:dotoss = +kpdl(dotoss) kpdl:dotoss_latin9 = +kpdl(dotoss_latin9) kpdl:commaoss = +kpdl(commaoss) kpdl:momayyezoss = +kpdl(momayyezoss) kpdl:kposs = +kpdl(kposs) kpdl:semi = +kpdl(semi) shift:breaks_caps = +shift(breaks_caps) esperanto:qwerty = +epo(qwerty) esperanto:dvorak = +epo(dvorak) esperanto:colemak = +epo(colemak) terminate:ctrl_alt_bksp = +terminate(ctrl_alt_bksp) keypad:pointerkeys = +keypad(pointerkeys) apple:alupckeys = +macintosh_vndr/apple(alupckeys) shift:both_capslock = +shift(both_capslock) shift:lshift_both_capslock = +shift(lshift_both_capslock) shift:rshift_both_capslock = +shift(rshift_both_capslock) shift:both_capslock_cancel = +shift(both_capslock_cancel) shift:lshift_both_capslock_cancel = +shift(lshift_both_capslock_cancel) shift:rshift_both_capslock_cancel = +shift(rshift_both_capslock_cancel) shift:both_shiftlock = +shift(both_shiftlock) shift:lshift_both_shiftlock = +shift(lshift_both_shiftlock) shift:rshift_both_shiftlock = +shift(rshift_both_shiftlock) solaris:sun_compat = +sun_vndr/solaris(sun_compat) lv3:caps_switch = +level3(caps_switch) lv3:bksl_switch = +level3(bksl_switch) lv3:lsgt_switch = +level3(lsgt_switch) lv3:caps_switch_latch = +level3(caps_switch_latch) lv3:bksl_switch_latch = +level3(bksl_switch_latch) lv3:lsgt_switch_latch = +level3(lsgt_switch_latch) lv5:lsgt_switch = +level5(lsgt_switch) lv5:ralt_switch = +level5(ralt_switch) lv5:lsgt_switch_lock = +level5(lsgt_switch_lock) lv5:ralt_switch_lock = +level5(ralt_switch_lock) lv5:lwin_switch_lock = +level5(lwin_switch_lock) lv5:rwin_switch_lock = +level5(rwin_switch_lock) lv5:lsgt_switch_lock_cancel = +level5(lsgt_switch_lock_cancel) lv5:ralt_switch_lock_cancel = +level5(ralt_switch_lock_cancel) lv5:lwin_switch_lock_cancel = +level5(lwin_switch_lock_cancel) lv5:rwin_switch_lock_cancel = +level5(rwin_switch_lock_cancel) parens:swap_brackets = +parens(swap_brackets) ! option = compat grp_led:num = +lednum(group_lock) grp_led:caps = +ledcaps(group_lock) grp_led:scroll = +ledscroll(group_lock) mod_led:compose = +ledcompose(compose) japan:kana_lock = +japan(kana_lock) caps:shiftlock = +ledcaps(shift_lock) grab:break_actions = +xfree86(grab_break) ! option = types caps:internal = +caps(internal) caps:internal_nocancel = +caps(internal_nocancel) caps:shift = +caps(shift) caps:shift_nocancel = +caps(shift_nocancel) numpad:pc = +numpad(pc) numpad:mac = +numpad(mac) numpad:microsoft = +numpad(microsoft) numpad:shift3 = +numpad(shift3) xkbcommon-libxkbcommon-54ee7ac/test/data/rules/base.extras.xml000066400000000000000000001255261510033435100246610ustar00rootroot00000000000000 apl apl APL eng dyalog dlg APL symbols (Dyalog APL) sax sax APL symbols (SAX, Sharp APL for Unix) unified ufd APL symbols (unified) apl2 apl2 APL symbols (IBM APL2) aplplusII aplII APL symbols (Manugistics APL*PLUS II) aplx aplx APL symbols (APLX unified) ca fr French (Canada) fra kut kut Kutenai shs shs Secwepemctsin sun_type6 Multilingual (Canada, Sun Type 6/7) de de German ger us German (US) eng hu German (with Hungarian letters, no dead keys) ger hun pl Polish (Germany, no dead keys) ger pol sun_type6 German (Sun Type 6/7) adnw German (Aus der Neo-Welt) koy German (KOY) bone German (Bone) bone_eszett_home German (Bone, eszett in the home row) neo_qwertz German (Neo, QWERTZ) neo_qwerty German (Neo, QWERTY) ru-recom ru Russian (Germany, recommended) rus ru-translit ru Russian (Germany, transliteration) rus lld de_lld German (Ladin) ger lld eg ⲕⲏⲙⲉ Coptic cop egy hu Hungarian oldhun oldhun Old Hungarian ohu_lig ohu_lig Old Hungarian (for ligatures) ir fa Persian per ave Avestan ave lt lt Lithuanian lit us_dvorak Lithuanian (Dvorak) sun_type6 Lithuanian (Sun Type 6/7) lv lv Latvian lav dvorak Latvian (Dvorak) ykeydvorak Latvian (Dvorak, with Y) minuskeydvorak Latvian (Dvorak, with minus) dvorakprogr Latvian (programmer Dvorak) ykeydvorakprogr Latvian (programmer Dvorak, with Y) minuskeydvorakprogr Latvian (programmer Dvorak, with minus) colemak Latvian (Colemak) apostrophecolemak Latvian (Colemak, with apostrophe) sun_type6 Latvian (Sun Type 6/7) us en English (US) eng intl-unicode English (US, intl., AltGr Unicode combining) alt-intl-unicode English (US, intl., AltGr Unicode combining, alt.) ats Atsina crd Coeur d'Alene Salish crd cz_sk_de Czech Slovak and German (US) eng cze slo ger drix English (Drix) de_se_fi German, Swedish and Finnish (US) eng ger swe fin ibm238l English (US, IBM Arabic 238_L) sun_type6 English (US, Sun Type 6/7) carpalx English (Carpalx) carpalx-intl English (Carpalx, intl., with dead keys) carpalx-altgr-intl English (Carpalx, intl., with AltGr dead keys) carpalx-full English (Carpalx, full optimization) carpalx-full-intl English (Carpalx, full optimization, intl., with dead keys) carpalx-full-altgr-intl English (Carpalx, full optimization, intl., with AltGr dead keys) 3l English (3l) 3l-cros English (3l, Chromebook) 3l-emacs English (3l, emacs) scn Sicilian (US keyboard) eng ita scn pl pl Polish pol intl Polish (intl., with dead keys) colemak Polish (Colemak) sun_type6 Polish (Sun Type 6/7) glagolica Polish (Glagolica) ro ro Romanian rum crh_dobruja crh Crimean Tatar (Dobruja Q) crh ergonomic Romanian (ergonomic Touchtype) sun_type6 Romanian (Sun Type 6/7) rs sr Serbian srp combiningkeys Serbian (combining accents instead of dead keys) ru ru Russian chu Church Slavonic chu ruu ru Russian (with Ukrainian-Belorussian layout) rus ukr bel rulemak Russian (Rulemak, phonetic Colemak) phonetic_mac Russian (phonetic Macintosh) sun_type6 Russian (Sun Type 6/7) unipunct Russian (with US punctuation) prxn ru Russian (Polyglot and Reactionary) RU RS BA ME MK BG MD UA BY KZ MN KG TJ UZ TM AZ rus rus-petr1708 ukr bel srp mkd bul chu rum-Cyrl kaz kir uzb bak aze tat uig kdr tyv kjh crh tgk abk sah mon kal sjd chv oss krl ale wbl kur niv dng kom udm sel ulc ude oac oaa gld eve evn kca itl yrk neg am hy Armenian hye olpc-phonetic Armenian (OLPC, phonetic) il he Hebrew heb biblicalSIL Hebrew (Biblical, SIL phonetic) heb ara ar Arabic sun_type6 Arabic (Sun Type 6/7) basic_ext Arabic (Arabic numerals, extensions in the 4th level) basic_ext_digits Arabic (Eastern Arabic numerals, extensions in the 4th level) uga Ugaritic instead of Arabic be be Belgian sun_type6 Belgian (Sun Type 6/7) br pt Portuguese (Brazil) sun_type6 Portuguese (Brazil, Sun Type 6/7) cz cs Czech sun_type6 Czech (Sun Type 6/7) prog Czech (programming) typo Czech (typographic) coder Czech (coder) prog_typo Czech (programming, typographic) dk da Danish sun_type6 Danish (Sun Type 6/7) nl nl Dutch sun_type6 Dutch (Sun Type 6/7) ee et Estonian sun_type6 Estonian (Sun Type 6/7) fi fi Finnish sun_type6 Finnish (Sun Type 6/7) das Finnish (DAS) fidvorak Finnish (Dvorak) fr fr French sun_type6 French (Sun Type 6/7) us-alt French (US with dead keys, alt.) us-azerty French (US, AZERTY) gr gr Greek sun_type6 Greek (Sun Type 6/7) colemak Greek (Colemak) it it Italian sun_type6 Italian (Sun Type 6/7) lld it_lld Italian (Ladin) it lld jp ja Japanese sun_type6 Japanese (Sun Type 6) sun_type7 Japanese (Sun Type 7, PC-compatible) sun_type7_suncompat Japanese (Sun Type 7, Sun-compatible) no no Norwegian sun_type6 Norwegian (Sun Type 6/7) pt pt Portuguese sun_type6 Portuguese (Sun Type 6/7) pt pt Portuguese colemak Portuguese (Colemak) sk sk Slovak acc Slovak (ACC layout, only accented letters) sun_type6 Slovak (Sun Type 6/7) es es Spanish sun_type6 Spanish (Sun Type 6/7) se sv Swedish dvorak_a5 Swedish (Dvorak A5) sun_type6 Swedish (Sun Type 6/7) ovd Elfdalian (Swedish, with combining ogonek) ovd ch de German (Switzerland) sun_type6_de German (Switzerland, Sun Type 6/7) sun_type6_fr French (Switzerland, Sun Type 6/7) tr tr Turkish sun_type6 Turkish (Sun Type 6/7) ua uk Ukrainian sun_type6 Ukrainian (Sun Type 6/7) gb en English (UK) sun_type6 English (UK, Sun Type 6/7) kr ko Korean sun_type6 Korean (Sun Type 6/7) vn vi Vietnamese vie aderty Vietnamese (AÐERTY) qderty Vietnamese (QĐERTY) eu eu EurKEY (US) cat dan eng est fao fin ger gre gsw ita lav lit nld nor por spa swe cm cm English (Cameroon) mmuock Mmuock trans International Phonetic Alphabet in in Indian modi-kagapa mr Modi (KaGaPa phonetic) mar lv3 Key to choose the 3rd level parens Parentheses position xkbcommon-libxkbcommon-54ee7ac/test/data/rules/base.xml000066400000000000000000007133111510033435100233470ustar00rootroot00000000000000 pc86 Generic 86-key PC Generic pc101 Generic 101-key PC Generic pc102 Generic 102-key PC Generic pc104 Generic 104-key PC Generic pc104alt Generic 104-key PC with L-shaped Enter key Generic pc105 Generic 105-key PC Generic dell101 Dell 101-key PC Dell latitude Dell Latitude laptop Dell dellm65 Dell Precision M65 laptop Dell everex Everex STEPnote Everex flexpro Keytronic FlexPro Keytronic microsoft Microsoft Natural Microsoft omnikey101 Northgate OmniKey 101 Northgate winbook Winbook Model XP5 Generic pc98 PC-98 Generic a4techKB21 A4Tech KB-21 A4Tech a4techKBS8 A4Tech KBS-8 A4Tech a4_rfkb23 A4Tech Wireless Desktop RFKB-23 A4Tech airkey Acer AirKey V Acer azonaRF2300 Azona RF2300 wireless Internet Azona scorpius Advance Scorpius KI Scorpius brother Brother Internet Brother btc5113rf BTC 5113RF Multimedia BTC btc5126t BTC 5126T BTC btc6301urf BTC 6301URF BTC btc9000 BTC 9000 BTC btc9000a BTC 9000A BTC btc9001ah BTC 9001AH BTC btc5090 BTC 5090 BTC btc9019u BTC 9019U BTC btc9116u BTC 9116U Mini Wireless Internet and Gaming cherryblue Cherry Blue Line CyBo@rd cherryblueb Cherry CyMotion Master XPress Cherry cherrybluea Cherry Blue Line CyBo@rd (alt.) Cherry cherrycyboard Cherry CyBo@rd USB-Hub Cherry cherrycmexpert Cherry CyMotion Expert Cherry cherrybunlim Cherry B.UNLIMITED Cherry chicony Chicony Internet Chicony chicony0108 Chicony KU-0108 Chicony chicony0420 Chicony KU-0420 Chicony chicony9885 Chicony KB-9885 Chicony compaqeak8 Compaq Easy Access Compaq compaqik7 Compaq Internet (7 keys) Compaq compaqik13 Compaq Internet (13 keys) Compaq compaqik18 Compaq Internet (18 keys) Compaq cymotionlinux Cherry CyMotion Master Linux Cherry armada Compaq Armada laptop Compaq presario Compaq Presario laptop Compaq ipaq Compaq iPaq Compaq dell Dell Dell dellsk8125 Dell SK-8125 Dell dellsk8135 Dell SK-8135 Dell dellusbmm Dell USB Multimedia Dell inspiron Dell Inspiron 6000/8000 laptop Dell precision_m Dell Precision M laptop Dell dexxa Dexxa Wireless Desktop Dexxa diamond Diamond 9801/9802 Diamond dtk2000 DTK2000 ennyah_dkb1008 Ennyah DKB-1008 Ennyah fscaa1667g Fujitsu-Siemens Amilo laptop Fujitsu-Siemens genius Genius Comfy KB-16M/Multimedia KWD-910 Genius geniuscomfy Genius Comfy KB-12e Genius geniuscomfy2 Genius Comfy KB-21e-Scroll Genius geniuskb19e Genius KB-19e NB Genius geniuskkb2050hs Genius KKB-2050HS Genius gyration Gyration Gyration kinesis Kinesis Kinesis logitech_base Logitech Logitech logitech_g15 Logitech G15 extra keys via G15daemon Logitech hpi6 Hewlett-Packard Internet Hewlett-Packard hp250x Hewlett-Packard NEC SK-2500 Multimedia Hewlett-Packard hpxe3gc Hewlett-Packard Omnibook XE3 GC Hewlett-Packard hpxe3gf Hewlett-Packard Omnibook XE3 GF Hewlett-Packard hpxt1000 Hewlett-Packard Omnibook XT1000 Hewlett-Packard hpdv5 Hewlett-Packard Pavilion dv5 Hewlett-Packard hpzt11xx Hewlett-Packard Pavilion ZT1100 Hewlett-Packard hp500fa Hewlett-Packard Omnibook 500 FA Hewlett-Packard hp5xx Hewlett-Packard Omnibook 500 Hewlett-Packard hpnx9020 Hewlett-Packard nx9020 Hewlett-Packard hp6000 Hewlett-Packard Omnibook 6000/6100 Hewlett-Packard honeywell_euroboard Honeywell Euroboard Hewlett-Packard hpmini110 Hewlett-Packard Mini 110 laptop Hewlett-Packard rapidaccess IBM Rapid Access Lenovo (previously IBM) rapidaccess2 IBM Rapid Access II Lenovo (previously IBM) thinkpad IBM ThinkPad 560Z/600/600E/A22E Lenovo (previously IBM) thinkpad60 IBM ThinkPad R60/T60/R61/T61 Lenovo (previously IBM) thinkpadz60 IBM ThinkPad Z60m/Z60t/Z61m/Z61t Lenovo (previously IBM) ibm_spacesaver IBM Space Saver Lenovo (previously IBM) logiaccess Logitech Access Logitech logiclx300 Logitech Cordless Desktop LX-300 Logitech logii350 Logitech Internet 350 Logitech 046d:c313 logimel Logitech Internet 350 Logitech logicd Logitech Cordless Desktop Logitech logicd_it Logitech Cordless Desktop iTouch Logitech logicd_nav Logitech Cordless Desktop Navigator Logitech logicd_opt Logitech Cordless Desktop Optical Logitech logicda Logitech Cordless Desktop (alt.) Logitech logicdpa2 Logitech Cordless Desktop Pro (2nd alt.) Logitech logicfn Logitech Cordless Freedom/Desktop Navigator Logitech logicdn Logitech Cordless Desktop Navigator Logitech logiitc Logitech iTouch Cordless Y-RB6 Logitech logiik Logitech Internet Logitech itouch Logitech iTouch Logitech logicink Logitech Internet Navigator Logitech logiex110 Logitech Cordless Desktop EX110 Logitech logiinkse Logitech iTouch Internet Navigator SE Logitech logiinkseusb Logitech iTouch Internet Navigator SE USB Logitech logiultrax Logitech Ultra-X Logitech logiultraxc Logitech Ultra-X Cordless Media Desktop Logitech logidinovo Logitech diNovo Logitech logidinovoedge Logitech diNovo Edge Logitech mx1998 Memorex MX1998 Memorex mx2500 Memorex MX2500 EZ-Access Memorex mx2750 Memorex MX2750 Memorex microsoft4000 Microsoft Natural Ergonomic 4000 Microsoft microsoft7000 Microsoft Natural Wireless Ergonomic 7000 Microsoft microsoftinet Microsoft Internet Microsoft microsoftpro Microsoft Natural Pro/Internet Pro Microsoft microsoftprousb Microsoft Natural Pro USB/Internet Pro Microsoft microsoftprooem Microsoft Natural Pro OEM Microsoft vsonku306 ViewSonic KU-306 Internet ViewSonic microsoftprose Microsoft Internet Pro (Swedish) Microsoft microsoftoffice Microsoft Office Keyboard Microsoft microsoftmult Microsoft Wireless Multimedia 1.0A Microsoft microsoftsurface Microsoft Surface Microsoft microsoftelite Microsoft Natural Elite Microsoft microsoftccurve2k Microsoft Comfort Curve 2000 Microsoft oretec Ortek Multimedia/Internet MCK-800 Ortek propeller Propeller Voyager KTEZ-1000 KeyTronic qtronix QTronix Scorpius 98N+ QTronix samsung4500 Samsung SDM 4500P Samsung samsung4510 Samsung SDM 4510P Samsung sanwaskbkg3 Sanwa Supply SKB-KG3 Sanwa Supply Inc. sk1300 NEC SK-1300 NEC sk2500 NEC SK-2500 NEC sk6200 NEC SK-6200 NEC sk7100 NEC SK-7100 NEC sp_inet Super Power Multimedia Generic sven SVEN Ergonomic 2500 SVEN sven303 SVEN Slim 303 SVEN symplon Symplon PaceBook tablet Symplon toshiba_s3000 Toshiba Satellite S3000 Toshiba trust Trust Wireless Classic Trust trustda Trust Direct Access Trust trust_slimline Trust Slimline Trust tm2020 TypeMatrix EZ-Reach 2020 TypeMatrix tm2030PS2 TypeMatrix EZ-Reach 2030 PS2 TypeMatrix tm2030USB TypeMatrix EZ-Reach 2030 USB TypeMatrix tm2030USB-102 TypeMatrix EZ-Reach 2030 USB (102/105:EU mode) TypeMatrix tm2030USB-106 TypeMatrix EZ-Reach 2030 USB (106:JP mode) TypeMatrix yahoo Yahoo! Internet Yahoo! macbook78 MacBook/MacBook Pro Apple macbook79 MacBook/MacBook Pro (intl.) Apple macintosh Macintosh Apple macintosh_old Macintosh Old Apple macintosh_hhk Happy Hacking for Mac Fujitsu acer_c300 Acer C300 Acer acer_ferrari4k Acer Ferrari 4000 Acer acer_laptop Acer laptop Acer asus_laptop Asus laptop Asus apple Apple Apple apple_laptop Apple laptop Apple applealu_ansi Apple Aluminium (ANSI) Apple applealu_iso Apple Aluminium (ISO) Apple applealu_jis Apple Aluminium (JIS) Apple silvercrest Silvercrest Multimedia Wireless Silvercrest emachines eMachines m6800 laptop eMachines benqx BenQ X-Touch BenQ benqx730 BenQ X-Touch 730 BenQ benqx800 BenQ X-Touch 800 BenQ hhk Happy Hacking Fujitsu classmate Classmate PC Intel olpc OLPC OLPC sun_type7_usb Sun Type 7 USB Sun Microsystems sun_type7_euro_usb Sun Type 7 USB (European) Sun Microsystems sun_type7_unix_usb Sun Type 7 USB (Unix) Sun Microsystems sun_type7_jp_usb Sun Type 7 USB (Japanese)/Japanese 106-key Sun Microsystems sun_type6_usb Sun Type 6/7 USB Sun Microsystems sun_type6_euro_usb Sun Type 6/7 USB (European) Sun Microsystems sun_type6_unix_usb Sun Type 6 USB (Unix) Sun Microsystems sun_type6_jp_usb Sun Type 6 USB (Japanese) Sun Microsystems sun_type6_jp Sun Type 6 (Japanese) Sun Microsystems targa_v811 Targa Visionary 811 Targa unitekkb1925 Unitek KB-1925 Unitek Group compalfl90 FL90 Compal Electronics creativedw7000 Creative Desktop Wireless 7000 Creative teck227 Truly Ergonomic 227 Truly Ergonomic teck229 Truly Ergonomic 229 Truly Ergonomic apex300 SteelSeries Apex 300 (Apex RAW) SteelSeries chromebook Chromebook Google teck227 Truly Ergonomic Computer Keyboard Model 227 (Wide Alt keys) Megawin Technology teck229 Truly Ergonomic Computer Keyboard Model 229 (Standard sized Alt keys, additional Super and Menu key) Megawin Technology us en English (US) eng chr chr Cherokee chr haw haw Hawaiian haw euro English (US, euro on 5) intl English (US, intl., with dead keys) alt-intl English (US, alt. intl.) colemak English (Colemak) dvorak English (Dvorak) dvorak-intl English (Dvorak, intl., with dead keys) dvorak-alt-intl English (Dvorak, alt. intl.) dvorak-l English (Dvorak, left-handed) dvorak-r English (Dvorak, right-handed) dvorak-classic English (classic Dvorak) dvp English (programmer Dvorak) rus ru Russian (US, phonetic) rus mac English (Macintosh) altgr-intl English (intl., with AltGr dead keys) eng fra deu olpc2 English (the divide/multiply toggle the layout) hbs Serbo-Croatian (US) eng bos hbs hrv srp norman English (Norman) workman English (Workman) workman-intl English (Workman, intl., with dead keys) af fa Afghani ps ps Pashto pus uz uz Uzbek (Afghanistan) uzb olpc-ps ps Pashto (Afghanistan, OLPC) pus fa-olpc fa Persian (Afghanistan, Dari OLPC) uz-olpc uz Uzbek (Afghanistan, OLPC) uzb ara ar Arabic AE BH DZ EG EH JO KW LB LY MA MR OM PS QA SA SD SY TN YE ara azerty Arabic (AZERTY) azerty_digits Arabic (AZERTY, Eastern Arabic numerals) digits Arabic (Eastern Arabic numerals) qwerty Arabic (QWERTY) qwerty_digits Arabic (QWERTY, Eastern Arabic numerals) buckwalter Arabic (Buckwalter) olpc Arabic (OLPC) mac Arabic (Macintosh) al sq Albanian sqi plisi Albanian (Plisi) veqilharxhi Albanian (Veqilharxhi) am hy Armenian hye phonetic Armenian (phonetic) phonetic-alt Armenian (alt. phonetic) eastern Armenian (eastern) western Armenian (western) eastern-alt Armenian (alt. eastern) at de German (Austria) deu nodeadkeys German (Austria, no dead keys) sundeadkeys German (Austria, Sun dead keys) mac German (Austria, Macintosh) au en English (Australian) eng az az Azerbaijani aze cyrillic Azerbaijani (Cyrillic) by by Belarusian bel legacy Belarusian (legacy) latin Belarusian (Latin) ru Russian (Belarus) intl Belarusian (intl.) be be Belgian deu nld fra oss Belgian (alt.) oss_latin9 Belgian (Latin-9 only, alt.) oss_sundeadkeys Belgian (Sun dead keys, alt.) iso-alternate Belgian (ISO, alt.) nodeadkeys Belgian (no dead keys) sundeadkeys Belgian (Sun dead keys) wang Belgian (Wang 724 AZERTY) bd bn Bangla ben sat probhat Bangla (Probhat) in in Indian ben bn Bangla (India) ben sat ben_probhat bn Bangla (India, Probhat) ben sat ben_baishakhi Bangla (India, Baishakhi) ben sat ben_bornona Bangla (India, Bornona) ben sat ben_gitanjali Bangla (India, Gitanjali) ben sat ben_inscript Bangla (India, Baishakhi Inscript) ben sat eeyek Manipuri (Eeyek) mni guj gu Gujarati guj guru pa Punjabi (Gurmukhi) pan jhelum pa Punjabi (Gurmukhi Jhelum) pan kan kn Kannada kan kan-kagapa kn Kannada (KaGaPa, phonetic) kan mal ml Malayalam mal mal_lalitha ml Malayalam (Lalitha) mal mal_enhanced ml Malayalam (enhanced Inscript, with rupee) mal ori or Oriya ori sat olck sat Ol Chiki sat tam_tamilnet ta Tamil (TamilNet '99) tam tam_tamilnet_with_tam_nums ta Tamil (TamilNet '99 with Tamil numerals) tam tam_tamilnet_TAB ta Tamil (TamilNet '99, TAB encoding) tam tam_tamilnet_TSCII ta Tamil (TamilNet '99, TSCII encoding) tam tam ta Tamil (Inscript) tam tel te Telugu tel tel-kagapa te Telugu (KaGaPa, phonetic) tel tel-sarala te Telugu (Sarala) tel tel-kagapa te Telugu (KaGaPa, phonetic) tel urd-phonetic ur Urdu (phonetic) urd urd-phonetic3 ur Urdu (alt. phonetic) urd urd-winkeys ur Urdu (Windows) urd bolnagri hi Hindi (Bolnagri) hin hin-wx hi Hindi (Wx) hin hin-kagapa hi Hindi (KaGaPa, phonetic) hin san-kagapa sa Sanskrit (KaGaPa, phonetic) san mar-kagapa mr Marathi (KaGaPa, phonetic) mar eng en English (India, with rupee) eng iipa iipa Indic IPA (IIPA) eng marathi ins मराठी इन्स्क्रिप्ट eng ba bs Bosnian bos alternatequotes Bosnian (with guillemets) unicode Bosnian (with Bosnian digraphs) unicodeus Bosnian (US, with Bosnian digraphs) us Bosnian (US) br pt Portuguese (Brazil) por nodeadkeys Portuguese (Brazil, no dead keys) dvorak Portuguese (Brazil, Dvorak) nativo Portuguese (Brazil, Nativo) nativo-us Portuguese (Brazil, Nativo for US keyboards) nativo-epo Esperanto (Brazil, Nativo) epo thinkpad Portuguese (Brazil, IBM/Lenovo ThinkPad) bg bg Bulgarian bul phonetic Bulgarian (traditional phonetic) bas_phonetic Bulgarian (new phonetic) dz kab Kabylian (azerty layout, no dead keys) azerty-deadkeys kab Kabylian (azerty layout, with dead keys) kab qwerty-gb-deadkeys kab Kabylian (qwerty-gb layout, with dead keys) kab qwerty-us-deadkeys kab Kabylian (qwerty-us layout, with dead keys) kab ber kab Kabylian (Algeria, Tifinagh) kab ar ar Arabic (Algeria) ara ma ar Arabic (Morocco) french fr French (Morocco) fra tifinagh ber Berber (Morocco, Tifinagh) ber tifinagh-alt ber Berber (Morocco, Tifinagh alt.) ber tifinagh-alt-phonetic ber Berber (Morocco, Tifinagh phonetic, alt.) ber tifinagh-extended ber Berber (Morocco, Tifinagh extended) ber tifinagh-phonetic ber Berber (Morocco, Tifinagh phonetic) ber tifinagh-extended-phonetic ber Berber (Morocco, Tifinagh extended phonetic) ber cm cm English (Cameroon) eng french French (Cameroon) fra qwerty Cameroon Multilingual (QWERTY, intl.) eng bas nmg fub ewo xmd mfh bkm ozm lns sox pny wes lem nyj mfk mcp ass xed dua anv bum btb bfd azo ken yam yat yas azerty Cameroon (AZERTY, intl.) fra bas nmg fub ewo xmd mfh bkm ozm lns sox pny wes lem nyj mfk mcp ass xed dua anv bum btb bfd azo ken yam yat yas dvorak Cameroon (Dvorak, intl.) mmuock Mmuock mm my Burmese mya zawgyi zg Burmese Zawgyi ca fr French (Canada) fra fr-dvorak fr French (Canada, Dvorak) fr-legacy fr French (Canada, legacy) multix Canadian (intl.) multi Canadian (intl., 1st part) multi-2gr Canadian (intl., 2nd part) ike ike Inuktitut iku eng en English (Canada) eng cd fr French (Democratic Republic of the Congo) fra cn zh Chinese zho mon_trad Mongolian (Bichig) mvf mon_trad_todo Mongolian (Todo) mvf mon_trad_xibe Mongolian (Xibe) sjo mon_trad_manchu Mongolian (Manchu) mnc mon_trad_galik Mongolian (Galik) mvf mon_todo_galik Mongolian (Todo Galik) mvf mon_manchu_galik Mongolian (Manchu Galik) mnc tib Tibetan tib tib_asciinum Tibetan (with ASCII numerals) tib ug ug Uyghur uig altgr-pinyin Hanyu Pinyin (with AltGr dead keys) zho hr hr Croatian hrv alternatequotes Croatian (with guillemets) unicode Croatian (with Croatian digraphs) unicodeus Croatian (US, with Croatian digraphs) us Croatian (US) cz cs Czech ces bksl Czech (with <\|> key) qwerty Czech (QWERTY) qwerty_bksl Czech (QWERTY, extended backslash) qwerty-mac Czech (QWERTY, Macintosh) ucw Czech (UCW, only accented letters) dvorak-ucw Czech (US, Dvorak, UCW support) rus ru Russian (Czech, phonetic) rus dk da Danish dan nodeadkeys Danish (no dead keys) winkeys Danish (Windows) mac Danish (Macintosh) mac_nodeadkeys Danish (Macintosh, no dead keys) dvorak Danish (Dvorak) nl nl Dutch nld sundeadkeys Dutch (Sun dead keys) mac Dutch (Macintosh) std Dutch (standard) bt dz Dzongkha dzo ee et Estonian est nodeadkeys Estonian (no dead keys) dvorak Estonian (Dvorak) us Estonian (US) ir fa Persian fas pes_keypad Persian (with Persian keypad) ku ku Kurdish (Iran, Latin Q) kur ku_f ku Kurdish (Iran, F) kur ku_alt ku Kurdish (Iran, Latin Alt-Q) kur ku_ara ku Kurdish (Iran, Arabic-Latin) kur iq ar Iraqi ara kur ku ku Kurdish (Iraq, Latin Q) kur ku_f ku Kurdish (Iraq, F) kur ku_alt ku Kurdish (Iraq, Latin Alt-Q) kur ku_ara ku Kurdish (Iraq, Arabic-Latin) kur fo fo Faroese fao nodeadkeys Faroese (no dead keys) fi fi Finnish fin winkeys Finnish (Windows) classic Finnish (classic) nodeadkeys Finnish (classic, no dead keys) smi Northern Saami (Finland) sme mac Finnish (Macintosh) fr fr French fra nodeadkeys French (no dead keys) sundeadkeys French (Sun dead keys) oss French (alt.) oss_latin9 French (alt., Latin-9 only) oss_nodeadkeys French (alt., no dead keys) oss_sundeadkeys French (alt., Sun dead keys) latin9 French (legacy, alt.) latin9_nodeadkeys French (legacy, alt., no dead keys) latin9_sundeadkeys French (legacy, alt., Sun dead keys) bepo French (BEPO) bepo_latin9 French (BEPO, Latin-9 only) bepo_afnor French (BEPO, AFNOR) dvorak French (Dvorak) mac French (Macintosh) azerty French (AZERTY) afnor French (AZERTY, AFNOR) bre French (Breton) oci Occitan oci geo Georgian (France, AZERTY Tskapo) kat us French (US) gh en English (Ghana) eng generic English (Ghana, multilingual) akan ak Akan aka ewe ee Ewe ewe fula ff Fula ful ga gaa Ga gaa hausa ha Hausa (Ghana) hau avn avn Avatime avn gillbt English (Ghana, GILLBT) gn fr French (Guinea) fra ge ka Georgian kat ergonomic Georgian (ergonomic) mess Georgian (MESS) ru ru Russian (Georgia) rus os Ossetian (Georgia) oss de de German deu deadacute German (dead acute) deadgraveacute German (dead grave acute) nodeadkeys German (no dead keys) T3 German (T3) ro Romanian (Germany) ron ro_nodeadkeys Romanian (Germany, no dead keys) ron dvorak German (Dvorak) sundeadkeys German (Sun dead keys) neo German (Neo 2) mac German (Macintosh) mac_nodeadkeys German (Macintosh, no dead keys) dsb Lower Sorbian dsb dsb_qwertz Lower Sorbian (QWERTZ) dsb qwerty German (QWERTY) tr Turkish (Germany) tr ru ru Russian (Germany, phonetic) rus deadtilde German (dead tilde) gr gr Greek ell simple Greek (simple) extended Greek (extended) nodeadkeys Greek (no dead keys) polytonic Greek (polytonic) hu hu Hungarian hun standard Hungarian (standard) nodeadkeys Hungarian (no dead keys) qwerty Hungarian (QWERTY) 101_qwertz_comma_dead Hungarian (QWERTZ, 101-key, comma, dead keys) 101_qwertz_comma_nodead Hungarian (QWERTZ, 101-key, comma, no dead keys) 101_qwertz_dot_dead Hungarian (QWERTZ, 101-key, dot, dead keys) 101_qwertz_dot_nodead Hungarian (QWERTZ, 101-key, dot, no dead keys) 101_qwerty_comma_dead Hungarian (QWERTY, 101-key, comma, dead keys) 101_qwerty_comma_nodead Hungarian (QWERTY, 101-key, comma, no dead keys) 101_qwerty_dot_dead Hungarian (QWERTY, 101-key, dot, dead keys) 101_qwerty_dot_nodead Hungarian (QWERTY, 101-key, dot, no dead keys) 102_qwertz_comma_dead Hungarian (QWERTZ, 102-key, comma, dead keys) 102_qwertz_comma_nodead Hungarian (QWERTZ, 102-key, comma, no dead keys) 102_qwertz_dot_dead Hungarian (QWERTZ, 102-key, dot, dead keys) 102_qwertz_dot_nodead Hungarian (QWERTZ, 102-key, dot, no dead keys) 102_qwerty_comma_dead Hungarian (QWERTY, 102-key, comma, dead keys) 102_qwerty_comma_nodead Hungarian (QWERTY, 102-key, comma, no dead keys) 102_qwerty_dot_dead Hungarian (QWERTY, 102-key, dot, dead keys) 102_qwerty_dot_nodead Hungarian (QWERTY, 102-key, dot, no dead keys) is is Icelandic isl Sundeadkeys Icelandic (Sun dead keys) nodeadkeys Icelandic (no dead keys) mac_legacy Icelandic (Macintosh, legacy) mac Icelandic (Macintosh) dvorak Icelandic (Dvorak) il he Hebrew heb lyx Hebrew (lyx) phonetic Hebrew (phonetic) biblical Hebrew (Biblical, Tiro) it it Italian ita nodeadkeys Italian (no dead keys) winkeys Italian (Windows) mac Italian (Macintosh) us Italian (US) geo Georgian (Italy) kat ibm Italian (IBM 142) intl Italian (intl., with dead keys) deu fra ita slk srd nap scn fur scn Sicilian ita scn fur Friulian (Italy) fur jp ja Japanese jpn kana Japanese (Kana) kana86 Japanese (Kana 86) OADG109A Japanese (OADG 109A) mac Japanese (Macintosh) dvorak Japanese (Dvorak) kg ki Kyrgyz kir phonetic Kyrgyz (phonetic) kh km Khmer (Cambodia) khm kz kk Kazakh kaz ruskaz ru Russian (Kazakhstan, with Kazakh) kaz rus kazrus Kazakh (with Russian) kaz rus ext Kazakh (extended) kaz latin Kazakh (Latin) kaz la lo Lao lao stea Lao (STEA) lao latam es Spanish (Latin American) AR BO CL CO CR CU DO EC GT HN HT MX NI PA PE PR PY SV US UY VE spa nodeadkeys Spanish (Latin American, no dead keys) deadtilde Spanish (Latin American, dead tilde) sundeadkeys Spanish (Latin American, Sun dead keys) dvorak Spanish (Latin American, Dvorak) colemak Spanish (Latin American, Colemak) colemak-gaming Spanish (Latin American, Colemak for gaming) lt lt Lithuanian lit std Lithuanian (standard) us Lithuanian (US) ibm Lithuanian (IBM LST 1205-92) lekp Lithuanian (LEKP) lekpa Lithuanian (LEKPa) sgs Samogitian sgs lv lv Latvian lav apostrophe Latvian (apostrophe) tilde Latvian (tilde) fkey Latvian (F) modern Latvian (modern) ergonomic Latvian (ergonomic, ŪGJRMV) adapted Latvian (adapted) mao mi Maori mri me sr Montenegrin srp cyrillic Montenegrin (Cyrillic) cyrillicyz Montenegrin (Cyrillic, ZE and ZHE swapped) latinunicode Montenegrin (Latin, Unicode) latinyz Montenegrin (Latin, QWERTY) latinunicodeyz Montenegrin (Latin, Unicode, QWERTY) cyrillicalternatequotes Montenegrin (Cyrillic, with guillemets) latinalternatequotes Montenegrin (Latin, with guillemets) mk mk Macedonian mkd nodeadkeys Macedonian (no dead keys) mt mt Maltese mlt us Maltese (US) alt-us Maltese (US layout with AltGr overrides) alt-gb Maltese (UK, with AltGr overrides) mn mn Mongolian mon no no Norwegian nor nob nno nodeadkeys Norwegian (no dead keys) winkeys Norwegian (Windows) dvorak Norwegian (Dvorak) smi Northern Saami (Norway) sme smi_nodeadkeys Northern Saami (Norway, no dead keys) sme mac Norwegian (Macintosh) mac_nodeadkeys Norwegian (Macintosh, no dead keys) colemak Norwegian (Colemak) pl pl Polish pol legacy Polish (legacy) qwertz Polish (QWERTZ) dvorak Polish (Dvorak) dvorak_quotes Polish (Dvorak, with Polish quotes on quotemark key) dvorak_altquotes Polish (Dvorak, with Polish quotes on key 1) csb Kashubian csb szl Silesian szl ru_phonetic_dvorak ru Russian (Poland, phonetic Dvorak) rus dvp Polish (programmer Dvorak) pt pt Portuguese por nodeadkeys Portuguese (no dead keys) sundeadkeys Portuguese (Sun dead keys) mac Portuguese (Macintosh) mac_nodeadkeys Portuguese (Macintosh, no dead keys) mac_sundeadkeys Portuguese (Macintosh, Sun dead keys) nativo Portuguese (Nativo) nativo-us Portuguese (Nativo for US keyboards) nativo-epo Esperanto (Portugal, Nativo) epo ro ro Romanian ron cedilla Romanian (cedilla) std Romanian (standard) std_cedilla Romanian (standard cedilla) winkeys Romanian (Windows) ru ru Russian rus phonetic Russian (phonetic) phonetic_winkeys Russian (phonetic, Windows) phonetic_YAZHERTY Russian (phonetic, YAZHERTY) typewriter Russian (typewriter) legacy Russian (legacy) typewriter-legacy Russian (typewriter, legacy) tt Tatar tat os_legacy Ossetian (legacy) oss os_winkeys Ossetian (Windows) oss cv Chuvash chv cv_latin Chuvash (Latin) chv udm Udmurt udm kom Komi kom sah Yakut sah xal Kalmyk xal dos Russian (DOS) mac Russian (Macintosh) srp Serbian (Russia) rus srp bak Bashkirian bak chm Mari chm phonetic_azerty Russian (phonetic, AZERTY) phonetic_dvorak Russian (phonetic, Dvorak) phonetic_fr Russian (phonetic, French) rs sr Serbian srp yz Serbian (Cyrillic, ZE and ZHE swapped) latin Serbian (Latin) latinunicode Serbian (Latin, Unicode) latinyz Serbian (Latin, QWERTY) latinunicodeyz Serbian (Latin, Unicode, QWERTY) alternatequotes Serbian (Cyrillic, with guillemets) latinalternatequotes Serbian (Latin, with guillemets) rue Pannonian Rusyn rue si sl Slovenian slv alternatequotes Slovenian (with guillemets) us Slovenian (US) sk sk Slovak slk bksl Slovak (extended backslash) qwerty Slovak (QWERTY) qwerty_bksl Slovak (QWERTY, extended backslash) es es Spanish spa nodeadkeys Spanish (no dead keys) winkeys Spanish (Windows) deadtilde Spanish (dead tilde) sundeadkeys Spanish (Sun dead keys) dvorak Spanish (Dvorak) ast ast Asturian (Spain, with bottom-dot H and L) ast cat ca Catalan (Spain, with middle-dot L) cat mac Spanish (Macintosh) se sv Swedish swe nodeadkeys Swedish (no dead keys) dvorak Swedish (Dvorak) rus ru Russian (Sweden, phonetic) rus rus_nodeadkeys ru Russian (Sweden, phonetic, no dead keys) rus smi Northern Saami (Sweden) sme mac Swedish (Macintosh) svdvorak Swedish (Svdvorak) us_dvorak Swedish (Dvorak, intl.) us Swedish (US) swl Swedish Sign Language swl ch de German (Switzerland) deu gsw legacy German (Switzerland, legacy) de_nodeadkeys de German (Switzerland, no dead keys) de_sundeadkeys de German (Switzerland, Sun dead keys) fr fr French (Switzerland) fra fr_nodeadkeys fr French (Switzerland, no dead keys) fra fr_sundeadkeys fr French (Switzerland, Sun dead keys) fra fr_mac fr French (Switzerland, Macintosh) fra de_mac de German (Switzerland, Macintosh) sy ar Arabic (Syria) syr syc syc Syriac syc_phonetic syc Syriac (phonetic) ku ku Kurdish (Syria, Latin Q) kur ku_f ku Kurdish (Syria, F) kur ku_alt ku Kurdish (Syria, Latin Alt-Q) kur tj tg Tajik tgk legacy Tajik (legacy) lk si Sinhala (phonetic) sin tam_unicode ta Tamil (Sri Lanka, TamilNet '99) tam tam_TAB Tamil (Sri Lanka, TamilNet '99, TAB encoding) tam us us Sinhala (US) th th Thai tha tis Thai (TIS-820.2538) pat Thai (Pattachote) tr tr Turkish tur f Turkish (F) alt Turkish (Alt-Q) sundeadkeys Turkish (Sun dead keys) ku ku Kurdish (Turkey, Latin Q) kur ku_f ku Kurdish (Turkey, F) kur ku_alt ku Kurdish (Turkey, Latin Alt-Q) kur intl Turkish (intl., with dead keys) crh crh Crimean Tatar (Turkish Q) crh crh_f crh Crimean Tatar (Turkish F) crh crh_alt crh Crimean Tatar (Turkish Alt-Q) crh tw zh Taiwanese fox indigenous Taiwanese (indigenous) ami tay bnn ckv pwn pyu dru ais ssf tao tsu trv xnb sxr uun fos saisiyat xsy Saisiyat (Taiwan) xsy ua uk Ukrainian ukr phonetic Ukrainian (phonetic) typewriter Ukrainian (typewriter) winkeys Ukrainian (Windows) legacy Ukrainian (legacy) rstu Ukrainian (standard RSTU) rstu_ru Russian (Ukraine, standard RSTU) homophonic Ukrainian (homophonic) gb en English (UK) eng extd English (UK, extended, Windows) intl English (UK, intl., with dead keys) dvorak English (UK, Dvorak) dvorakukp English (UK, Dvorak, with UK punctuation) mac English (UK, Macintosh) mac_intl English (UK, Macintosh, intl.) colemak English (UK, Colemak) pl pl Polish (British keyboard) pol uz uz Uzbek uzb latin Uzbek (Latin) vn vi Vietnamese vie us Vietnamese (US) fr Vietnamese (French) kr ko Korean kor kr104 Korean (101/104-key compatible) nec_vndr/jp ja Japanese (PC-98) JP jpn ie ie Irish eng CloGaelach CloGaelach gle UnicodeExpert Irish (UnicodeExpert) ogam Ogham sga ogam_is434 Ogham (IS434) sga pk ur Urdu (Pakistan) urd urd-crulp Urdu (Pakistan, CRULP) urd-nla Urdu (Pakistan, NLA) ara ar Arabic (Pakistan) ara snd sd Sindhi snd mv dv Dhivehi div za en English (South Africa) eng epo eo Esperanto epo legacy Esperanto (legacy) np ne Nepali nep sat ng en English (Nigeria) eng igbo ig Igbo ibo yoruba yo Yoruba yor hausa ha Hausa (Nigeria) hau et am Amharic amh sn wo Wolof wol brai brl Braille left_hand Braille (left-handed) left_hand_invert Braille (left-handed inverted thumb) right_hand Braille (right-handed) right_hand_invert Braille (right-handed inverted thumb) tm tk Turkmen tuk alt Turkmen (Alt-Q) ml bm Bambara bam fr-oss fr French (Mali, alt.) fra us-mac en English (Mali, US, Macintosh) eng us-intl en English (Mali, US, intl.) eng tz sw Swahili (Tanzania) swa tg fr-tg French (Togo) fra ajg blo kpo ewe fon fue gej ife kbp las dop mfg nmz bud gng kdh soy ke sw Swahili (Kenya) swa kik ki Kikuyu kik bw tn Tswana tsn ph ph Filipino eng bik ceb fil hil ilo pam pag phi tgl war qwerty-bay Filipino (QWERTY, Baybayin) bik ceb fil hil ilo pam pag phi tgl war capewell-dvorak Filipino (Capewell-Dvorak, Latin) capewell-dvorak-bay Filipino (Capewell-Dvorak, Baybayin) bik ceb fil hil ilo pam pag phi tgl war capewell-qwerf2k6 Filipino (Capewell-QWERF 2006, Latin) capewell-qwerf2k6-bay Filipino (Capewell-QWERF 2006, Baybayin) bik ceb fil hil ilo pam pag phi tgl war colemak Filipino (Colemak, Latin) colemak-bay Filipino (Colemak, Baybayin) bik ceb fil hil ilo pam pag phi tgl war dvorak Filipino (Dvorak, Latin) dvorak-bay Filipino (Dvorak, Baybayin) bik ceb fil hil ilo pam pag phi tgl war md md Moldavian ron gag gag Moldavian (Gagauz) gag id id Indonesian (Arab Melayu, phonetic) ind msa min ace bjn tsg mfa phoneticx Indonesian (Arab Melayu, extended phonetic) jv jv Indonesian (Javanese) jv my ms Malay (Jawi, Arabic Keyboard) ind msa min ace bjn tsg mfa phonetic Malay (Jawi, phonetic) grp Switching to another layout lv3 Key to choose the 3rd level ctrl Ctrl position grp_led Use keyboard LED to show alternative layout mod_led Use keyboard LED to indicate modifiers keypad Layout of numeric keypad kpdl Numeric keypad Delete behavior caps Caps Lock behavior altwin Alt and Win behavior Compose key Position of Compose key compat Compatibility options currencysign Currency signs lv5 Key to choose 5th level nbsp Non-breaking space input japan Japanese keyboard options korean Korean Hangul/Hanja keys esperanto Esperanto letters with superscripts solaris Old Solaris keycodes compatibility terminate Key sequence to kill the X server xkbcommon-libxkbcommon-54ee7ac/test/data/rules/evdev000066400000000000000000001277421510033435100227560ustar00rootroot00000000000000// DO NOT EDIT THIS FILE - IT WAS AUTOGENERATED BY merge.py FROM rules/*.part // // // Rules for resolving XKB components for use with XFree86 // Copyright 1996 by Joseph Moss // // 2002 Modifier: Ivan Pascal The XFree86 Project // // If you want non-latin layouts implicitly include the en_US layout // uncomment lines below //! $nonlatin = am ara ben bd bg bt by cs deva ge gh gr guj guru il \ // in ir iku jp kan kh kr la lao lk mk mm mn mv mal olck \ // ori pk ru scc sy syr tel th tj tam ua uz // PC models ! $pcmodels = pc86 pc101 pc102 pc104 pc104alt pc105 // Jolla devices and keyboards ! $jollamodels = jollasbj // Microsoft models (using MS geometry) ! $msmodels = microsoft microsoft4000 microsoft7000 microsoftpro microsoftprousb microsoftprose microsoftsurface // Nokia devices and keyboards ! $nokiamodels = nokiasu8w nokiarx44 nokiarx51 // TypeMatrix geometries ! $tmgeometries = tm2020 tm2030PS2 tm2030USB tm2030USB-102 tm2030USB-106 // Layouts that provide further specializations for the OLPC ! $olpclayouts = af am ara br ca es et fr it kh kz in mn np ru th tr us ! $macbooks = macbook78 macbook79 ! $maclaptop = ibook powerbook macbook78 macbook79 ! $applealu = applealu_ansi applealu_iso applealu_jis ! $macs = macintosh macintosh_old ibook powerbook macbook78 macbook79 ! $macvendorlayouts = ch de dk fi fr gb is it latam nl no pt se us ! $azerty = be fr ! $qwertz = al cz de hr hu ro si sk // all layouts with 3rd and 4th groups ! $threelevellayouts = al az \ be br bt \ ca ch cs cz \ de dk \ ee es \ fi fo fr \ gb gr \ hu \ ie ir is it \ latam \ lk lt \ mn mt \ nl no \ pl pt \ ro \ se sk \ tr \ us \ vn \ za ! $thinkpads = thinkpad thinkpad60 thinkpadz60 ! $sun = sun_type6_jp sun_type6_usb sun_type6_euro_usb \ sun_type6_jp_usb sun_type6_unix_usb sun_type7_jp_usb \ sun_type7_usb sun_type7_euro_usb sun_type7_unix_usb ! $sun_jp = sun_type6_jp sun_type6_jp_usb sun_type7_jp_usb // Sun Type_6_7 keyboards with custom layouts ! $sun_custom = ara be br ca ch cz de dk \ ee es fi fr gb gr it jp \ kr lt lv nl no pl pt ro \ ru se sk tr tw ua us ! $sun_var = sun_type6 sun_type6_suncompat sun_type6_de sun_type6_fr \ sun_type7 sun_type7_suncompat suncompat ! $sun_compat = sun_type6 sun_type6_suncompat sun_type7_suncompat suncompat ! $evdevkbds = ibm_spacesaver ! $dvoraklayouts = br ca de ee es fr gb no pl se us ! model = keycodes applealu_jis = evdev+macintosh(jisevdev) $jollamodels = evdev+jolla(jolla) olpc = evdev+olpc(olpc) olpcm = evdev+olpc(olpcm) * = evdev ! layout[1] = keycodes $azerty = +aliases(azerty) $qwertz = +aliases(qwertz) * = +aliases(qwerty) ! layout = keycodes $azerty = +aliases(azerty) $qwertz = +aliases(qwertz) * = +aliases(qwerty) ! option = keycodes ! model layout = geometry thinkpad us = thinkpad(us) ! model = geometry microsoftelite = microsoft(elite) $msmodels = microsoft(natural) dell101 = dell(dell101) dellm65 = dell(dellm65) latitude = dell(latitude) flexpro = keytronic(FlexPro) hp6000 = hp(omnibook) hpmini110 = hp(mini110) hpdv5 = hp(dv5) omnikey101 = northgate(omnikey101) sanwaskbkg3 = sanwa(sanwaskbkg3) $pcmodels = pc(%m) everex = everex(STEPnote) thinkpad = thinkpad(intl) thinkpad60 = thinkpad(60) thinkpadz60 = thinkpad(60) apex300 = steelseries(apex300) $tmgeometries = typematrix(%m) winbook = winbook(XP5) pc98 = nec(pc98) $applealu = macintosh(%m) $macbooks = macintosh(%m) $macs = macintosh(macintosh) hhk = hhk(basic) kinesis = kinesis(model100) $nokiamodels = nokia(%m) sun_type6_jp = sun(type6jp) sun_type6_usb = sun(type6) sun_type6_euro_usb = sun(type6tuv) sun_type6_jp_usb = sun(type6jp) sun_type6_unix_usb = sun(type6unix) sun_type7_jp_usb = sun(type6jp) sun_type7_usb = sun(type7) sun_type7_euro_usb = sun(type7tuv) sun_type7_unix_usb = sun(type7unix) * = pc(pc104) ! model layout variant = symbols * ben basic = pc+in(ben) * ben probhat = pc+in(ben_probhat) * dev basic = pc+in(deva) * dvorak $dvoraklayouts = pc+%v(dvorak) * dvorak basic = pc+us(dvorak) * dvorak pl_basic = pc+pl(dvorak) * dvorak pl = pc+pl(dvorak_quotes) * dvorak pl_altquotes = pc+pl(dvorak_altquotes) * dzdwi basic = pc+bt(basic) * fi basic = pc+fi(classic) * ge azerty_tskapo = pc+fr(geo) * guj basic = pc+in(guj) * gur basic = pc+in(guru) * ie laptop = pc+ie(basic) * ie CloGaelachLaptop = pc+ie(CloGaelach) * in urd = pc+in(urd-phonetic) * iu basic = pc+ca(ike) * lo basic = pc+la(basic) * kan basic = pc+in(kan) * mal basic = pc+in(mal) * mal mlplusnum = pc+in(mal) * ogham basic = pc+ie(ogam) * ogham laptop = pc+ie(ogam) * ogham is434 = pc+ie(ogam_is434) * ogham is434laptop = pc+ie(ogam_is434) * ori basic = pc+in(ori) * ro de = pc+ro(winkeys) * ro us = pc+ro(std) * ro academic = pc+ro(std) * ro std_comma = pc+ro(std) * ro comma = pc+ro(basic) * ru os = pc+ru(os_legacy) * pk urd = pc+pk(urd-phonetic) * sapmi basic = pc+no(smi) * sapmi nodeadkeys = pc+no(smi_nodeadkeys) * sapmi sefi = pc+fi(smi) * sin phonetic-static = pc+in(sin_phonetic) * syr basic = pc+sy(syc) * syr phonetic = pc+sy(syc_phonetic) * tam INSCRIPT = pc+in(tam) * tam UNI = pc+in(tam_unicode) * tam NUMERAL-KEYBOARD = pc+in(tam_keyboard_with_numerals) * tam TAB = pc+in(tam_TAB) * tam TSCII = pc+in(tam_TSCII) * tel basic = pc+in(tel) * yu basic = pc+srp(latin) * yu unicode = pc+srp(latinunicode) * yu yz = pc+srp(latinyz) * yu unicodeyz = pc+srp(latinunicodeyz) classmate us intl = pc+us(classmate-intl) classmate us alt-intl = pc+us(classmate-alt-intl) classmate us altgr-intl = pc+us(classmate-altgr-intl) nokiarx51 cz qwerty = nokia_vndr/rx-51(cz_qwerty) * $sun_custom $sun_var = pc+sun_vndr/%l%(v) ! model layout = symbols * ar = pc+ara * ben = pc+in(ben) * bs = pc+ba * cs = pc+rs * cz_qwerty = pc+cz(qwerty) * dev = pc+in(deva) * dvorak = pc+us(dvorak) * dzdwi = pc+bt * el = pc+gr * en_US = pc+latin * guj = pc+in(guj) * gur = pc+in(guru) * iu = pc+ca(ike) * lo = pc+la * kan = pc+in(kan) * mi = pc+mao * ogham = pc+ie(ogam) * ori = pc+ie(ori) * sapmi = pc+no(smi) * sr = pc+srp * syr = pc+sy(syc) * tel = pc+in(tel) * tml = pc+in(tam) * yu = pc+srp * fr-latin9 = pc+fr(latin9) * us_intl = pc+us(alt-intl) * ben(basic) = pc+in(ben) * ben(probhat) = pc+in(ben_probhat) * dev(basic) = pc+in(deva) * dvorak($dvoraklayouts) = pc+%v(dvorak) * dvorak(basic) = pc+us(dvorak) * dvorak(pl_basic) = pc+pl(dvorak) * dvorak(pl) = pc+pl(dvorak_quotes) * dvorak(pl_altquotes) = pc+pl(dvorak_altquotes) * dzdwi(basic) = pc+bt(basic) * fi(basic) = pc+fi(classic) * ge(azerty_tskapo) = pc+fr(geo) * guj(basic) = pc+in(guj) * gur(basic) = pc+in(guru) * ie(laptop) = pc+ie(basic) * ie(CloGaelachLaptop) = pc+ie(CloGaelach) * in(urd) = pc+in(urd-phonetic) * iu(basic) = pc+ca(ike) * lo(basic) = pc+la(basic) * kan(basic) = pc+in(kan) * mal(basic) = pc+in(mal) * mal(mlplusnum) = pc+in(mal) * ogham(basic) = pc+ie(ogam) * ogham(laptop) = pc+ie(ogam) * ogham(is434) = pc+ie(ogam_is434) * ogham(is434laptop) = pc+ie(ogam_is434) * ori(basic) = pc+in(ori) * ro(de) = pc+ro(winkeys) * ro(us) = pc+ro(std) * ro(academic) = pc+ro(std) * ro(std_comma) = pc+ro(std) * ro(comma) = pc+ro(basic) * ru(os) = pc+ru(os_legacy) * pk(urd) = pc+pk(urd-phonetic) * sapmi(basic) = pc+no(smi) * sapmi(nodeadkeys) = pc+no(smi_nodeadkeys) * sapmi(sefi) = pc+fi(smi) * sin(phonetic-static) = pc+in(sin_phonetic) * syr(basic) = pc+sy(syc) * syr(phonetic) = pc+sy(syc_phonetic) * tam(INSCRIPT) = pc+in(tam) * tam(UNI) = pc+in(tam_unicode) * tam(NUMERAL-KEYBOARD) = pc+in(tam_keyboard_with_numerals) * tam(TAB) = pc+in(tam_TAB) * tam(TSCII) = pc+in(tam_TSCII) * tel(basic) = pc+in(tel) * yu(basic) = pc+srp(latin) * yu(unicode) = pc+srp(latinunicode) * yu(yz) = pc+srp(latinyz) * yu(unicodeyz) = pc+srp(latinunicodeyz) ataritt $nonlatin = xfree68_vndr/ataritt(us)+%l%(v):2 ataritt * = xfree68_vndr/ataritt(us)+%l%(v) amiga $nonlatin = xfree68_vndr/amiga(usa1)+%l%(v):2 amiga * = xfree68_vndr/amiga(usa1)+%l%(v) classmate us = pc+%l(classmate) empty * = empty(basic) * empty = empty(basic) jollasbj $nonlatin = jolla_vndr/sbj(common)+us+%l%(v):2 jollasbj * = jolla_vndr/sbj(common)+%l%(v) $sun $sun_custom = pc+sun_vndr/%l%(v) pc98 nec_vndr/jp = nec_vndr/jp(pc98) macintosh_old us = macintosh_vndr/us(oldmac) macintosh_old en_US = macintosh_vndr/us(oldmac) macintosh_old $macvendorlayouts = macintosh_vndr/us(oldmac)+macintosh_vndr/%l%(v) macintosh_old $nonlatin = macintosh_vndr/us(oldmac)+%l%(v):2 macintosh_old * = macintosh_vndr/us(oldmac)+%l%(v) applealu_jis jp = macintosh_vndr/apple(alukbd)+macintosh_vndr/jp(usmac)+macintosh_vndr/jp(mac):2 applealu_jis * = macintosh_vndr/apple(alukbd)+%l%(v)+macintosh_vndr/jp(mac):2 $applealu $macvendorlayouts = macintosh_vndr/apple(alukbd)+macintosh_vndr/%l%(v) $applealu * = macintosh_vndr/apple(alukbd)+%l%(v) $macs en_US = pc+macintosh_vndr/us(extended) $macs $macvendorlayouts = pc+macintosh_vndr/%l%(v) nokiarx44 * = nokia_vndr/rx-44(%l) nokiarx51 cz(qwerty) = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(cz_qwerty) nokiarx51 * = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(%l%_v) nokiasu8w * = nokia_vndr/su-8w(%l) olpc $olpclayouts = olpc+%l%(m) olpc * = olpc+%l%(v) olpcm $olpclayouts = olpc+%l%(m) olpcm * = olpc+%l%(v) $thinkpads br = pc+br(thinkpad) sl-c3x00 * = pc+sharp_vndr/sl-c3x00(basic) ws003sh * = pc+sharp_vndr/ws003sh(basic) ws007sh * = pc+sharp_vndr/ws007sh(basic) ws011sh * = pc+sharp_vndr/ws011sh(basic) ws020sh * = pc+sharp_vndr/ws020sh(basic) * $nonlatin = pc+us+%l%(v):2 * * = pc+%l%(v) ! model layout[1] = symbols * ar = pc+ara%(v[1]) * ben = pc+in(ben) * bs = pc+ba%(v[1]) * cs = pc+rs%(v[1]) * cz_qwerty = pc+cz(qwerty) * dev = pc+in(deva) * dvorak = pc+us(dvorak) * dzdwi = pc+bt%(v[1]) * el = pc+gr%(v[1]) * en_US = pc+latin%(v[1]) * guj = pc+in(guj) * gur = pc+in(guru) * iu = pc+ca(ike) * lo = pc+la%(v[1]) * kan = pc+in(kan) * mi = pc+mao%(v[1]) * ogham = pc+ie(ogam) * ori = pc+ie(ori) * sapmi = pc+no(smi) * sr = pc+srp%(v[1]) * syr = pc+sy(syc) * tel = pc+in(tel) * tml = pc+in(tam) * yu = pc+srp%(v[1]) * fr-latin9 = pc+fr(latin9) * us_intl = pc+us(alt-intl) * ben(basic) = pc+in(ben) * ben(probhat) = pc+in(ben_probhat) * dev(basic) = pc+in(deva) * dvorak($dvoraklayouts) = pc+%v(dvorak) * dvorak(basic) = pc+us(dvorak) * dvorak(pl_basic) = pc+pl(dvorak) * dvorak(pl) = pc+pl(dvorak_quotes) * dvorak(pl_altquotes) = pc+pl(dvorak_altquotes) * dzdwi(basic) = pc+bt(basic) * fi(basic) = pc+fi(classic) * ge(azerty_tskapo) = pc+fr(geo) * guj(basic) = pc+in(guj) * gur(basic) = pc+in(guru) * ie(laptop) = pc+ie(basic) * ie(CloGaelachLaptop) = pc+ie(CloGaelach) * in(urd) = pc+in(urd-phonetic) * iu(basic) = pc+ca(ike) * lo(basic) = pc+la(basic) * kan(basic) = pc+in(kan) * mal(basic) = pc+in(mal) * mal(mlplusnum) = pc+in(mal) * ogham(basic) = pc+ie(ogam) * ogham(laptop) = pc+ie(ogam) * ogham(is434) = pc+ie(ogam_is434) * ogham(is434laptop) = pc+ie(ogam_is434) * ori(basic) = pc+in(ori) * ro(de) = pc+ro(winkeys) * ro(us) = pc+ro(std) * ro(academic) = pc+ro(std) * ro(std_comma) = pc+ro(std) * ro(comma) = pc+ro(basic) * ru(os) = pc+ru(os_legacy) * pk(urd) = pc+pk(urd-phonetic) * sapmi(basic) = pc+no(smi) * sapmi(nodeadkeys) = pc+no(smi_nodeadkeys) * sapmi(sefi) = pc+fi(smi) * sin(phonetic-static) = pc+in(sin_phonetic) * syr(basic) = pc+sy(syc) * syr(phonetic) = pc+sy(syc_phonetic) * tam(INSCRIPT) = pc+in(tam) * tam(UNI) = pc+in(tam_unicode) * tam(NUMERAL-KEYBOARD) = pc+in(tam_keyboard_with_numerals) * tam(TAB) = pc+in(tam_TAB) * tam(TSCII) = pc+in(tam_TSCII) * tel(basic) = pc+in(tel) * yu(basic) = pc+srp(latin) * yu(unicode) = pc+srp(latinunicode) * yu(yz) = pc+srp(latinyz) * yu(unicodeyz) = pc+srp(latinunicodeyz) ataritt * = xfree68_vndr/ataritt(us)+%l[1]%(v[1]) amiga * = xfree68_vndr/amiga(usa1)+%l[1]%(v[1]) jollasbj * = jolla_vndr/sbj(common)+%l[1]%(v[1]) $sun $sun_custom = pc+sun_vndr/%l[1]%(v[1]) macintosh_old us = macintosh_vndr/us(oldmac) macintosh_old $macvendorlayouts = macintosh_vndr/us(oldmac)+macintosh_vndr/%l[1]%(v[1]) macintosh_old * = macintosh_vndr/us(oldmac)+%l[1]%(v[1]) applealu_jis us = macintosh_vndr/apple(alukbd)+macintosh_vndr/jp(usmac) $applealu $macvendorlayouts = macintosh_vndr/apple(alukbd)+macintosh_vndr/%l[1]%(v[1]) $applealu * = macintosh_vndr/apple(alukbd)+%l[1]%(v[1]) $macs $macvendorlayouts = pc+macintosh_vndr/%l[1]%(v[1]) nokiarx51 cz(qwerty) = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(cz_qwerty) nokiarx51 * = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(%l[1]%_v[1]) $thinkpads br = pc+%l[1](thinkpad) * * = pc+%l[1]%(v[1]) ! model layout[1] variant[1] = symbols * ben basic = pc+in(ben) * ben probhat = pc+in(ben_probhat) * dev basic = pc+in(deva) * dvorak $dvoraklayouts = pc+%v(dvorak) * dvorak basic = pc+us(dvorak) * dvorak pl_basic = pc+pl(dvorak) * dvorak pl = pc+pl(dvorak_quotes) * dvorak pl_altquotes = pc+pl(dvorak_altquotes) * dzdwi basic = pc+bt(basic) * fi basic = pc+fi(classic) * ge azerty_tskapo = pc+fr(geo) * guj basic = pc+in(guj) * gur basic = pc+in(guru) * ie laptop = pc+ie(basic) * ie CloGaelachLaptop = pc+ie(CloGaelach) * in urd = pc+in(urd-phonetic) * iu basic = pc+ca(ike) * lo basic = pc+la(basic) * kan basic = pc+in(kan) * mal basic = pc+in(mal) * mal mlplusnum = pc+in(mal) * ogham basic = pc+ie(ogam) * ogham laptop = pc+ie(ogam) * ogham is434 = pc+ie(ogam_is434) * ogham is434laptop = pc+ie(ogam_is434) * ori basic = pc+in(ori) * ro de = pc+ro(winkeys) * ro us = pc+ro(std) * ro academic = pc+ro(std) * ro std_comma = pc+ro(std) * ro comma = pc+ro(basic) * ru os = pc+ru(os_legacy) * pk urd = pc+pk(urd-phonetic) * sapmi basic = pc+no(smi) * sapmi nodeadkeys = pc+no(smi_nodeadkeys) * sapmi sefi = pc+fi(smi) * sin phonetic-static = pc+in(sin_phonetic) * syr basic = pc+sy(syc) * syr phonetic = pc+sy(syc_phonetic) * tam INSCRIPT = pc+in(tam) * tam UNI = pc+in(tam_unicode) * tam NUMERAL-KEYBOARD = pc+in(tam_keyboard_with_numerals) * tam TAB = pc+in(tam_TAB) * tam TSCII = pc+in(tam_TSCII) * tel basic = pc+in(tel) * yu basic = pc+srp(latin) * yu unicode = pc+srp(latinunicode) * yu yz = pc+srp(latinyz) * yu unicodeyz = pc+srp(latinunicodeyz) ! model layout[2] = symbols * ar = +ara%(v[2]):2 * ben = +in(ben):2 * bs = +ba%(v[2]):2 * cs = +rs%(v[2]):2 * cz_qwerty = +cz(qwerty):2 * dev = +in(deva):2 * dvorak = +us(dvorak):2 * dzdwi = +bt%(v[2]):2 * el = +gr%(v[2]):2 * en_US = +latin%(v[2]):2 * guj = +in(guj):2 * gur = +in(guru):2 * iu = +ca(ike):2 * lo = +la%(v[2]):2 * kan = +in(kan):2 * mi = +mao%(v[2]):2 * ogham = +ie(ogam):2 * ori = +ie(ori):2 * sapmi = +no(smi):2 * sr = +srp%(v[2]):2 * syr = +sy(syc):2 * tel = +in(tel):2 * tml = +in(tam):2 * yu = +srp%(v[2]):2 * fr-latin9 = +fr(latin9):2 * us_intl = +us(alt-intl):2 * ben(basic) = +in(ben):2 * ben(probhat) = +in(ben_probhat):2 * dev(basic) = +in(deva):2 * dvorak($dvoraklayouts) = +%v(dvorak):2 * dvorak(basic) = +us(dvorak):2 * dvorak(pl_basic) = +pl(dvorak):2 * dvorak(pl) = +pl(dvorak_quotes):2 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):2 * dzdwi(basic) = +bt(basic):2 * fi(basic) = +fi(classic):2 * ge(azerty_tskapo) = +fr(geo):2 * guj(basic) = +in(guj):2 * gur(basic) = +in(guru):2 * ie(laptop) = +ie(basic):2 * ie(CloGaelachLaptop) = +ie(CloGaelach):2 * in(urd) = +in(urd-phonetic):2 * iu(basic) = +ca(ike):2 * lo(basic) = +la(basic):2 * kan(basic) = +in(kan):2 * mal(basic) = +in(mal):2 * mal(mlplusnum) = +in(mal):2 * ogham(basic) = +ie(ogam):2 * ogham(laptop) = +ie(ogam):2 * ogham(is434) = +ie(ogam_is434):2 * ogham(is434laptop) = +ie(ogam_is434):2 * ori(basic) = +in(ori):2 * ro(de) = +ro(winkeys):2 * ro(us) = +ro(std):2 * ro(academic) = +ro(std):2 * ro(std_comma) = +ro(std):2 * ro(comma) = +ro(basic):2 * ru(os) = +ru(os_legacy):2 * pk(urd) = +pk(urd-phonetic):2 * sapmi(basic) = +no(smi):2 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):2 * sapmi(sefi) = +fi(smi):2 * sin(phonetic-static) = +in(sin_phonetic):2 * syr(basic) = +sy(syc):2 * syr(phonetic) = +sy(syc_phonetic):2 * tam(INSCRIPT) = +in(tam):2 * tam(UNI) = +in(tam_unicode):2 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):2 * tam(TAB) = +in(tam_TAB):2 * tam(TSCII) = +in(tam_TSCII):2 * tel(basic) = +in(tel):2 * yu(basic) = +srp(latin):2 * yu(unicode) = +srp(latinunicode):2 * yu(yz) = +srp(latinyz):2 * yu(unicodeyz) = +srp(latinunicodeyz):2 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):2 nokiarx51 * = +nokia_vndr/rx-51(%l[2]%_v[2]):2 $sun $sun_custom = +sun_vndr/%l[2]%(v[2]):2 * * = +%l[2]%(v[2]):2 ! model layout[3] = symbols * ar = +ara%(v[3]):3 * ben = +in(ben):3 * bs = +ba%(v[3]):3 * cs = +rs%(v[3]):3 * cz_qwerty = +cz(qwerty):3 * dev = +in(deva):3 * dvorak = +us(dvorak):3 * dzdwi = +bt%(v[3]):3 * el = +gr%(v[3]):3 * en_US = +latin%(v[3]):3 * guj = +in(guj):3 * gur = +in(guru):3 * iu = +ca(ike):3 * lo = +la%(v[3]):3 * kan = +in(kan):3 * mi = +mao%(v[3]):3 * ogham = +ie(ogam):3 * ori = +ie(ori):3 * sapmi = +no(smi):3 * sr = +srp%(v[3]):3 * syr = +sy(syc):3 * tel = +in(tel):3 * tml = +in(tam):3 * yu = +srp%(v[3]):3 * fr-latin9 = +fr(latin9):3 * us_intl = +us(alt-intl):3 * ben(basic) = +in(ben):3 * ben(probhat) = +in(ben_probhat):3 * dev(basic) = +in(deva):3 * dvorak($dvoraklayouts) = +%v(dvorak):3 * dvorak(basic) = +us(dvorak):3 * dvorak(pl_basic) = +pl(dvorak):3 * dvorak(pl) = +pl(dvorak_quotes):3 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):3 * dzdwi(basic) = +bt(basic):3 * fi(basic) = +fi(classic):3 * ge(azerty_tskapo) = +fr(geo):3 * guj(basic) = +in(guj):3 * gur(basic) = +in(guru):3 * ie(laptop) = +ie(basic):3 * ie(CloGaelachLaptop) = +ie(CloGaelach):3 * in(urd) = +in(urd-phonetic):3 * iu(basic) = +ca(ike):3 * lo(basic) = +la(basic):3 * kan(basic) = +in(kan):3 * mal(basic) = +in(mal):3 * mal(mlplusnum) = +in(mal):3 * ogham(basic) = +ie(ogam):3 * ogham(laptop) = +ie(ogam):3 * ogham(is434) = +ie(ogam_is434):3 * ogham(is434laptop) = +ie(ogam_is434):3 * ori(basic) = +in(ori):3 * ro(de) = +ro(winkeys):3 * ro(us) = +ro(std):3 * ro(academic) = +ro(std):3 * ro(std_comma) = +ro(std):3 * ro(comma) = +ro(basic):3 * ru(os) = +ru(os_legacy):3 * pk(urd) = +pk(urd-phonetic):3 * sapmi(basic) = +no(smi):3 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):3 * sapmi(sefi) = +fi(smi):3 * sin(phonetic-static) = +in(sin_phonetic):3 * syr(basic) = +sy(syc):3 * syr(phonetic) = +sy(syc_phonetic):3 * tam(INSCRIPT) = +in(tam):3 * tam(UNI) = +in(tam_unicode):3 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):3 * tam(TAB) = +in(tam_TAB):3 * tam(TSCII) = +in(tam_TSCII):3 * tel(basic) = +in(tel):3 * yu(basic) = +srp(latin):3 * yu(unicode) = +srp(latinunicode):3 * yu(yz) = +srp(latinyz):3 * yu(unicodeyz) = +srp(latinunicodeyz):3 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):3 nokiarx51 * = +nokia_vndr/rx-51(%l[3]%_v[3]):3 $sun $sun_custom = +sun_vndr/%l[3]%(v[3]):3 * * = +%l[3]%(v[3]):3 ! model layout[4] = symbols * ar = +ara%(v[4]):4 * ben = +in(ben):4 * bs = +ba%(v[4]):4 * cs = +rs%(v[4]):4 * cz_qwerty = +cz(qwerty):4 * dev = +in(deva):4 * dvorak = +us(dvorak):4 * dzdwi = +bt%(v[4]):4 * el = +gr%(v[4]):4 * en_US = +latin%(v[4]):4 * guj = +in(guj):4 * gur = +in(guru):4 * iu = +ca(ike):4 * lo = +la%(v[4]):4 * kan = +in(kan):4 * mi = +mao%(v[4]):4 * ogham = +ie(ogam):4 * ori = +ie(ori):4 * sapmi = +no(smi):4 * sr = +srp%(v[4]):4 * syr = +sy(syc):4 * tel = +in(tel):4 * tml = +in(tam):4 * yu = +srp%(v[4]):4 * fr-latin9 = +fr(latin9):4 * us_intl = +us(alt-intl):4 * ben(basic) = +in(ben):4 * ben(probhat) = +in(ben_probhat):4 * dev(basic) = +in(deva):4 * dvorak($dvoraklayouts) = +%v(dvorak):4 * dvorak(basic) = +us(dvorak):4 * dvorak(pl_basic) = +pl(dvorak):4 * dvorak(pl) = +pl(dvorak_quotes):4 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):4 * dzdwi(basic) = +bt(basic):4 * fi(basic) = +fi(classic):4 * ge(azerty_tskapo) = +fr(geo):4 * guj(basic) = +in(guj):4 * gur(basic) = +in(guru):4 * ie(laptop) = +ie(basic):4 * ie(CloGaelachLaptop) = +ie(CloGaelach):4 * in(urd) = +in(urd-phonetic):4 * iu(basic) = +ca(ike):4 * lo(basic) = +la(basic):4 * kan(basic) = +in(kan):4 * mal(basic) = +in(mal):4 * mal(mlplusnum) = +in(mal):4 * ogham(basic) = +ie(ogam):4 * ogham(laptop) = +ie(ogam):4 * ogham(is434) = +ie(ogam_is434):4 * ogham(is434laptop) = +ie(ogam_is434):4 * ori(basic) = +in(ori):4 * ro(de) = +ro(winkeys):4 * ro(us) = +ro(std):4 * ro(academic) = +ro(std):4 * ro(std_comma) = +ro(std):4 * ro(comma) = +ro(basic):4 * ru(os) = +ru(os_legacy):4 * pk(urd) = +pk(urd-phonetic):4 * sapmi(basic) = +no(smi):4 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):4 * sapmi(sefi) = +fi(smi):4 * sin(phonetic-static) = +in(sin_phonetic):4 * syr(basic) = +sy(syc):4 * syr(phonetic) = +sy(syc_phonetic):4 * tam(INSCRIPT) = +in(tam):4 * tam(UNI) = +in(tam_unicode):4 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):4 * tam(TAB) = +in(tam_TAB):4 * tam(TSCII) = +in(tam_TSCII):4 * tel(basic) = +in(tel):4 * yu(basic) = +srp(latin):4 * yu(unicode) = +srp(latinunicode):4 * yu(yz) = +srp(latinyz):4 * yu(unicodeyz) = +srp(latinunicodeyz):4 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):4 nokiarx51 * = +nokia_vndr/rx-51(%l[4]%_v[4]):4 $sun $sun_custom = +sun_vndr/%l[4]%(v[4]):4 * * = +%l[4]%(v[4]):4 ! model layout[2] variant[2] = symbols * ben basic = +in(ben):2 * ben probhat = +in(ben_probhat):2 * dev basic = +in(deva):2 * dvorak $dvoraklayouts = +%v(dvorak):2 * dvorak basic = +us(dvorak):2 * dvorak pl_basic = +pl(dvorak):2 * dvorak pl = +pl(dvorak_quotes):2 * dvorak pl_altquotes = +pl(dvorak_altquotes):2 * dzdwi basic = +bt(basic):2 * fi basic = +fi(classic):2 * ge azerty_tskapo = +fr(geo):2 * guj basic = +in(guj):2 * gur basic = +in(guru):2 * ie laptop = +ie(basic):2 * ie CloGaelachLaptop = +ie(CloGaelach):2 * in urd = +in(urd-phonetic):2 * iu basic = +ca(ike):2 * lo basic = +la(basic):2 * kan basic = +in(kan):2 * mal basic = +in(mal):2 * mal mlplusnum = +in(mal):2 * ogham basic = +ie(ogam):2 * ogham laptop = +ie(ogam):2 * ogham is434 = +ie(ogam_is434):2 * ogham is434laptop = +ie(ogam_is434):2 * ori basic = +in(ori):2 * ro de = +ro(winkeys):2 * ro us = +ro(std):2 * ro academic = +ro(std):2 * ro std_comma = +ro(std):2 * ro comma = +ro(basic):2 * ru os = +ru(os_legacy):2 * pk urd = +pk(urd-phonetic):2 * sapmi basic = +no(smi):2 * sapmi nodeadkeys = +no(smi_nodeadkeys):2 * sapmi sefi = +fi(smi):2 * sin phonetic-static = +in(sin_phonetic):2 * syr basic = +sy(syc):2 * syr phonetic = +sy(syc_phonetic):2 * tam INSCRIPT = +in(tam):2 * tam UNI = +in(tam_unicode):2 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):2 * tam TAB = +in(tam_TAB):2 * tam TSCII = +in(tam_TSCII):2 * tel basic = +in(tel):2 * yu basic = +srp(latin):2 * yu unicode = +srp(latinunicode):2 * yu yz = +srp(latinyz):2 * yu unicodeyz = +srp(latinunicodeyz):2 ! model layout[3] variant[3] = symbols * ben basic = +in(ben):3 * ben probhat = +in(ben_probhat):3 * dev basic = +in(deva):3 * dvorak $dvoraklayouts = +%v(dvorak):3 * dvorak basic = +us(dvorak):3 * dvorak pl_basic = +pl(dvorak):3 * dvorak pl = +pl(dvorak_quotes):3 * dvorak pl_altquotes = +pl(dvorak_altquotes):3 * dzdwi basic = +bt(basic):3 * fi basic = +fi(classic):3 * ge azerty_tskapo = +fr(geo):3 * guj basic = +in(guj):3 * gur basic = +in(guru):3 * ie laptop = +ie(basic):3 * ie CloGaelachLaptop = +ie(CloGaelach):3 * in urd = +in(urd-phonetic):3 * iu basic = +ca(ike):3 * lo basic = +la(basic):3 * kan basic = +in(kan):3 * mal basic = +in(mal):3 * mal mlplusnum = +in(mal):3 * ogham basic = +ie(ogam):3 * ogham laptop = +ie(ogam):3 * ogham is434 = +ie(ogam_is434):3 * ogham is434laptop = +ie(ogam_is434):3 * ori basic = +in(ori):3 * ro de = +ro(winkeys):3 * ro us = +ro(std):3 * ro academic = +ro(std):3 * ro std_comma = +ro(std):3 * ro comma = +ro(basic):3 * ru os = +ru(os_legacy):3 * pk urd = +pk(urd-phonetic):3 * sapmi basic = +no(smi):3 * sapmi nodeadkeys = +no(smi_nodeadkeys):3 * sapmi sefi = +fi(smi):3 * sin phonetic-static = +in(sin_phonetic):3 * syr basic = +sy(syc):3 * syr phonetic = +sy(syc_phonetic):3 * tam INSCRIPT = +in(tam):3 * tam UNI = +in(tam_unicode):3 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):3 * tam TAB = +in(tam_TAB):3 * tam TSCII = +in(tam_TSCII):3 * tel basic = +in(tel):3 * yu basic = +srp(latin):3 * yu unicode = +srp(latinunicode):3 * yu yz = +srp(latinyz):3 * yu unicodeyz = +srp(latinunicodeyz):3 ! model layout[4] variant[4] = symbols * ben basic = +in(ben):4 * ben probhat = +in(ben_probhat):4 * dev basic = +in(deva):4 * dvorak $dvoraklayouts = +%v(dvorak):4 * dvorak basic = +us(dvorak):4 * dvorak pl_basic = +pl(dvorak):4 * dvorak pl = +pl(dvorak_quotes):4 * dvorak pl_altquotes = +pl(dvorak_altquotes):4 * dzdwi basic = +bt(basic):4 * fi basic = +fi(classic):4 * ge azerty_tskapo = +fr(geo):4 * guj basic = +in(guj):4 * gur basic = +in(guru):4 * ie laptop = +ie(basic):4 * ie CloGaelachLaptop = +ie(CloGaelach):4 * in urd = +in(urd-phonetic):4 * iu basic = +ca(ike):4 * lo basic = +la(basic):4 * kan basic = +in(kan):4 * mal basic = +in(mal):4 * mal mlplusnum = +in(mal):4 * ogham basic = +ie(ogam):4 * ogham laptop = +ie(ogam):4 * ogham is434 = +ie(ogam_is434):4 * ogham is434laptop = +ie(ogam_is434):4 * ori basic = +in(ori):4 * ro de = +ro(winkeys):4 * ro us = +ro(std):4 * ro academic = +ro(std):4 * ro std_comma = +ro(std):4 * ro comma = +ro(basic):4 * ru os = +ru(os_legacy):4 * pk urd = +pk(urd-phonetic):4 * sapmi basic = +no(smi):4 * sapmi nodeadkeys = +no(smi_nodeadkeys):4 * sapmi sefi = +fi(smi):4 * sin phonetic-static = +in(sin_phonetic):4 * syr basic = +sy(syc):4 * syr phonetic = +sy(syc_phonetic):4 * tam INSCRIPT = +in(tam):4 * tam UNI = +in(tam_unicode):4 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):4 * tam TAB = +in(tam_TAB):4 * tam TSCII = +in(tam_TSCII):4 * tel basic = +in(tel):4 * yu basic = +srp(latin):4 * yu unicode = +srp(latinunicode):4 * yu yz = +srp(latinyz):4 * yu unicodeyz = +srp(latinunicodeyz):4 ! model = symbols $evdevkbds = +inet(evdev)+inet(%m) chromebook = +inet(evdev)+inet(chromebook) applealu_jis = +inet(evdev)+macintosh_vndr/jp(alujiskeys) * = +inet(evdev) ! model layout = symbols ! layout variant = compat de neo = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de adnw = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de koy = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de bone = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de bone_eszett_home = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de neo_qwertz = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de neo_qwerty = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) jp $sun_compat = complete+japan(kana_lock) ! layout[1] variant[1] = compat de neo = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de adnw = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de koy = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de bone = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de bone_eszett_home = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de neo_qwertz = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) de neo_qwerty = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) jp $sun_compat = complete+japan(kana_lock) ! layout[2] variant[2] = compat de neo = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de adnw = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de koy = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de bone = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de bone_eszett_home = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de neo_qwertz = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 de neo_qwerty = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 jp $sun_compat = +complete+japan(kana_lock):2 ! layout[3] variant[3] = compat de neo = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de adnw = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de koy = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de bone = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de bone_eszett_home = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de neo_qwertz = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 de neo_qwerty = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 jp $sun_compat = +complete+japan(kana_lock):3 ! layout[4] variant[4] = compat de neo = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de adnw = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de koy = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de bone = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de bone_eszett_home = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de neo_qwertz = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 de neo_qwerty = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 jp $sun_compat = +complete+japan(kana_lock):4 ! model layout = compat pc98 nec_vndr/jp = pc98(basic) * jp = complete+japan olpc * = olpc olpcm * = olpc * * = complete ! model layout[1] = compat * * = complete ! model = types $macs = complete+numpad(mac) $applealu = complete+numpad(mac) $nokiamodels = complete+nokia * = complete ! layout option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle) * misc:typo = +typo(base) * misc:apl = +apl(level3) ! layout[1] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):1 * misc:typo = +typo(base):1 * misc:apl = +apl(level3):1 ! layout[2] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):2 * misc:typo = +typo(base):2 * misc:apl = +apl(level3):2 ! layout[3] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):3 * misc:typo = +typo(base):3 * misc:apl = +apl(level3):3 ! layout[4] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):4 * misc:typo = +typo(base):4 * misc:apl = +apl(level3):4 ! option = symbols grp:shift_toggle = +group(shifts_toggle) altwin:menu = +altwin(menu) altwin:menu_win = +altwin(menu_win) altwin:meta_alt = +altwin(meta_alt) altwin:alt_win = +altwin(alt_win) altwin:ctrl_win = +altwin(ctrl_win) altwin:ctrl_alt_win = +altwin(ctrl_alt_win) altwin:meta_win = +altwin(meta_win) altwin:left_meta_win = +altwin(left_meta_win) altwin:hyper_win = +altwin(hyper_win) altwin:alt_super_win = +altwin(alt_super_win) altwin:swap_lalt_lwin = +altwin(swap_lalt_lwin) altwin:swap_alt_win = +altwin(swap_alt_win) altwin:prtsc_rwin = +altwin(prtsc_rwin) grab:debug = +srvr_ctrl(grab_debug) grp:switch = +group(switch) grp:lswitch = +group(lswitch) grp:win_switch = +group(win_switch) grp:lwin_switch = +group(lwin_switch) grp:rwin_switch = +group(rwin_switch) grp:menu_switch = +group(menu_switch) grp:toggle = +group(toggle) grp:shifts_toggle = +group(shifts_toggle) grp:ctrls_toggle = +group(ctrls_toggle) grp:alts_toggle = +group(alts_toggle) grp:caps_toggle = +capslock(grouplock) grp:caps_switch = +capslock(groupshift) grp:shift_caps_toggle = +group(shift_caps_toggle) grp:shift_caps_switch = +group(shift_caps_switch) grp:win_space_toggle = +group(win_space_toggle) grp:win_menu_switch = +group(win_menu_switch) grp:alt_caps_toggle = +group(alt_caps_toggle) grp:alt_space_toggle = +group(alt_space_toggle) grp:menu_toggle = +group(menu_toggle) grp:lwin_toggle = +group(lwin_toggle) grp:lwin_latch = +group(lwin_latch) grp:rwin_toggle = +group(rwin_toggle) grp:rwin_latch_lock_clear = +group(rwin_latch_lock_clear) grp:lshift_toggle = +group(lshift_toggle) grp:rshift_toggle = +group(rshift_toggle) grp:rctrl_switch = +group(rctrl_switch) grp:lctrl_toggle = +group(lctrl_toggle) grp:rctrl_toggle = +group(rctrl_toggle) grp:lalt_toggle = +group(lalt_toggle) grp:sclk_toggle = +group(sclk_toggle) grp:sclk_latch_no_lock = +group(sclk_latch_no_lock) grp:lctrl_rctrl_switch = +group(lctrl_rctrl_switch) grp:lctrl_lwin_rctrl_menu = +group(lctrl_lwin_rctrl_menu) grp:lctrl_lalt_toggle = +group(lctrl_lalt_toggle) grp:rctrl_ralt_toggle = +group(rctrl_ralt_toggle) grp:ctrl_alt_toggle = +group(ctrl_alt_toggle) grp:ctrl_alt_toggle_bidir = +group(ctrl_alt_toggle_bidir) grp:lctrl_lshift_toggle = +group(lctrl_lshift_toggle) grp:rctrl_rshift_toggle = +group(rctrl_rshift_toggle) grp:ctrl_shift_toggle = +group(ctrl_shift_toggle) grp:ctrl_shift_toggle_bidir = +group(ctrl_shift_toggle_bidir) grp:lalt_lshift_toggle = +group(lalt_lshift_toggle) grp:ralt_rshift_toggle = +group(ralt_rshift_toggle) grp:alt_shift_toggle = +group(alt_shift_toggle) grp:alt_shift_toggle_bidir = +group(alt_shift_toggle_bidir) grp:lctrl_lwin_toggle = +group(lctrl_lwin_toggle) grp:menu_latch_group2 = +group(menu_latch_group2) grp:menu_latch_group2_lock = +group(menu_latch_group2_lock) grp:menu_latch = +group(menu_latch) grp:menu_latch_lock = +group(menu_latch_lock) grp:menu_latch_negative = +group(menu_latch_negative) grp:menu_latch_negative_lock = +group(menu_latch_negative_lock) lv3:switch = +level3(switch) lv3:ralt_switch = +level3(ralt_switch) lv3:ralt_switch_multikey = +level3(ralt_switch_multikey) lv3:ralt_latch = +level3(ralt_latch) lv3:ralt_alt = +level3(ralt_alt) lv3:lalt_switch = +level3(lalt_switch) lv3:alt_switch = +level3(alt_switch) lv3:menu_switch = +level3(menu_switch) lv3:win_switch = +level3(win_switch) lv3:lwin_switch = +level3(lwin_switch) lv3:rwin_switch = +level3(rwin_switch) lv3:enter_switch = +level3(enter_switch) lv3:4_switch_isolated = +level3(4_switch_isolated) lv3:9_switch_isolated = +level3(9_switch_isolated) caps:capslock = +capslock(capslock) caps:numlock = +capslock(numlock) caps:shiftlock = +capslock(shiftlock) caps:swapescape = +capslock(swapescape) caps:escape = +capslock(escape) caps:escape_shifted_capslock = +capslock(escape_shifted_capslock) caps:backspace = +capslock(backspace) caps:super = +capslock(super) caps:hyper = +capslock(hyper) caps:menu = +capslock(menu) caps:none = +capslock(none) caps:ctrl_modifier = +capslock(ctrl_modifier) ctrl:nocaps = +ctrl(nocaps) ctrl:lctrl_meta = +ctrl(lctrl_meta) ctrl:swapcaps = +ctrl(swapcaps) ctrl:swapcaps_hyper = +ctrl(swapcaps_hyper) ctrl:swapcaps_and_switch_layout = +ctrl(swapcaps_and_switch_layout) ctrl:ac_ctrl = +ctrl(ac_ctrl) ctrl:aa_ctrl = +ctrl(aa_ctrl) ctrl:rctrl_ralt = +ctrl(rctrl_ralt) ctrl:menu_rctrl = +ctrl(menu_rctrl) ctrl:ralt_rctrl = +ctrl(ralt_rctrl) ctrl:swap_lalt_lctl = +ctrl(swap_lalt_lctl) ctrl:swap_lwin_lctl = +ctrl(swap_lwin_lctl) ctrl:swap_rwin_rctl = +ctrl(swap_rwin_rctl) ctrl:swap_lalt_lctl_lwin = +ctrl(swap_lalt_lctl_lwin) compose:ralt = +compose(ralt) compose:lwin = +compose(lwin) compose:lwin-altgr = +compose(lwin-altgr) compose:rwin = +compose(rwin) compose:rwin-altgr = +compose(rwin-altgr) compose:menu = +compose(menu) compose:menu-altgr = +compose(menu-altgr) compose:lctrl = +compose(lctrl) compose:lctrl-altgr = +compose(lctrl-altgr) compose:rctrl = +compose(rctrl) compose:rctrl-altgr = +compose(rctrl-altgr) compose:caps = +compose(caps) compose:caps-altgr = +compose(caps-altgr) compose:102 = +compose(102) compose:102-altgr = +compose(102-altgr) compose:paus = +compose(paus) compose:prsc = +compose(prsc) compose:sclk = +compose(sclk) srvrkeys:none = +srvr_ctrl(no_srvr_keys) eurosign:e = +eurosign(e) eurosign:2 = +eurosign(2) eurosign:4 = +eurosign(4) eurosign:5 = +eurosign(5) rupeesign:4 = +rupeesign(4) keypad:oss = +keypad(oss) keypad:legacy = +keypad(legacy) keypad:legacy_wang = +keypad(legacy_wang) keypad:oss_wang = +keypad(oss_wang) keypad:future = +keypad(future) keypad:future_wang = +keypad(future_wang) keypad:hex = +keypad(ops)+keypad(hex) keypad:atm = +keypad(ops)+keypad(hex)+keypad(atm) nbsp:none = +nbsp(none) nbsp:level2 = +nbsp(level2) nbsp:level3 = +nbsp(level3) nbsp:level3s = +nbsp(level3s) nbsp:level3n = +nbsp(level3n) nbsp:level4 = +nbsp(level4) nbsp:level4n = +nbsp(level4n) nbsp:level4nl = +nbsp(level4nl) nbsp:zwnj2 = +nbsp(zwnj2) nbsp:zwnj2zwj3 = +nbsp(zwnj2zwj3) nbsp:zwnj2zwj3nb4 = +nbsp(zwnj2zwj3nb4) nbsp:zwnj2nb3 = +nbsp(zwnj2nb3) nbsp:zwnj2nb3s = +nbsp(zwnj2nb3s) nbsp:zwnj2nb3zwj4 = +nbsp(zwnj2nb3zwj4) nbsp:zwnj2nb3nnb4 = +nbsp(zwnj2nb3nnb4) nbsp:zwnj3zwj4 = +nbsp(zwnj3zwj4) japan:nicola_f_bs = +jp(nicola_f_bs) japan:hztg_escape = +jp(hztg_escape) korean:ralt_hangul = +kr(ralt_hangul) korean:rctrl_hangul = +kr(rctrl_hangul) korean:ralt_hanja = +kr(ralt_hanja) korean:rctrl_hanja = +kr(rctrl_hanja) kpdl:dot = +kpdl(dot) kpdl:comma = +kpdl(comma) kpdl:dotoss = +kpdl(dotoss) kpdl:dotoss_latin9 = +kpdl(dotoss_latin9) kpdl:commaoss = +kpdl(commaoss) kpdl:momayyezoss = +kpdl(momayyezoss) kpdl:kposs = +kpdl(kposs) kpdl:semi = +kpdl(semi) shift:breaks_caps = +shift(breaks_caps) shift:breaks_caps-v2 = +shift-v2(breaks_caps) esperanto:qwerty = +epo(qwerty) esperanto:dvorak = +epo(dvorak) esperanto:colemak = +epo(colemak) terminate:ctrl_alt_bksp = +terminate(ctrl_alt_bksp) keypad:pointerkeys = +keypad(pointerkeys) apple:alupckeys = +macintosh_vndr/apple(alupckeys) shift:both_capslock = +shift(both_capslock) shift:lshift_both_capslock = +shift(lshift_both_capslock) shift:rshift_both_capslock = +shift(rshift_both_capslock) shift:both_capslock_cancel = +shift(both_capslock_cancel) shift:lshift_both_capslock_cancel = +shift(lshift_both_capslock_cancel) shift:rshift_both_capslock_cancel = +shift(rshift_both_capslock_cancel) shift:both_shiftlock = +shift(both_shiftlock) shift:lshift_both_shiftlock = +shift(lshift_both_shiftlock) shift:rshift_both_shiftlock = +shift(rshift_both_shiftlock) solaris:sun_compat = +sun_vndr/solaris(sun_compat) lv3:caps_switch = +level3(caps_switch) lv3:bksl_switch = +level3(bksl_switch) lv3:lsgt_switch = +level3(lsgt_switch) lv3:caps_switch_latch = +level3(caps_switch_latch) lv3:bksl_switch_latch = +level3(bksl_switch_latch) lv3:bksl_latch_no_lock = +level3(bksl_latch_no_lock) lv3:lsgt_switch_latch = +level3(lsgt_switch_latch) lv3:lsgt_latch = +level3(lsgt_latch) lv5:lsgt_switch = +level5(lsgt_switch) lv5:ralt_switch = +level5(ralt_switch) lv5:lsgt_switch_lock = +level5(lsgt_switch_lock) lv5:ralt_switch_lock = +level5(ralt_switch_lock) lv5:lwin_switch_lock = +level5(lwin_switch_lock) lv5:rwin_switch_lock = +level5(rwin_switch_lock) lv5:lsgt_switch_lock_cancel = +level5(lsgt_switch_lock_cancel) lv5:ralt_switch_lock_cancel = +level5(ralt_switch_lock_cancel) lv5:lwin_switch_lock_cancel = +level5(lwin_switch_lock_cancel) lv5:rwin_switch_lock_cancel = +level5(rwin_switch_lock_cancel) parens:swap_brackets = +parens(swap_brackets) overlapping_modifiers:super_hyper = +overlapping_modifiers(super_hyper) overlapping_modifiers:meta = +overlapping_modifiers(meta) ! option = compat grp_led:num = +lednum(group_lock) grp_led:caps = +ledcaps(group_lock) grp_led:scroll = +ledscroll(group_lock) mod_led:compose = +ledcompose(compose) japan:kana_lock = +japan(kana_lock) caps:shiftlock = +ledcaps(shift_lock) caps:unlock-on-release = +caps(unlock-on-release) caps:unlock-on-press = +caps(unlock-on-press) grab:break_actions = +xfree86(grab_break) grp:lockOnRelease = +iso9995-v2(lockOnRelease) grp:lockOnPress = +iso9995-v2(lockOnPress) lv3:latchOnPress = +level3-v2(latchOnPress) lv3:latchOnRelease = +level3-v2(latchOnRelease) ! option = types caps:internal = +caps(internal) caps:internal_nocancel = +caps(internal_nocancel) caps:shift = +caps(shift) caps:shift_nocancel = +caps(shift_nocancel) numpad:pc = +numpad(pc) numpad:mac = +numpad(mac) numpad:microsoft = +numpad(microsoft) numpad:shift3 = +numpad(shift3) xkbcommon-libxkbcommon-54ee7ac/test/data/rules/evdev-modern000066400000000000000000000657061510033435100242410ustar00rootroot00000000000000// DO NOT EDIT THIS FILE - IT WAS AUTOGENERATED BY merge.py FROM rules/*.part // // // Rules for resolving XKB components for use with XFree86 // Copyright 1996 by Joseph Moss // // 2002 Modifier: Ivan Pascal The XFree86 Project // // If you want non-latin layouts implicitly include the en_US layout // uncomment lines below //! $nonlatin = am ara ben bd bg bt by cs deva ge gh gr guj guru il \ // in ir iku jp kan kh kr la lao lk mk mm mn mv mal olck \ // ori pk ru scc sy syr tel th tj tam ua uz // PC models ! $pcmodels = pc86 pc101 pc102 pc104 pc104alt pc105 // Jolla devices and keyboards ! $jollamodels = jollasbj // Microsoft models (using MS geometry) ! $msmodels = microsoft microsoft4000 microsoft7000 microsoftpro microsoftprousb microsoftprose microsoftsurface // Nokia devices and keyboards ! $nokiamodels = nokiasu8w nokiarx44 nokiarx51 // TypeMatrix geometries ! $tmgeometries = tm2020 tm2030PS2 tm2030USB tm2030USB-102 tm2030USB-106 // Layouts that provide further specializations for the OLPC ! $olpclayouts = af am ara br ca es et fr it kh kz in mn np ru th tr us ! $macbooks = macbook78 macbook79 ! $maclaptop = ibook powerbook macbook78 macbook79 ! $applealu = applealu_ansi applealu_iso applealu_jis ! $macs = macintosh macintosh_old ibook powerbook macbook78 macbook79 ! $macvendorlayouts = ch de dk fi fr gb is it latam nl no pt se us ! $azerty = be fr ! $qwertz = al cz de hr hu ro si sk // all layouts with 3rd and 4th groups ! $threelevellayouts = al az \ be br bt \ ca ch cs cz \ de dk \ ee es \ fi fo fr \ gb gr \ hu \ ie ir is it \ latam \ lk lt \ mn mt \ nl no \ pl pt \ ro \ se sk \ tr \ us \ vn \ za ! $thinkpads = thinkpad thinkpad60 thinkpadz60 ! $sun = sun_type6_jp sun_type6_usb sun_type6_euro_usb \ sun_type6_jp_usb sun_type6_unix_usb sun_type7_jp_usb \ sun_type7_usb sun_type7_euro_usb sun_type7_unix_usb ! $sun_jp = sun_type6_jp sun_type6_jp_usb sun_type7_jp_usb // Sun Type_6_7 keyboards with custom layouts ! $sun_custom = ara be br ca ch cz de dk \ ee es fi fr gb gr it jp \ kr lt lv nl no pl pt ro \ ru se sk tr tw ua us ! $sun_var = sun_type6 sun_type6_suncompat sun_type6_de sun_type6_fr \ sun_type7 sun_type7_suncompat suncompat ! $sun_compat = sun_type6 sun_type6_suncompat sun_type7_suncompat suncompat ! $evdevkbds = ibm_spacesaver ! $dvoraklayouts = br ca de ee es fr gb no pl se us ! model = keycodes applealu_jis = evdev+macintosh(jisevdev) $jollamodels = evdev+jolla(jolla) olpc = evdev+olpc(olpc) olpcm = evdev+olpc(olpcm) * = evdev ! layout[1] = keycodes $azerty = +aliases(azerty) $qwertz = +aliases(qwertz) * = +aliases(qwerty) ! layout = keycodes $azerty = +aliases(azerty) $qwertz = +aliases(qwertz) * = +aliases(qwerty) ! option = keycodes ! model layout = geometry thinkpad us = thinkpad(us) ! model = geometry microsoftelite = microsoft(elite) $msmodels = microsoft(natural) dell101 = dell(dell101) dellm65 = dell(dellm65) latitude = dell(latitude) flexpro = keytronic(FlexPro) hp6000 = hp(omnibook) hpmini110 = hp(mini110) hpdv5 = hp(dv5) omnikey101 = northgate(omnikey101) sanwaskbkg3 = sanwa(sanwaskbkg3) $pcmodels = pc(%m) everex = everex(STEPnote) thinkpad = thinkpad(intl) thinkpad60 = thinkpad(60) thinkpadz60 = thinkpad(60) apex300 = steelseries(apex300) $tmgeometries = typematrix(%m) winbook = winbook(XP5) pc98 = nec(pc98) $applealu = macintosh(%m) $macbooks = macintosh(%m) $macs = macintosh(macintosh) hhk = hhk(basic) kinesis = kinesis(model100) $nokiamodels = nokia(%m) sun_type6_jp = sun(type6jp) sun_type6_usb = sun(type6) sun_type6_euro_usb = sun(type6tuv) sun_type6_jp_usb = sun(type6jp) sun_type6_unix_usb = sun(type6unix) sun_type7_jp_usb = sun(type6jp) sun_type7_usb = sun(type7) sun_type7_euro_usb = sun(type7tuv) sun_type7_unix_usb = sun(type7unix) * = pc(pc104) ! model layout[first] variant[first] = symbols * ben basic = pc+in(ben) * ben probhat = pc+in(ben_probhat) * dev basic = pc+in(deva) * dvorak $dvoraklayouts = pc+%v(dvorak) * dvorak basic = pc+us(dvorak) * dvorak pl_basic = pc+pl(dvorak) * dvorak pl = pc+pl(dvorak_quotes) * dvorak pl_altquotes = pc+pl(dvorak_altquotes) * dzdwi basic = pc+bt(basic) * fi basic = pc+fi(classic) * ge azerty_tskapo = pc+fr(geo) * guj basic = pc+in(guj) * gur basic = pc+in(guru) * ie laptop = pc+ie(basic) * ie CloGaelachLaptop = pc+ie(CloGaelach) * in urd = pc+in(urd-phonetic) * iu basic = pc+ca(ike) * lo basic = pc+la(basic) * kan basic = pc+in(kan) * mal basic = pc+in(mal) * mal mlplusnum = pc+in(mal) * ogham basic = pc+ie(ogam) * ogham laptop = pc+ie(ogam) * ogham is434 = pc+ie(ogam_is434) * ogham is434laptop = pc+ie(ogam_is434) * ori basic = pc+in(ori) * ro de = pc+ro(winkeys) * ro us = pc+ro(std) * ro academic = pc+ro(std) * ro std_comma = pc+ro(std) * ro comma = pc+ro(basic) * ru os = pc+ru(os_legacy) * pk urd = pc+pk(urd-phonetic) * sapmi basic = pc+no(smi) * sapmi nodeadkeys = pc+no(smi_nodeadkeys) * sapmi sefi = pc+fi(smi) * sin phonetic-static = pc+in(sin_phonetic) * syr basic = pc+sy(syc) * syr phonetic = pc+sy(syc_phonetic) * tam INSCRIPT = pc+in(tam) * tam UNI = pc+in(tam_unicode) * tam NUMERAL-KEYBOARD = pc+in(tam_keyboard_with_numerals) * tam TAB = pc+in(tam_TAB) * tam TSCII = pc+in(tam_TSCII) * tel basic = pc+in(tel) * yu basic = pc+srp(latin) * yu unicode = pc+srp(latinunicode) * yu yz = pc+srp(latinyz) * yu unicodeyz = pc+srp(latinunicodeyz) classmate us intl = pc+us(classmate-intl) classmate us alt-intl = pc+us(classmate-alt-intl) classmate us altgr-intl = pc+us(classmate-altgr-intl) nokiarx51 cz qwerty = nokia_vndr/rx-51(cz_qwerty) * $sun_custom $sun_var = pc+sun_vndr/%l%(v) ! model layout[first] = symbols * ar = pc+ara * ben = pc+in(ben) * bs = pc+ba * cs = pc+rs * cz_qwerty = pc+cz(qwerty) * dev = pc+in(deva) * dvorak = pc+us(dvorak) * dzdwi = pc+bt * el = pc+gr * en_US = pc+latin * guj = pc+in(guj) * gur = pc+in(guru) * iu = pc+ca(ike) * lo = pc+la * kan = pc+in(kan) * mi = pc+mao * ogham = pc+ie(ogam) * ori = pc+ie(ori) * sapmi = pc+no(smi) * sr = pc+srp * syr = pc+sy(syc) * tel = pc+in(tel) * tml = pc+in(tam) * yu = pc+srp * fr-latin9 = pc+fr(latin9) * us_intl = pc+us(alt-intl) * ben(basic) = pc+in(ben) * ben(probhat) = pc+in(ben_probhat) * dev(basic) = pc+in(deva) * dvorak($dvoraklayouts) = pc+%v(dvorak) * dvorak(basic) = pc+us(dvorak) * dvorak(pl_basic) = pc+pl(dvorak) * dvorak(pl) = pc+pl(dvorak_quotes) * dvorak(pl_altquotes) = pc+pl(dvorak_altquotes) * dzdwi(basic) = pc+bt(basic) * fi(basic) = pc+fi(classic) * ge(azerty_tskapo) = pc+fr(geo) * guj(basic) = pc+in(guj) * gur(basic) = pc+in(guru) * ie(laptop) = pc+ie(basic) * ie(CloGaelachLaptop) = pc+ie(CloGaelach) * in(urd) = pc+in(urd-phonetic) * iu(basic) = pc+ca(ike) * lo(basic) = pc+la(basic) * kan(basic) = pc+in(kan) * mal(basic) = pc+in(mal) * mal(mlplusnum) = pc+in(mal) * ogham(basic) = pc+ie(ogam) * ogham(laptop) = pc+ie(ogam) * ogham(is434) = pc+ie(ogam_is434) * ogham(is434laptop) = pc+ie(ogam_is434) * ori(basic) = pc+in(ori) * ro(de) = pc+ro(winkeys) * ro(us) = pc+ro(std) * ro(academic) = pc+ro(std) * ro(std_comma) = pc+ro(std) * ro(comma) = pc+ro(basic) * ru(os) = pc+ru(os_legacy) * pk(urd) = pc+pk(urd-phonetic) * sapmi(basic) = pc+no(smi) * sapmi(nodeadkeys) = pc+no(smi_nodeadkeys) * sapmi(sefi) = pc+fi(smi) * sin(phonetic-static) = pc+in(sin_phonetic) * syr(basic) = pc+sy(syc) * syr(phonetic) = pc+sy(syc_phonetic) * tam(INSCRIPT) = pc+in(tam) * tam(UNI) = pc+in(tam_unicode) * tam(NUMERAL-KEYBOARD) = pc+in(tam_keyboard_with_numerals) * tam(TAB) = pc+in(tam_TAB) * tam(TSCII) = pc+in(tam_TSCII) * tel(basic) = pc+in(tel) * yu(basic) = pc+srp(latin) * yu(unicode) = pc+srp(latinunicode) * yu(yz) = pc+srp(latinyz) * yu(unicodeyz) = pc+srp(latinunicodeyz) ! model layout = symbols ataritt $nonlatin = xfree68_vndr/ataritt(us)+%l[%i]%(v[%i]):2 ataritt * = xfree68_vndr/ataritt(us)+%l[%i]%(v[%i]) amiga $nonlatin = xfree68_vndr/amiga(usa1)+%l[%i]%(v[%i]):2 amiga * = xfree68_vndr/amiga(usa1)+%l[%i]%(v[%i]) classmate us = pc+%l[%i](classmate) empty * = empty(basic) * empty = empty(basic) jollasbj $nonlatin = jolla_vndr/sbj(common)+us+%l[%i]%(v[%i]):2 jollasbj * = jolla_vndr/sbj(common)+%l[%i]%(v[%i]) $sun $sun_custom = pc+sun_vndr/%l[%i]%(v[%i]) pc98 nec_vndr/jp = nec_vndr/jp(pc98) macintosh_old us = macintosh_vndr/us(oldmac) macintosh_old en_US = macintosh_vndr/us(oldmac) macintosh_old $macvendorlayouts = macintosh_vndr/us(oldmac)+macintosh_vndr/%l%(v) macintosh_old $nonlatin = macintosh_vndr/us(oldmac)+%l[%i]%(v[%i]):2 macintosh_old * = macintosh_vndr/us(oldmac)+%l[%i]%(v[%i]) applealu_jis jp = macintosh_vndr/apple(alukbd)+macintosh_vndr/jp(usmac)+macintosh_vndr/jp(mac):2 applealu_jis * = macintosh_vndr/apple(alukbd)+%l[%i]%(v[%i])+macintosh_vndr/jp(mac):2 $applealu $macvendorlayouts = macintosh_vndr/apple(alukbd)+macintosh_vndr/%l[%i]%(v[%i]) $applealu * = macintosh_vndr/apple(alukbd)+%l[%i]%(v[%i]) $macs en_US = pc+macintosh_vndr/us(extended) $macs $macvendorlayouts = pc+macintosh_vndr/%l[%i]%(v[%i]) nokiarx44 * = nokia_vndr/rx-44(%l[%i]) nokiarx51 cz(qwerty) = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(cz_qwerty) nokiarx51 * = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(%l[%i]%_v[%i]) nokiasu8w * = nokia_vndr/su-8w(%l[%i]) olpc $olpclayouts = olpc+%l[%i]%(m) olpc * = olpc+%l[%i]%(v[%i]) olpcm $olpclayouts = olpc+%l[%i]%(m) olpcm * = olpc+%l[%i]%(v[%i]) $thinkpads br = pc+br(thinkpad) sl-c3x00 * = pc+sharp_vndr/sl-c3x00(basic) ws003sh * = pc+sharp_vndr/ws003sh(basic) ws007sh * = pc+sharp_vndr/ws007sh(basic) ws011sh * = pc+sharp_vndr/ws011sh(basic) ws020sh * = pc+sharp_vndr/ws020sh(basic) * $nonlatin = pc+us+%l[%i]%(v[%i]):2 ! model layout[first] = symbols * * = pc+%l[%i]%(v[%i]) ! model layout[later] = symbols * ar = +ara%(v[%i]):%i * ben = +in(ben):%i * bs = +ba%(v[%i]):%i * cs = +rs%(v[%i]):%i * cz_qwerty = +cz(qwerty):%i * dev = +in(deva):%i * dvorak = +us(dvorak):%i * dzdwi = +bt%(v[%i]):%i * el = +gr%(v[%i]):%i * en_US = +latin%(v[%i]):%i * guj = +in(guj):%i * gur = +in(guru):%i * iu = +ca(ike):%i * lo = +la%(v[%i]):%i * kan = +in(kan):%i * mi = +mao%(v[%i]):%i * ogham = +ie(ogam):%i * ori = +ie(ori):%i * sapmi = +no(smi):%i * sr = +srp%(v[%i]):%i * syr = +sy(syc):%i * tel = +in(tel):%i * tml = +in(tam):%i * yu = +srp%(v[%i]):%i * fr-latin9 = +fr(latin9):%i * us_intl = +us(alt-intl):%i * ben(basic) = +in(ben):%i * ben(probhat) = +in(ben_probhat):%i * dev(basic) = +in(deva):%i * dvorak($dvoraklayouts) = +%v(dvorak):%i * dvorak(basic) = +us(dvorak):%i * dvorak(pl_basic) = +pl(dvorak):%i * dvorak(pl) = +pl(dvorak_quotes):%i * dvorak(pl_altquotes) = +pl(dvorak_altquotes):%i * dzdwi(basic) = +bt(basic):%i * fi(basic) = +fi(classic):%i * ge(azerty_tskapo) = +fr(geo):%i * guj(basic) = +in(guj):%i * gur(basic) = +in(guru):%i * ie(laptop) = +ie(basic):%i * ie(CloGaelachLaptop) = +ie(CloGaelach):%i * in(urd) = +in(urd-phonetic):%i * iu(basic) = +ca(ike):%i * lo(basic) = +la(basic):%i * kan(basic) = +in(kan):%i * mal(basic) = +in(mal):%i * mal(mlplusnum) = +in(mal):%i * ogham(basic) = +ie(ogam):%i * ogham(laptop) = +ie(ogam):%i * ogham(is434) = +ie(ogam_is434):%i * ogham(is434laptop) = +ie(ogam_is434):%i * ori(basic) = +in(ori):%i * ro(de) = +ro(winkeys):%i * ro(us) = +ro(std):%i * ro(academic) = +ro(std):%i * ro(std_comma) = +ro(std):%i * ro(comma) = +ro(basic):%i * ru(os) = +ru(os_legacy):%i * pk(urd) = +pk(urd-phonetic):%i * sapmi(basic) = +no(smi):%i * sapmi(nodeadkeys) = +no(smi_nodeadkeys):%i * sapmi(sefi) = +fi(smi):%i * sin(phonetic-static) = +in(sin_phonetic):%i * syr(basic) = +sy(syc):%i * syr(phonetic) = +sy(syc_phonetic):%i * tam(INSCRIPT) = +in(tam):%i * tam(UNI) = +in(tam_unicode):%i * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):%i * tam(TAB) = +in(tam_TAB):%i * tam(TSCII) = +in(tam_TSCII):%i * tel(basic) = +in(tel):%i * yu(basic) = +srp(latin):%i * yu(unicode) = +srp(latinunicode):%i * yu(yz) = +srp(latinyz):%i * yu(unicodeyz) = +srp(latinunicodeyz):%i nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):%i nokiarx51 * = +nokia_vndr/rx-51(%l[%i]%_v[%i]):%i $sun $sun_custom = +sun_vndr/%l[%i]%(v[%i]):%i * * = +%l[%i]%(v[%i]):%i ! model layout[later] variant[later] = symbols * ben basic = +in(ben):%i * ben probhat = +in(ben_probhat):%i * dev basic = +in(deva):%i * dvorak $dvoraklayouts = +%v(dvorak):%i * dvorak basic = +us(dvorak):%i * dvorak pl_basic = +pl(dvorak):%i * dvorak pl = +pl(dvorak_quotes):%i * dvorak pl_altquotes = +pl(dvorak_altquotes):%i * dzdwi basic = +bt(basic):%i * fi basic = +fi(classic):%i * ge azerty_tskapo = +fr(geo):%i * guj basic = +in(guj):%i * gur basic = +in(guru):%i * ie laptop = +ie(basic):%i * ie CloGaelachLaptop = +ie(CloGaelach):%i * in urd = +in(urd-phonetic):%i * iu basic = +ca(ike):%i * lo basic = +la(basic):%i * kan basic = +in(kan):%i * mal basic = +in(mal):%i * mal mlplusnum = +in(mal):%i * ogham basic = +ie(ogam):%i * ogham laptop = +ie(ogam):%i * ogham is434 = +ie(ogam_is434):%i * ogham is434laptop = +ie(ogam_is434):%i * ori basic = +in(ori):%i * ro de = +ro(winkeys):%i * ro us = +ro(std):%i * ro academic = +ro(std):%i * ro std_comma = +ro(std):%i * ro comma = +ro(basic):%i * ru os = +ru(os_legacy):%i * pk urd = +pk(urd-phonetic):%i * sapmi basic = +no(smi):%i * sapmi nodeadkeys = +no(smi_nodeadkeys):%i * sapmi sefi = +fi(smi):%i * sin phonetic-static = +in(sin_phonetic):%i * syr basic = +sy(syc):%i * syr phonetic = +sy(syc_phonetic):%i * tam INSCRIPT = +in(tam):%i * tam UNI = +in(tam_unicode):%i * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):%i * tam TAB = +in(tam_TAB):%i * tam TSCII = +in(tam_TSCII):%i * tel basic = +in(tel):%i * yu basic = +srp(latin):%i * yu unicode = +srp(latinunicode):%i * yu yz = +srp(latinyz):%i * yu unicodeyz = +srp(latinunicodeyz):%i ! model = symbols $evdevkbds = +inet(evdev)+inet(%m) chromebook = +inet(evdev)+inet(chromebook) applealu_jis = +inet(evdev)+macintosh_vndr/jp(alujiskeys) * = +inet(evdev) ! layout[any] variant[any] = compat de neo = +caps(caps_lock):%i+misc(assign_shift_left_action):%i+level5(level5_lock):%i de adnw = +caps(caps_lock):%i+misc(assign_shift_left_action):%i+level5(level5_lock):%i de koy = +caps(caps_lock):%i+misc(assign_shift_left_action):%i+level5(level5_lock):%i de bone = +caps(caps_lock):%i+misc(assign_shift_left_action):%i+level5(level5_lock):%i de bone_eszett_home = +caps(caps_lock):%i+misc(assign_shift_left_action):%i+level5(level5_lock):%i de neo_qwertz = +caps(caps_lock):%i+misc(assign_shift_left_action):%i+level5(level5_lock):%i de neo_qwerty = +caps(caps_lock):%i+misc(assign_shift_left_action):%i+level5(level5_lock):%i jp $sun_compat = +complete+japan(kana_lock):%i ! model layout[single] = compat pc98 nec_vndr/jp = pc98(basic) * jp = complete+japan olpc * = olpc olpcm * = olpc * * = complete ! model layout[first] = compat * * = complete ! model = types $macs = complete+numpad(mac) $applealu = complete+numpad(mac) $nokiamodels = complete+nokia * = complete ! layout[any] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):%i * misc:apl = +apl(level3):%i ! option = symbols grp:shift_toggle = +group(shifts_toggle) altwin:menu = +altwin(menu) altwin:menu_win = +altwin(menu_win) altwin:meta_alt = +altwin(meta_alt) altwin:alt_win = +altwin(alt_win) altwin:ctrl_win = +altwin(ctrl_win) altwin:ctrl_alt_win = +altwin(ctrl_alt_win) altwin:meta_win = +altwin(meta_win) altwin:left_meta_win = +altwin(left_meta_win) altwin:hyper_win = +altwin(hyper_win) altwin:alt_super_win = +altwin(alt_super_win) altwin:swap_lalt_lwin = +altwin(swap_lalt_lwin) altwin:swap_alt_win = +altwin(swap_alt_win) altwin:prtsc_rwin = +altwin(prtsc_rwin) grab:debug = +srvr_ctrl(grab_debug) grp:switch = +group(switch) grp:lswitch = +group(lswitch) grp:win_switch = +group(win_switch) grp:lwin_switch = +group(lwin_switch) grp:rwin_switch = +group(rwin_switch) grp:menu_switch = +group(menu_switch) grp:toggle = +group(toggle) grp:shifts_toggle = +group(shifts_toggle) grp:ctrls_toggle = +group(ctrls_toggle) grp:alts_toggle = +group(alts_toggle) grp:caps_toggle = +capslock(grouplock) grp:caps_switch = +capslock(groupshift) grp:shift_caps_toggle = +group(shift_caps_toggle) grp:shift_caps_switch = +group(shift_caps_switch) grp:win_space_toggle = +group(win_space_toggle) grp:win_menu_switch = +group(win_menu_switch) grp:alt_caps_toggle = +group(alt_caps_toggle) grp:alt_space_toggle = +group(alt_space_toggle) grp:menu_toggle = +group(menu_toggle) grp:lwin_toggle = +group(lwin_toggle) grp:rwin_toggle = +group(rwin_toggle) grp:lshift_toggle = +group(lshift_toggle) grp:rshift_toggle = +group(rshift_toggle) grp:rctrl_switch = +group(rctrl_switch) grp:lctrl_toggle = +group(lctrl_toggle) grp:rctrl_toggle = +group(rctrl_toggle) grp:lalt_toggle = +group(lalt_toggle) grp:sclk_toggle = +group(sclk_toggle) grp:sclk_latch_no_lock = +group(sclk_latch_no_lock) grp:lctrl_rctrl_switch = +group(lctrl_rctrl_switch) grp:lctrl_lwin_rctrl_menu = +group(lctrl_lwin_rctrl_menu) grp:lctrl_lalt_toggle = +group(lctrl_lalt_toggle) grp:rctrl_ralt_toggle = +group(rctrl_ralt_toggle) grp:ctrl_alt_toggle = +group(ctrl_alt_toggle) grp:ctrl_alt_toggle_bidir = +group(ctrl_alt_toggle_bidir) grp:lctrl_lshift_toggle = +group(lctrl_lshift_toggle) grp:rctrl_rshift_toggle = +group(rctrl_rshift_toggle) grp:ctrl_shift_toggle = +group(ctrl_shift_toggle) grp:ctrl_shift_toggle_bidir = +group(ctrl_shift_toggle_bidir) grp:lalt_lshift_toggle = +group(lalt_lshift_toggle) grp:ralt_rshift_toggle = +group(ralt_rshift_toggle) grp:alt_shift_toggle = +group(alt_shift_toggle) grp:alt_shift_toggle_bidir = +group(alt_shift_toggle_bidir) grp:lctrl_lwin_toggle = +group(lctrl_lwin_toggle) grp:menu_latch_group2 = +group(menu_latch_group2) grp:menu_latch_group2_lock = +group(menu_latch_group2_lock) grp:menu_latch = +group(menu_latch) grp:menu_latch_lock = +group(menu_latch_lock) grp:menu_latch_negative = +group(menu_latch_negative) grp:menu_latch_negative_lock = +group(menu_latch_negative_lock) lv3:switch = +level3(switch) lv3:ralt_switch = +level3(ralt_switch) lv3:ralt_switch_multikey = +level3(ralt_switch_multikey) lv3:ralt_latch = +level3(ralt_latch) lv3:ralt_alt = +level3(ralt_alt) lv3:lalt_switch = +level3(lalt_switch) lv3:alt_switch = +level3(alt_switch) lv3:menu_switch = +level3(menu_switch) lv3:win_switch = +level3(win_switch) lv3:lwin_switch = +level3(lwin_switch) lv3:rwin_switch = +level3(rwin_switch) lv3:enter_switch = +level3(enter_switch) lv3:4_switch_isolated = +level3(4_switch_isolated) lv3:9_switch_isolated = +level3(9_switch_isolated) caps:capslock = +capslock(capslock) caps:numlock = +capslock(numlock) caps:shiftlock = +capslock(shiftlock) caps:swapescape = +capslock(swapescape) caps:escape = +capslock(escape) caps:escape_shifted_capslock = +capslock(escape_shifted_capslock) caps:backspace = +capslock(backspace) caps:super = +capslock(super) caps:hyper = +capslock(hyper) caps:menu = +capslock(menu) caps:none = +capslock(none) caps:ctrl_modifier = +capslock(ctrl_modifier) ctrl:nocaps = +ctrl(nocaps) ctrl:lctrl_meta = +ctrl(lctrl_meta) ctrl:swapcaps = +ctrl(swapcaps) ctrl:swapcaps_hyper = +ctrl(swapcaps_hyper) ctrl:swapcaps_and_switch_layout = +ctrl(swapcaps_and_switch_layout) ctrl:ac_ctrl = +ctrl(ac_ctrl) ctrl:aa_ctrl = +ctrl(aa_ctrl) ctrl:rctrl_ralt = +ctrl(rctrl_ralt) ctrl:menu_rctrl = +ctrl(menu_rctrl) ctrl:ralt_rctrl = +ctrl(ralt_rctrl) ctrl:swap_lalt_lctl = +ctrl(swap_lalt_lctl) ctrl:swap_lwin_lctl = +ctrl(swap_lwin_lctl) ctrl:swap_rwin_rctl = +ctrl(swap_rwin_rctl) ctrl:swap_lalt_lctl_lwin = +ctrl(swap_lalt_lctl_lwin) compose:ralt = +compose(ralt) compose:lwin = +compose(lwin) compose:lwin-altgr = +compose(lwin-altgr) compose:rwin = +compose(rwin) compose:rwin-altgr = +compose(rwin-altgr) compose:menu = +compose(menu) compose:menu-altgr = +compose(menu-altgr) compose:lctrl = +compose(lctrl) compose:lctrl-altgr = +compose(lctrl-altgr) compose:rctrl = +compose(rctrl) compose:rctrl-altgr = +compose(rctrl-altgr) compose:caps = +compose(caps) compose:caps-altgr = +compose(caps-altgr) compose:102 = +compose(102) compose:102-altgr = +compose(102-altgr) compose:paus = +compose(paus) compose:prsc = +compose(prsc) compose:sclk = +compose(sclk) srvrkeys:none = +srvr_ctrl(no_srvr_keys) eurosign:e = +eurosign(e) eurosign:2 = +eurosign(2) eurosign:4 = +eurosign(4) eurosign:5 = +eurosign(5) rupeesign:4 = +rupeesign(4) keypad:oss = +keypad(oss) keypad:legacy = +keypad(legacy) keypad:legacy_wang = +keypad(legacy_wang) keypad:oss_wang = +keypad(oss_wang) keypad:future = +keypad(future) keypad:future_wang = +keypad(future_wang) keypad:hex = +keypad(ops)+keypad(hex) keypad:atm = +keypad(ops)+keypad(hex)+keypad(atm) nbsp:none = +nbsp(none) nbsp:level2 = +nbsp(level2) nbsp:level3 = +nbsp(level3) nbsp:level3s = +nbsp(level3s) nbsp:level3n = +nbsp(level3n) nbsp:level4 = +nbsp(level4) nbsp:level4n = +nbsp(level4n) nbsp:level4nl = +nbsp(level4nl) nbsp:zwnj2 = +nbsp(zwnj2) nbsp:zwnj2zwj3 = +nbsp(zwnj2zwj3) nbsp:zwnj2zwj3nb4 = +nbsp(zwnj2zwj3nb4) nbsp:zwnj2nb3 = +nbsp(zwnj2nb3) nbsp:zwnj2nb3s = +nbsp(zwnj2nb3s) nbsp:zwnj2nb3zwj4 = +nbsp(zwnj2nb3zwj4) nbsp:zwnj2nb3nnb4 = +nbsp(zwnj2nb3nnb4) nbsp:zwnj3zwj4 = +nbsp(zwnj3zwj4) japan:nicola_f_bs = +jp(nicola_f_bs) japan:hztg_escape = +jp(hztg_escape) korean:ralt_hangul = +kr(ralt_hangul) korean:rctrl_hangul = +kr(rctrl_hangul) korean:ralt_hanja = +kr(ralt_hanja) korean:rctrl_hanja = +kr(rctrl_hanja) kpdl:dot = +kpdl(dot) kpdl:comma = +kpdl(comma) kpdl:dotoss = +kpdl(dotoss) kpdl:dotoss_latin9 = +kpdl(dotoss_latin9) kpdl:commaoss = +kpdl(commaoss) kpdl:momayyezoss = +kpdl(momayyezoss) kpdl:kposs = +kpdl(kposs) kpdl:semi = +kpdl(semi) shift:breaks_caps = +shift(breaks_caps) shift:breaks_caps-v2 = +shift-v2(breaks_caps) esperanto:qwerty = +epo(qwerty) esperanto:dvorak = +epo(dvorak) esperanto:colemak = +epo(colemak) terminate:ctrl_alt_bksp = +terminate(ctrl_alt_bksp) keypad:pointerkeys = +keypad(pointerkeys) apple:alupckeys = +macintosh_vndr/apple(alupckeys) shift:both_capslock = +shift(both_capslock) shift:lshift_both_capslock = +shift(lshift_both_capslock) shift:rshift_both_capslock = +shift(rshift_both_capslock) shift:both_capslock_cancel = +shift(both_capslock_cancel) shift:lshift_both_capslock_cancel = +shift(lshift_both_capslock_cancel) shift:rshift_both_capslock_cancel = +shift(rshift_both_capslock_cancel) shift:both_shiftlock = +shift(both_shiftlock) shift:lshift_both_shiftlock = +shift(lshift_both_shiftlock) shift:rshift_both_shiftlock = +shift(rshift_both_shiftlock) solaris:sun_compat = +sun_vndr/solaris(sun_compat) lv3:caps_switch = +level3(caps_switch) lv3:bksl_switch = +level3(bksl_switch) lv3:lsgt_switch = +level3(lsgt_switch) lv3:caps_switch_latch = +level3(caps_switch_latch) lv3:bksl_switch_latch = +level3(bksl_switch_latch) lv3:bksl_latch_no_lock = +level3(bksl_latch_no_lock) lv3:lsgt_switch_latch = +level3(lsgt_switch_latch) lv5:lsgt_switch = +level5(lsgt_switch) lv5:ralt_switch = +level5(ralt_switch) lv5:lsgt_switch_lock = +level5(lsgt_switch_lock) lv5:ralt_switch_lock = +level5(ralt_switch_lock) lv5:lwin_switch_lock = +level5(lwin_switch_lock) lv5:rwin_switch_lock = +level5(rwin_switch_lock) lv5:lsgt_switch_lock_cancel = +level5(lsgt_switch_lock_cancel) lv5:ralt_switch_lock_cancel = +level5(ralt_switch_lock_cancel) lv5:lwin_switch_lock_cancel = +level5(lwin_switch_lock_cancel) lv5:rwin_switch_lock_cancel = +level5(rwin_switch_lock_cancel) parens:swap_brackets = +parens(swap_brackets) misc:typo = +typo(base):all ! option = compat grp_led:num = +lednum(group_lock) grp_led:caps = +ledcaps(group_lock) grp_led:scroll = +ledscroll(group_lock) mod_led:compose = +ledcompose(compose) japan:kana_lock = +japan(kana_lock) caps:shiftlock = +ledcaps(shift_lock) caps:unlock-on-release = +caps(unlock-on-release) caps:unlock-on-press = +caps(unlock-on-press) grab:break_actions = +xfree86(grab_break) grp:lockOnRelease = +iso9995-v2(lockOnRelease) grp:lockOnPress = +iso9995-v2(lockOnPress) lv3:latchOnPress = +level3-v2(latchOnPress) lv3:latchOnRelease = +level3-v2(latchOnRelease) ! option = types caps:internal = +caps(internal) caps:internal_nocancel = +caps(internal_nocancel) caps:shift = +caps(shift) caps:shift_nocancel = +caps(shift_nocancel) numpad:pc = +numpad(pc) numpad:mac = +numpad(mac) numpad:microsoft = +numpad(microsoft) numpad:shift3 = +numpad(shift3) xkbcommon-libxkbcommon-54ee7ac/test/data/rules/evdev-pure-virtual-mods000066400000000000000000000020551510033435100263400ustar00rootroot00000000000000// Special rules to test pure virtual modifiers. // Needed for a test involving `applealu_ansi`. ! $macvendorlayouts = ch de dk fi fr gb is it latam nl no pt se us ! $applealu = applealu_ansi applealu_iso applealu_jis ! model layout = symbols $applealu $macvendorlayouts = macintosh_vndr/apple(alukbd)+macintosh_vndr/%l%(v) * * = pc(pc105-pure-virtual-modifiers)+%l%(v) ! model layout[1] = symbols * * = pc(pc105-pure-virtual-modifiers)+%l[1]%(v[1]) ! model = types * = virtual_modifiers(ordered_explicit_mapping)+complete ! model = types $macs = +numpad(mac) $applealu = +numpad(mac) $nokiamodels = +nokia ! model layout = compat * * = complete+basic(pure-virtual-modifiers) ! model layout[1] = compat * * = complete+basic(pure-virtual-modifiers) // The rules in the current file will *not* be overridden by the // following include, because the keymap sections do not start with // an explicit merge operator. E.g. `[pc(x), pc]` is merged as `pc(x)`, // while `[pc, +us]` is merged as `pc+us`. ! include evdev xkbcommon-libxkbcommon-54ee7ac/test/data/rules/evdev-xkbcommon000066400000000000000000001143251510033435100247420ustar00rootroot00000000000000// DO NOT EDIT THIS FILE - IT WAS AUTOGENERATED BY merge.sh FROM rules/*.part // // Rules for resolving XKB components for use with XFree86 // Copyright 1996 by Joseph Moss // // 2002 Modifier: Ivan Pascal The XFree86 Project // // If you want non-latin layouts implicitly include the en_US layout // uncomment lines below //! $nonlatin = am ara ben bd bg bt by cs deva ge gh gr guj guru il \ // in ir iku jp kan kh kr la lao lk mk mm mn mv mal ori pk \ // ru scc sy syr tel th tj tam ua uz // PC models ! $pcmodels = pc101 pc102 pc104 pc105 // Microsoft models (using MS geometry) ! $msmodels = microsoft microsoft4000 microsoft7000 microsoftpro microsoftprousb microsoftprose // Nokia devices and keyboards ! $nokiamodels = nokiasu8w nokiarx44 nokiarx51 // PC geometries - they have special geometry but symbols are mostly pc105 ! $pcgeometries = latitude // TypeMatrix geometries ! $tmgeometries = tm2020 tm2030PS2 tm2030USB tm2030USB-102 tm2030USB-106 // Layouts that provide further specializations for the OLPC ! $olpclayouts = af am ara br ca es et fr it kh kz in mn np ru th tr us ! $macbooks = macbook78 macbook79 ! $maclaptop = ibook powerbook macbook78 macbook79 ! $applealu = applealu_ansi applealu_iso applealu_jis ! $macs = macintosh macintosh_old ibook powerbook macbook78 macbook79 ! $macvendorlayouts = ch de dk fi fr gb is it latam nl no pt se us ! $azerty = be fr ! $qwertz = al cz de hr hu ro si sk ! $inetkbds = acer_c300 acer_ferrari4k acer_laptop \ airkey \ apple armada azonaRF2300 \ benqx brother \ btc5113rf btc9000 btc9000a btc9001ah btc5090 btc9019u \ cherryblue cherrybluea cherryblueb \ cherrycyboard cherrycmexpert \ chicony chicony0108 chicony0420 chicony9885 \ compalfl90 \ compaqeak8 compaqik7 compaqik13 compaqik18 \ creativedw7000 \ cymotionlinux \ dell dellm65 inspiron dellusbmm \ emachines ennyah_dkb1008 evdev \ genius geniuscomfy2 \ gyration honeywell_euroboard \ hp250x hp5xx hp500fa hpdv5 \ hpi6 hpxe3gc hpxe3gf hpxe4xxx hpxt1000 hpzt11xx htcdream \ ibm_spacesaver ipaq inspiron intel \ logiaccess logicda logicink \ logiex110 logiclx300 \ logiinkse logiinkseusb logiitc logiik \ logitech_base itouch logiultrax \ logitech_g15 \ logidinovo logidinovoedge \ microsoft4000 microsoft7000 microsoftinet microsoftprousb microsoftprooem microsoftprose \ microsoftoffice microsoftmult \ mx1998 mx2500 mx2750 \ oretec \ pc105 \ presario propeller \ qtronix \ rapidaccess rapidaccess2 thinkpad60 \ samsung4500 samsung4510 \ silvercrest \ sk1300 sk2500 sk6200 sk7100 \ sven sven303 symplon \ toshiba_s3000 trust trustda \ unitekkb1925 yahoo // all layouts with 3rd and 4th groups ! $threelevellayouts = al az \ be br bt \ ca ch cs cz \ de dk \ ee es \ fi fo fr \ gb gr \ hu \ ie ir is it \ latam \ lk lt \ mn mt \ nl no \ pl pt \ ro \ se sk \ tr \ us \ vn \ za ! $evdevkbds = ibm_spacesaver ! $thinkpads = thinkpad thinkpad60 thinkpadz60 ! $sun_t6_custom = ara be br ca ch cz de dk \ ee es fi fr gb gr it kr \ lt lv nl no pl pt ro ru \ se sk tr tw ua ! $htcdreamlayouts = us it de ! $dvoraklayouts = br ca de ee es fr gb no pl se us ! model = keycodes * = evdev-xkbcommon ! layout[1] = keycodes $azerty = +aliases-xkbcommon(azerty) $qwertz = +aliases-xkbcommon(qwertz) * = +aliases-xkbcommon(qwerty) ! layout = keycodes $azerty = +aliases-xkbcommon(azerty) $qwertz = +aliases-xkbcommon(qwertz) * = +aliases-xkbcommon(qwerty) ! model layout = geometry thinkpad us = thinkpad(us) ! model = geometry microsoftelite = microsoft(elite) $msmodels = microsoft(natural) dell101 = dell(dell101) dellm65 = dell(dellm65) latitude = dell(latitude) flexpro = keytronic(FlexPro) hp6000 = hp(omnibook) hpmini110 = hp(mini110) hpdv5 = hp(dv5) omnikey101 = northgate(omnikey101) sanwaskbkg3 = sanwa(sanwaskbkg3) $pcmodels = pc(%m) $pcgeometries = pc(%m) everex = everex(STEPnote) thinkpad = thinkpad(intl) thinkpad60 = thinkpad(60) thinkpadz60 = thinkpad(60) $tmgeometries = typematrix(%m) winbook = winbook(XP5) pc98 = nec(pc98) $applealu = macintosh(%m) $macbooks = macintosh(%m) $macs = macintosh(macintosh) hhk = hhk(basic) kinesis = kinesis(model100) $nokiamodels = nokia(%m) * = pc(pc104) ! model layout variant = symbols * ben basic = pc+in(ben) * ben probhat = pc+in(ben_probhat) * dev basic = pc+in(deva) * dvorak $dvoraklayouts = pc+%v(dvorak) * dvorak basic = pc+us(dvorak) * dvorak pl_basic = pc+pl(dvorak) * dvorak pl = pc+pl(dvorak_quotes) * dvorak pl_altquotes = pc+pl(dvorak_altquotes) * dzdwi basic = pc+bt(basic) * fi basic = pc+fi(classic) * ge azerty_tskapo = pc+fr(geo) * guj basic = pc+in(guj) * gur basic = pc+in(guru) * ie laptop = pc+ie(basic) * ie CloGaelachLaptop = pc+ie(CloGaelach) * in urd = pc+in(urd-phonetic) * iu basic = pc+ca(ike) * lo basic = pc+la(basic) * kan basic = pc+in(kan) * mal basic = pc+in(mal) * mal mlplusnum = pc+in(mal) * ogham basic = pc+ie(ogam) * ogham laptop = pc+ie(ogam) * ogham is434 = pc+ie(ogam_is434) * ogham is434laptop = pc+ie(ogam_is434) * ori basic = pc+in(ori) * ro de = pc+ro(winkeys) * ro us = pc+ro(std) * ro academic = pc+ro(std) * ro std_comma = pc+ro(std) * ro comma = pc+ro(basic) * ru os = pc+ru(os_legacy) * pk urd = pc+pk(urd-phonetic) * sapmi basic = pc+no(smi) * sapmi nodeadkeys = pc+no(smi_nodeadkeys) * sapmi sefi = pc+fi(smi) * sin phonetic-static = pc+in(sin_phonetic) * syr basic = pc+sy(syc) * syr phonetic = pc+sy(syc_phonetic) * tam INSCRIPT = pc+in(tam) * tam UNI = pc+in(tam_unicode) * tam NUMERAL-KEYBOARD = pc+in(tam_keyboard_with_numerals) * tam TAB = pc+in(tam_TAB) * tam TSCII = pc+in(tam_TSCII) * tel basic = pc+in(tel) * yu basic = pc+srp(latin) * yu unicode = pc+srp(latinunicode) * yu yz = pc+srp(latinyz) * yu unicodeyz = pc+srp(latinunicodeyz) classmate us intl = pc+us(classmate-intl) classmate us alt-intl = pc+us(classmate-alt-intl) classmate us altgr-intl = pc+us(classmate-altgr-intl) nokiarx51 cz qwerty = nokia_vndr/rx-51(cz_qwerty) ! model layout = symbols * ar = pc+ara * ben = pc+in(ben) * bs = pc+ba * cs = pc+rs * cz_qwerty = pc+cz(qwerty) * dev = pc+in(deva) * dvorak = pc+us(dvorak) * dzdwi = pc+bt * el = pc+gr * en_US = pc+latin * guj = pc+in(guj) * gur = pc+in(guru) * iu = pc+ca(ike) * lo = pc+la * kan = pc+in(kan) * mi = pc+mao * ml = pc+in(mal) * ogham = pc+ie(ogam) * ori = pc+ie(ori) * sapmi = pc+no(smi) * sr = pc+srp * syr = pc+sy(syc) * tel = pc+in(tel) * tml = pc+in(tam) * yu = pc+srp * fr-latin9 = pc+fr(latin9) * us_intl = pc+us(alt-intl) * ben(basic) = pc+in(ben) * ben(probhat) = pc+in(ben_probhat) * dev(basic) = pc+in(deva) * dvorak($dvoraklayouts) = pc+%v(dvorak) * dvorak(basic) = pc+us(dvorak) * dvorak(pl_basic) = pc+pl(dvorak) * dvorak(pl) = pc+pl(dvorak_quotes) * dvorak(pl_altquotes) = pc+pl(dvorak_altquotes) * dzdwi(basic) = pc+bt(basic) * fi(basic) = pc+fi(classic) * ge(azerty_tskapo) = pc+fr(geo) * guj(basic) = pc+in(guj) * gur(basic) = pc+in(guru) * ie(laptop) = pc+ie(basic) * ie(CloGaelachLaptop) = pc+ie(CloGaelach) * in(urd) = pc+in(urd-phonetic) * iu(basic) = pc+ca(ike) * lo(basic) = pc+la(basic) * kan(basic) = pc+in(kan) * mal(basic) = pc+in(mal) * mal(mlplusnum) = pc+in(mal) * ogham(basic) = pc+ie(ogam) * ogham(laptop) = pc+ie(ogam) * ogham(is434) = pc+ie(ogam_is434) * ogham(is434laptop) = pc+ie(ogam_is434) * ori(basic) = pc+in(ori) * ro(de) = pc+ro(winkeys) * ro(us) = pc+ro(std) * ro(academic) = pc+ro(std) * ro(std_comma) = pc+ro(std) * ro(comma) = pc+ro(basic) * ru(os) = pc+ru(os_legacy) * pk(urd) = pc+pk(urd-phonetic) * sapmi(basic) = pc+no(smi) * sapmi(nodeadkeys) = pc+no(smi_nodeadkeys) * sapmi(sefi) = pc+fi(smi) * sin(phonetic-static) = pc+in(sin_phonetic) * syr(basic) = pc+sy(syc) * syr(phonetic) = pc+sy(syc_phonetic) * tam(INSCRIPT) = pc+in(tam) * tam(UNI) = pc+in(tam_unicode) * tam(NUMERAL-KEYBOARD) = pc+in(tam_keyboard_with_numerals) * tam(TAB) = pc+in(tam_TAB) * tam(TSCII) = pc+in(tam_TSCII) * tel(basic) = pc+in(tel) * yu(basic) = pc+srp(latin) * yu(unicode) = pc+srp(latinunicode) * yu(yz) = pc+srp(latinyz) * yu(unicodeyz) = pc+srp(latinunicodeyz) ataritt $nonlatin = xfree68_vndr/ataritt(us)+%l%(v):2 ataritt * = xfree68_vndr/ataritt(us)+%l%(v) amiga $nonlatin = xfree68_vndr/amiga(usa1)+%l%(v):2 amiga * = xfree68_vndr/amiga(usa1)+%l%(v) classmate us = pc+%l(classmate) empty * = empty(basic) * empty = empty(basic) sun4 $nonlatin = latin+sun_vndr/us(type4)+%l%(v):2 sun4 * = latin+sun_vndr/us(type4)+%l%(v) sun5 $nonlatin = latin+sun_vndr/us(type5)+%l%(v):2 sun5 * = latin+sun_vndr/us(type5)+%l%(v) sun6 us = pc+sun_vndr/us(type6) sun6 en_US = pc+sun_vndr/us(type6)+iso9995-3(basic) sun6 $sun_t6_custom = pc+sun_vndr/us(type6)+sun_vndr/%l%(v) sun6 * = pc+sun_vndr/us(type6)+%l%(v) sun6euro us = pc+sun_vndr/us(type6) sun6euro en_US = pc+sun_vndr/us(type6)+iso9995-3(basic) sun6euro $sun_t6_custom = pc+sun_vndr/us(type6)+sun_vndr/%l%(v) sun6euro * = pc+sun_vndr/us(type6)+%l%(v) pc98 nec_vndr/jp = nec_vndr/jp(pc98) macintosh_old us = macintosh_vndr/us(oldmac) macintosh_old en_US = macintosh_vndr/us(oldmac) macintosh_old $macvendorlayouts = macintosh_vndr/us(oldmac)+macintosh_vndr/%l%(v) macintosh_old $nonlatin = macintosh_vndr/us(oldmac)+%l%(v):2 macintosh_old * = macintosh_vndr/us(oldmac)+%l%(v) applealu_jis jp = macintosh_vndr/apple(alukbd)+macintosh_vndr/jp(usmac)+macintosh_vndr/jp(mac):2 applealu_jis * = macintosh_vndr/apple(alukbd)+%l%(v)+macintosh_vndr/jp(mac):2 $applealu $macvendorlayouts = macintosh_vndr/apple(alukbd)+macintosh_vndr/%l%(v) $applealu * = macintosh_vndr/apple(alukbd)+%l%(v) $macs en_US = pc+macintosh_vndr/us(extended) $macs $macvendorlayouts = pc+macintosh_vndr/%l%(v) nokiarx44 * = nokia_vndr/rx-44(%l) nokiarx51 cz(qwerty) = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(cz_qwerty) nokiarx51 * = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(%l%_v) nokiasu8w * = nokia_vndr/su-8w(%l) olpc $olpclayouts = olpc+%l%(m) olpc * = olpc+%l%(v) $thinkpads br = pc+br(thinkpad) htcdream $htcdreamlayouts = %l(htcdream) * $nonlatin = pc+us+%l%(v):2 * * = pc+%l%(v) ! model layout[1] = symbols * ar = pc+ara%(v[1]) * ben = pc+in(ben) * bs = pc+ba%(v[1]) * cs = pc+rs%(v[1]) * cz_qwerty = pc+cz(qwerty) * dev = pc+in(deva) * dvorak = pc+us(dvorak) * dzdwi = pc+bt%(v[1]) * el = pc+gr%(v[1]) * en_US = pc+latin%(v[1]) * guj = pc+in(guj) * gur = pc+in(guru) * iu = pc+ca(ike) * lo = pc+la%(v[1]) * kan = pc+in(kan) * mi = pc+mao%(v[1]) * ml = pc+in(mal) * ogham = pc+ie(ogam) * ori = pc+ie(ori) * sapmi = pc+no(smi) * sr = pc+srp%(v[1]) * syr = pc+sy(syc) * tel = pc+in(tel) * tml = pc+in(tam) * yu = pc+srp%(v[1]) * fr-latin9 = pc+fr(latin9) * us_intl = pc+us(alt-intl) * ben(basic) = pc+in(ben) * ben(probhat) = pc+in(ben_probhat) * dev(basic) = pc+in(deva) * dvorak($dvoraklayouts) = pc+%v(dvorak) * dvorak(basic) = pc+us(dvorak) * dvorak(pl_basic) = pc+pl(dvorak) * dvorak(pl) = pc+pl(dvorak_quotes) * dvorak(pl_altquotes) = pc+pl(dvorak_altquotes) * dzdwi(basic) = pc+bt(basic) * fi(basic) = pc+fi(classic) * ge(azerty_tskapo) = pc+fr(geo) * guj(basic) = pc+in(guj) * gur(basic) = pc+in(guru) * ie(laptop) = pc+ie(basic) * ie(CloGaelachLaptop) = pc+ie(CloGaelach) * in(urd) = pc+in(urd-phonetic) * iu(basic) = pc+ca(ike) * lo(basic) = pc+la(basic) * kan(basic) = pc+in(kan) * mal(basic) = pc+in(mal) * mal(mlplusnum) = pc+in(mal) * ogham(basic) = pc+ie(ogam) * ogham(laptop) = pc+ie(ogam) * ogham(is434) = pc+ie(ogam_is434) * ogham(is434laptop) = pc+ie(ogam_is434) * ori(basic) = pc+in(ori) * ro(de) = pc+ro(winkeys) * ro(us) = pc+ro(std) * ro(academic) = pc+ro(std) * ro(std_comma) = pc+ro(std) * ro(comma) = pc+ro(basic) * ru(os) = pc+ru(os_legacy) * pk(urd) = pc+pk(urd-phonetic) * sapmi(basic) = pc+no(smi) * sapmi(nodeadkeys) = pc+no(smi_nodeadkeys) * sapmi(sefi) = pc+fi(smi) * sin(phonetic-static) = pc+in(sin_phonetic) * syr(basic) = pc+sy(syc) * syr(phonetic) = pc+sy(syc_phonetic) * tam(INSCRIPT) = pc+in(tam) * tam(UNI) = pc+in(tam_unicode) * tam(NUMERAL-KEYBOARD) = pc+in(tam_keyboard_with_numerals) * tam(TAB) = pc+in(tam_TAB) * tam(TSCII) = pc+in(tam_TSCII) * tel(basic) = pc+in(tel) * yu(basic) = pc+srp(latin) * yu(unicode) = pc+srp(latinunicode) * yu(yz) = pc+srp(latinyz) * yu(unicodeyz) = pc+srp(latinunicodeyz) ataritt * = xfree68_vndr/ataritt(us)+%l[1]%(v[1]) amiga * = xfree68_vndr/amiga(usa1)+%l[1]%(v[1]) sun4 * = latin+sun_vndr/us(type4)+%l[1]%(v[1]) sun5 * = latin+sun_vndr/us(type5)+%l[1]%(v[1]) macintosh_old us = macintosh_vndr/us(oldmac) macintosh_old $macvendorlayouts = macintosh_vndr/us(oldmac)+macintosh_vndr/%l[1]%(v[1]) macintosh_old * = macintosh_vndr/us(oldmac)+%l[1]%(v[1]) applealu_jis us = macintosh_vndr/apple(alukbd)+macintosh_vndr/jp(usmac) $applealu $macvendorlayouts = macintosh_vndr/apple(alukbd)+macintosh_vndr/%l[1]%(v[1]) $applealu * = macintosh_vndr/apple(alukbd)+%l[1]%(v[1]) $macs $macvendorlayouts = pc+macintosh_vndr/%l[1]%(v[1]) nokiarx51 cz(qwerty) = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(cz_qwerty) nokiarx51 * = nokia_vndr/rx-51(common)+nokia_vndr/rx-51(%l[1]%_v[1]) $thinkpads br = pc+%l[1](thinkpad) * * = pc+%l[1]%(v[1]) ! model layout[1] variant[1] = symbols * ben basic = pc+in(ben) * ben probhat = pc+in(ben_probhat) * dev basic = pc+in(deva) * dvorak $dvoraklayouts = pc+%v(dvorak) * dvorak basic = pc+us(dvorak) * dvorak pl_basic = pc+pl(dvorak) * dvorak pl = pc+pl(dvorak_quotes) * dvorak pl_altquotes = pc+pl(dvorak_altquotes) * dzdwi basic = pc+bt(basic) * fi basic = pc+fi(classic) * ge azerty_tskapo = pc+fr(geo) * guj basic = pc+in(guj) * gur basic = pc+in(guru) * ie laptop = pc+ie(basic) * ie CloGaelachLaptop = pc+ie(CloGaelach) * in urd = pc+in(urd-phonetic) * iu basic = pc+ca(ike) * lo basic = pc+la(basic) * kan basic = pc+in(kan) * mal basic = pc+in(mal) * mal mlplusnum = pc+in(mal) * ogham basic = pc+ie(ogam) * ogham laptop = pc+ie(ogam) * ogham is434 = pc+ie(ogam_is434) * ogham is434laptop = pc+ie(ogam_is434) * ori basic = pc+in(ori) * ro de = pc+ro(winkeys) * ro us = pc+ro(std) * ro academic = pc+ro(std) * ro std_comma = pc+ro(std) * ro comma = pc+ro(basic) * ru os = pc+ru(os_legacy) * pk urd = pc+pk(urd-phonetic) * sapmi basic = pc+no(smi) * sapmi nodeadkeys = pc+no(smi_nodeadkeys) * sapmi sefi = pc+fi(smi) * sin phonetic-static = pc+in(sin_phonetic) * syr basic = pc+sy(syc) * syr phonetic = pc+sy(syc_phonetic) * tam INSCRIPT = pc+in(tam) * tam UNI = pc+in(tam_unicode) * tam NUMERAL-KEYBOARD = pc+in(tam_keyboard_with_numerals) * tam TAB = pc+in(tam_TAB) * tam TSCII = pc+in(tam_TSCII) * tel basic = pc+in(tel) * yu basic = pc+srp(latin) * yu unicode = pc+srp(latinunicode) * yu yz = pc+srp(latinyz) * yu unicodeyz = pc+srp(latinunicodeyz) ! model layout[2] = symbols * ar = +ara%(v[2]):2 * ben = +in(ben):2 * bs = +ba%(v[2]):2 * cs = +rs%(v[2]):2 * cz_qwerty = +cz(qwerty):2 * dev = +in(deva):2 * dvorak = +us(dvorak):2 * dzdwi = +bt%(v[2]):2 * el = +gr%(v[2]):2 * en_US = +latin%(v[2]):2 * guj = +in(guj):2 * gur = +in(guru):2 * iu = +ca(ike):2 * lo = +la%(v[2]):2 * kan = +in(kan):2 * mi = +mao%(v[2]):2 * ml = +in(mal):2 * ogham = +ie(ogam):2 * ori = +ie(ori):2 * sapmi = +no(smi):2 * sr = +srp%(v[2]):2 * syr = +sy(syc):2 * tel = +in(tel):2 * tml = +in(tam):2 * yu = +srp%(v[2]):2 * fr-latin9 = +fr(latin9):2 * us_intl = +us(alt-intl):2 * ben(basic) = +in(ben):2 * ben(probhat) = +in(ben_probhat):2 * dev(basic) = +in(deva):2 * dvorak($dvoraklayouts) = +%v(dvorak):2 * dvorak(basic) = +us(dvorak):2 * dvorak(pl_basic) = +pl(dvorak):2 * dvorak(pl) = +pl(dvorak_quotes):2 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):2 * dzdwi(basic) = +bt(basic):2 * fi(basic) = +fi(classic):2 * ge(azerty_tskapo) = +fr(geo):2 * guj(basic) = +in(guj):2 * gur(basic) = +in(guru):2 * ie(laptop) = +ie(basic):2 * ie(CloGaelachLaptop) = +ie(CloGaelach):2 * in(urd) = +in(urd-phonetic):2 * iu(basic) = +ca(ike):2 * lo(basic) = +la(basic):2 * kan(basic) = +in(kan):2 * mal(basic) = +in(mal):2 * mal(mlplusnum) = +in(mal):2 * ogham(basic) = +ie(ogam):2 * ogham(laptop) = +ie(ogam):2 * ogham(is434) = +ie(ogam_is434):2 * ogham(is434laptop) = +ie(ogam_is434):2 * ori(basic) = +in(ori):2 * ro(de) = +ro(winkeys):2 * ro(us) = +ro(std):2 * ro(academic) = +ro(std):2 * ro(std_comma) = +ro(std):2 * ro(comma) = +ro(basic):2 * ru(os) = +ru(os_legacy):2 * pk(urd) = +pk(urd-phonetic):2 * sapmi(basic) = +no(smi):2 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):2 * sapmi(sefi) = +fi(smi):2 * sin(phonetic-static) = +in(sin_phonetic):2 * syr(basic) = +sy(syc):2 * syr(phonetic) = +sy(syc_phonetic):2 * tam(INSCRIPT) = +in(tam):2 * tam(UNI) = +in(tam_unicode):2 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):2 * tam(TAB) = +in(tam_TAB):2 * tam(TSCII) = +in(tam_TSCII):2 * tel(basic) = +in(tel):2 * yu(basic) = +srp(latin):2 * yu(unicode) = +srp(latinunicode):2 * yu(yz) = +srp(latinyz):2 * yu(unicodeyz) = +srp(latinunicodeyz):2 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):2 nokiarx51 * = +nokia_vndr/rx-51(%l[2]%_v[2]):2 * * = +%l[2]%(v[2]):2 ! model layout[3] = symbols * ar = +ara%(v[3]):3 * ben = +in(ben):3 * bs = +ba%(v[3]):3 * cs = +rs%(v[3]):3 * cz_qwerty = +cz(qwerty):3 * dev = +in(deva):3 * dvorak = +us(dvorak):3 * dzdwi = +bt%(v[3]):3 * el = +gr%(v[3]):3 * en_US = +latin%(v[3]):3 * guj = +in(guj):3 * gur = +in(guru):3 * iu = +ca(ike):3 * lo = +la%(v[3]):3 * kan = +in(kan):3 * mi = +mao%(v[3]):3 * ml = +in(mal):3 * ogham = +ie(ogam):3 * ori = +ie(ori):3 * sapmi = +no(smi):3 * sr = +srp%(v[3]):3 * syr = +sy(syc):3 * tel = +in(tel):3 * tml = +in(tam):3 * yu = +srp%(v[3]):3 * fr-latin9 = +fr(latin9):3 * us_intl = +us(alt-intl):3 * ben(basic) = +in(ben):3 * ben(probhat) = +in(ben_probhat):3 * dev(basic) = +in(deva):3 * dvorak($dvoraklayouts) = +%v(dvorak):3 * dvorak(basic) = +us(dvorak):3 * dvorak(pl_basic) = +pl(dvorak):3 * dvorak(pl) = +pl(dvorak_quotes):3 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):3 * dzdwi(basic) = +bt(basic):3 * fi(basic) = +fi(classic):3 * ge(azerty_tskapo) = +fr(geo):3 * guj(basic) = +in(guj):3 * gur(basic) = +in(guru):3 * ie(laptop) = +ie(basic):3 * ie(CloGaelachLaptop) = +ie(CloGaelach):3 * in(urd) = +in(urd-phonetic):3 * iu(basic) = +ca(ike):3 * lo(basic) = +la(basic):3 * kan(basic) = +in(kan):3 * mal(basic) = +in(mal):3 * mal(mlplusnum) = +in(mal):3 * ogham(basic) = +ie(ogam):3 * ogham(laptop) = +ie(ogam):3 * ogham(is434) = +ie(ogam_is434):3 * ogham(is434laptop) = +ie(ogam_is434):3 * ori(basic) = +in(ori):3 * ro(de) = +ro(winkeys):3 * ro(us) = +ro(std):3 * ro(academic) = +ro(std):3 * ro(std_comma) = +ro(std):3 * ro(comma) = +ro(basic):3 * ru(os) = +ru(os_legacy):3 * pk(urd) = +pk(urd-phonetic):3 * sapmi(basic) = +no(smi):3 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):3 * sapmi(sefi) = +fi(smi):3 * sin(phonetic-static) = +in(sin_phonetic):3 * syr(basic) = +sy(syc):3 * syr(phonetic) = +sy(syc_phonetic):3 * tam(INSCRIPT) = +in(tam):3 * tam(UNI) = +in(tam_unicode):3 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):3 * tam(TAB) = +in(tam_TAB):3 * tam(TSCII) = +in(tam_TSCII):3 * tel(basic) = +in(tel):3 * yu(basic) = +srp(latin):3 * yu(unicode) = +srp(latinunicode):3 * yu(yz) = +srp(latinyz):3 * yu(unicodeyz) = +srp(latinunicodeyz):3 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):3 nokiarx51 * = +nokia_vndr/rx-51(%l[3]%_v[3]):3 * * = +%l[3]%(v[3]):3 ! model layout[4] = symbols * ar = +ara%(v[4]):4 * ben = +in(ben):4 * bs = +ba%(v[4]):4 * cs = +rs%(v[4]):4 * cz_qwerty = +cz(qwerty):4 * dev = +in(deva):4 * dvorak = +us(dvorak):4 * dzdwi = +bt%(v[4]):4 * el = +gr%(v[4]):4 * en_US = +latin%(v[4]):4 * guj = +in(guj):4 * gur = +in(guru):4 * iu = +ca(ike):4 * lo = +la%(v[4]):4 * kan = +in(kan):4 * mi = +mao%(v[4]):4 * ml = +in(mal):4 * ogham = +ie(ogam):4 * ori = +ie(ori):4 * sapmi = +no(smi):4 * sr = +srp%(v[4]):4 * syr = +sy(syc):4 * tel = +in(tel):4 * tml = +in(tam):4 * yu = +srp%(v[4]):4 * fr-latin9 = +fr(latin9):4 * us_intl = +us(alt-intl):4 * ben(basic) = +in(ben):4 * ben(probhat) = +in(ben_probhat):4 * dev(basic) = +in(deva):4 * dvorak($dvoraklayouts) = +%v(dvorak):4 * dvorak(basic) = +us(dvorak):4 * dvorak(pl_basic) = +pl(dvorak):4 * dvorak(pl) = +pl(dvorak_quotes):4 * dvorak(pl_altquotes) = +pl(dvorak_altquotes):4 * dzdwi(basic) = +bt(basic):4 * fi(basic) = +fi(classic):4 * ge(azerty_tskapo) = +fr(geo):4 * guj(basic) = +in(guj):4 * gur(basic) = +in(guru):4 * ie(laptop) = +ie(basic):4 * ie(CloGaelachLaptop) = +ie(CloGaelach):4 * in(urd) = +in(urd-phonetic):4 * iu(basic) = +ca(ike):4 * lo(basic) = +la(basic):4 * kan(basic) = +in(kan):4 * mal(basic) = +in(mal):4 * mal(mlplusnum) = +in(mal):4 * ogham(basic) = +ie(ogam):4 * ogham(laptop) = +ie(ogam):4 * ogham(is434) = +ie(ogam_is434):4 * ogham(is434laptop) = +ie(ogam_is434):4 * ori(basic) = +in(ori):4 * ro(de) = +ro(winkeys):4 * ro(us) = +ro(std):4 * ro(academic) = +ro(std):4 * ro(std_comma) = +ro(std):4 * ro(comma) = +ro(basic):4 * ru(os) = +ru(os_legacy):4 * pk(urd) = +pk(urd-phonetic):4 * sapmi(basic) = +no(smi):4 * sapmi(nodeadkeys) = +no(smi_nodeadkeys):4 * sapmi(sefi) = +fi(smi):4 * sin(phonetic-static) = +in(sin_phonetic):4 * syr(basic) = +sy(syc):4 * syr(phonetic) = +sy(syc_phonetic):4 * tam(INSCRIPT) = +in(tam):4 * tam(UNI) = +in(tam_unicode):4 * tam(NUMERAL-KEYBOARD) = +in(tam_keyboard_with_numerals):4 * tam(TAB) = +in(tam_TAB):4 * tam(TSCII) = +in(tam_TSCII):4 * tel(basic) = +in(tel):4 * yu(basic) = +srp(latin):4 * yu(unicode) = +srp(latinunicode):4 * yu(yz) = +srp(latinyz):4 * yu(unicodeyz) = +srp(latinunicodeyz):4 nokiarx51 cz(qwerty) = +nokia_vndr/rx-51(cz_qwerty):4 nokiarx51 * = +nokia_vndr/rx-51(%l[4]%_v[4]):4 * * = +%l[4]%(v[4]):4 ! model layout[2] variant[2] = symbols * ben basic = +in(ben):2 * ben probhat = +in(ben_probhat):2 * dev basic = +in(deva):2 * dvorak $dvoraklayouts = +%v(dvorak):2 * dvorak basic = +us(dvorak):2 * dvorak pl_basic = +pl(dvorak):2 * dvorak pl = +pl(dvorak_quotes):2 * dvorak pl_altquotes = +pl(dvorak_altquotes):2 * dzdwi basic = +bt(basic):2 * fi basic = +fi(classic):2 * ge azerty_tskapo = +fr(geo):2 * guj basic = +in(guj):2 * gur basic = +in(guru):2 * ie laptop = +ie(basic):2 * ie CloGaelachLaptop = +ie(CloGaelach):2 * in urd = +in(urd-phonetic):2 * iu basic = +ca(ike):2 * lo basic = +la(basic):2 * kan basic = +in(kan):2 * mal basic = +in(mal):2 * mal mlplusnum = +in(mal):2 * ogham basic = +ie(ogam):2 * ogham laptop = +ie(ogam):2 * ogham is434 = +ie(ogam_is434):2 * ogham is434laptop = +ie(ogam_is434):2 * ori basic = +in(ori):2 * ro de = +ro(winkeys):2 * ro us = +ro(std):2 * ro academic = +ro(std):2 * ro std_comma = +ro(std):2 * ro comma = +ro(basic):2 * ru os = +ru(os_legacy):2 * pk urd = +pk(urd-phonetic):2 * sapmi basic = +no(smi):2 * sapmi nodeadkeys = +no(smi_nodeadkeys):2 * sapmi sefi = +fi(smi):2 * sin phonetic-static = +in(sin_phonetic):2 * syr basic = +sy(syc):2 * syr phonetic = +sy(syc_phonetic):2 * tam INSCRIPT = +in(tam):2 * tam UNI = +in(tam_unicode):2 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):2 * tam TAB = +in(tam_TAB):2 * tam TSCII = +in(tam_TSCII):2 * tel basic = +in(tel):2 * yu basic = +srp(latin):2 * yu unicode = +srp(latinunicode):2 * yu yz = +srp(latinyz):2 * yu unicodeyz = +srp(latinunicodeyz):2 ! model layout[3] variant[3] = symbols * ben basic = +in(ben):3 * ben probhat = +in(ben_probhat):3 * dev basic = +in(deva):3 * dvorak $dvoraklayouts = +%v(dvorak):3 * dvorak basic = +us(dvorak):3 * dvorak pl_basic = +pl(dvorak):3 * dvorak pl = +pl(dvorak_quotes):3 * dvorak pl_altquotes = +pl(dvorak_altquotes):3 * dzdwi basic = +bt(basic):3 * fi basic = +fi(classic):3 * ge azerty_tskapo = +fr(geo):3 * guj basic = +in(guj):3 * gur basic = +in(guru):3 * ie laptop = +ie(basic):3 * ie CloGaelachLaptop = +ie(CloGaelach):3 * in urd = +in(urd-phonetic):3 * iu basic = +ca(ike):3 * lo basic = +la(basic):3 * kan basic = +in(kan):3 * mal basic = +in(mal):3 * mal mlplusnum = +in(mal):3 * ogham basic = +ie(ogam):3 * ogham laptop = +ie(ogam):3 * ogham is434 = +ie(ogam_is434):3 * ogham is434laptop = +ie(ogam_is434):3 * ori basic = +in(ori):3 * ro de = +ro(winkeys):3 * ro us = +ro(std):3 * ro academic = +ro(std):3 * ro std_comma = +ro(std):3 * ro comma = +ro(basic):3 * ru os = +ru(os_legacy):3 * pk urd = +pk(urd-phonetic):3 * sapmi basic = +no(smi):3 * sapmi nodeadkeys = +no(smi_nodeadkeys):3 * sapmi sefi = +fi(smi):3 * sin phonetic-static = +in(sin_phonetic):3 * syr basic = +sy(syc):3 * syr phonetic = +sy(syc_phonetic):3 * tam INSCRIPT = +in(tam):3 * tam UNI = +in(tam_unicode):3 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):3 * tam TAB = +in(tam_TAB):3 * tam TSCII = +in(tam_TSCII):3 * tel basic = +in(tel):3 * yu basic = +srp(latin):3 * yu unicode = +srp(latinunicode):3 * yu yz = +srp(latinyz):3 * yu unicodeyz = +srp(latinunicodeyz):3 ! model layout[4] variant[4] = symbols * ben basic = +in(ben):4 * ben probhat = +in(ben_probhat):4 * dev basic = +in(deva):4 * dvorak $dvoraklayouts = +%v(dvorak):4 * dvorak basic = +us(dvorak):4 * dvorak pl_basic = +pl(dvorak):4 * dvorak pl = +pl(dvorak_quotes):4 * dvorak pl_altquotes = +pl(dvorak_altquotes):4 * dzdwi basic = +bt(basic):4 * fi basic = +fi(classic):4 * ge azerty_tskapo = +fr(geo):4 * guj basic = +in(guj):4 * gur basic = +in(guru):4 * ie laptop = +ie(basic):4 * ie CloGaelachLaptop = +ie(CloGaelach):4 * in urd = +in(urd-phonetic):4 * iu basic = +ca(ike):4 * lo basic = +la(basic):4 * kan basic = +in(kan):4 * mal basic = +in(mal):4 * mal mlplusnum = +in(mal):4 * ogham basic = +ie(ogam):4 * ogham laptop = +ie(ogam):4 * ogham is434 = +ie(ogam_is434):4 * ogham is434laptop = +ie(ogam_is434):4 * ori basic = +in(ori):4 * ro de = +ro(winkeys):4 * ro us = +ro(std):4 * ro academic = +ro(std):4 * ro std_comma = +ro(std):4 * ro comma = +ro(basic):4 * ru os = +ru(os_legacy):4 * pk urd = +pk(urd-phonetic):4 * sapmi basic = +no(smi):4 * sapmi nodeadkeys = +no(smi_nodeadkeys):4 * sapmi sefi = +fi(smi):4 * sin phonetic-static = +in(sin_phonetic):4 * syr basic = +sy(syc):4 * syr phonetic = +sy(syc_phonetic):4 * tam INSCRIPT = +in(tam):4 * tam UNI = +in(tam_unicode):4 * tam NUMERAL-KEYBOARD = +in(tam_keyboard_with_numerals):4 * tam TAB = +in(tam_TAB):4 * tam TSCII = +in(tam_TSCII):4 * tel basic = +in(tel):4 * yu basic = +srp(latin):4 * yu unicode = +srp(latinunicode):4 * yu yz = +srp(latinyz):4 * yu unicodeyz = +srp(latinunicodeyz):4 ! model = symbols $evdevkbds = +inet(evdev)+inet(%m) applealu_jis = +inet(evdev)+macintosh_vndr/jp(alujiskeys) * = +inet(evdev) ! layout variant = compat de neo = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) ! layout[1] variant[1] = compat de neo = +caps(caps_lock)+misc(assign_shift_left_action)+level5(level5_lock) ! layout[2] variant[2] = compat de neo = +caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2 ! layout[3] variant[3] = compat de neo = +caps(caps_lock):3+misc(assign_shift_left_action):3+level5(level5_lock):3 ! layout[4] variant[4] = compat de neo = +caps(caps_lock):4+misc(assign_shift_left_action):4+level5(level5_lock):4 ! model layout = compat pc98 nec_vndr/jp = pc98(basic) * jp = complete+japan olpc * = olpc * * = complete ! model layout[1] = compat * * = complete ! model = types $macs = complete+numpad(mac) $applealu = complete+numpad(mac) $nokiamodels = complete+nokia * = complete ! layout option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle) * misc:typo = +typo(base) ! layout[1] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):1 * misc:typo = +typo(base):1 ! layout[2] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):2 * misc:typo = +typo(base):2 ! layout[3] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):3 * misc:typo = +typo(base):3 ! layout[4] option = symbols $threelevellayouts grp:alts_toggle = +level3(ralt_switch_for_alts_toggle):4 * misc:typo = +typo(base):4 ! option = symbols grp:shift_toggle = +group(shifts_toggle) altwin:menu = +altwin(menu) altwin:meta_alt = +altwin(meta_alt) altwin:ctrl_win = +altwin(ctrl_win) altwin:ctrl_alt_win = +altwin(ctrl_alt_win) altwin:meta_win = +altwin(meta_win) altwin:left_meta_win = +altwin(left_meta_win) altwin:hyper_win = +altwin(hyper_win) altwin:alt_super_win = +altwin(alt_super_win) altwin:swap_lalt_lwin = +altwin(swap_lalt_lwin) grp:switch = +group(switch) grp:lswitch = +group(lswitch) grp:win_switch = +group(win_switch) grp:lwin_switch = +group(lwin_switch) grp:rwin_switch = +group(rwin_switch) grp:toggle = +group(toggle) grp:shifts_toggle = +group(shifts_toggle) grp:ctrls_toggle = +group(ctrls_toggle) grp:alts_toggle = +group(alts_toggle) grp:caps_toggle = +capslock(grouplock) grp:caps_switch = +capslock(groupshift) grp:shift_caps_toggle = +group(shift_caps_toggle) grp:shift_caps_switch = +group(shift_caps_switch) grp:win_menu_switch = +group(win_menu_switch) grp:alt_caps_toggle = +group(alt_caps_toggle) grp:alt_space_toggle = +group(alt_space_toggle) grp:menu_toggle = +group(menu_toggle) grp:lwin_toggle = +group(lwin_toggle) grp:rwin_toggle = +group(rwin_toggle) grp:lshift_toggle = +group(lshift_toggle) grp:rshift_toggle = +group(rshift_toggle) grp:rctrl_switch = +group(rctrl_switch) grp:lctrl_toggle = +group(lctrl_toggle) grp:rctrl_toggle = +group(rctrl_toggle) grp:lalt_toggle = +group(lalt_toggle) grp:sclk_toggle = +group(sclk_toggle) grp:lctrl_rctrl_switch = +group(lctrl_rctrl_switch) grp:lctrl_lwin_rctrl_menu = +group(lctrl_lwin_rctrl_menu) grp:lctrl_lalt_toggle = +group(lctrl_lalt_toggle) grp:rctrl_ralt_toggle = +group(rctrl_ralt_toggle) grp:ctrl_alt_toggle = +group(ctrl_alt_toggle) grp:ctrl_alt_toggle_bidir = +group(ctrl_alt_toggle_bidir) grp:lctrl_lshift_toggle = +group(lctrl_lshift_toggle) grp:rctrl_rshift_toggle = +group(rctrl_rshift_toggle) grp:ctrl_shift_toggle = +group(ctrl_shift_toggle) grp:ctrl_shift_toggle_bidir = +group(ctrl_shift_toggle_bidir) grp:lalt_lshift_toggle = +group(lalt_lshift_toggle) grp:ralt_rshift_toggle = +group(ralt_rshift_toggle) grp:alt_shift_toggle = +group(alt_shift_toggle) grp:alt_shift_toggle_bidir = +group(alt_shift_toggle_bidir) lv3:switch = +level3(switch) lv3:ralt_switch = +level3(ralt_switch) lv3:ralt_switch_multikey = +level3(ralt_switch_multikey) lv3:ralt_alt = +level3(ralt_alt) lv3:lalt_switch = +level3(lalt_switch) lv3:alt_switch = +level3(alt_switch) lv3:menu_switch = +level3(menu_switch) lv3:win_switch = +level3(win_switch) lv3:lwin_switch = +level3(lwin_switch) lv3:rwin_switch = +level3(rwin_switch) lv3:enter_switch = +level3(enter_switch) caps:capslock = +capslock(capslock) caps:numlock = +capslock(numlock) caps:shiftlock = +capslock(shiftlock) caps:swapescape = +capslock(swapescape) caps:escape = +capslock(escape) caps:backspace = +capslock(backspace) caps:super = +capslock(super) caps:hyper = +capslock(hyper) caps:none = +capslock(none) caps:ctrl_modifier = +capslock(ctrl_modifier) ctrl:nocaps = +ctrl(nocaps) ctrl:lctrl_meta = +ctrl(lctrl_meta) ctrl:swapcaps = +ctrl(swapcaps) ctrl:ac_ctrl = +ctrl(ac_ctrl) ctrl:aa_ctrl = +ctrl(aa_ctrl) ctrl:rctrl_ralt = +ctrl(rctrl_ralt) ctrl:menu_rctrl = +ctrl(menu_rctrl) ctrl:ralt_rctrl = +ctrl(ralt_rctrl) compose:ralt = +compose(ralt) compose:lwin = +compose(lwin) compose:rwin = +compose(rwin) compose:menu = +compose(menu) compose:lctrl = +compose(lctrl) compose:rctrl = +compose(rctrl) compose:caps = +compose(caps) compose:102 = +compose(102) compose:paus = +compose(paus) compose:prsc = +compose(prsc) compose:sclk = +compose(sclk) srvrkeys:none = +srvr_ctrl(no_srvr_keys) eurosign:e = +eurosign(e) eurosign:2 = +eurosign(2) eurosign:4 = +eurosign(4) eurosign:5 = +eurosign(5) rupeesign:4 = +rupeesign(4) keypad:oss = +keypad(oss) keypad:legacy = +keypad(legacy) keypad:legacy_wang = +keypad(legacy_wang) keypad:oss_wang = +keypad(oss_wang) keypad:future = +keypad(future) keypad:future_wang = +keypad(future_wang) keypad:hex = +keypad(ops)+keypad(hex) keypad:atm = +keypad(ops)+keypad(hex)+keypad(atm) nbsp:none = +nbsp(none) nbsp:level2 = +nbsp(level2) nbsp:level3 = +nbsp(level3) nbsp:level3s = +nbsp(level3s) nbsp:level3n = +nbsp(level3n) nbsp:level4 = +nbsp(level4) nbsp:level4n = +nbsp(level4n) nbsp:level4nl = +nbsp(level4nl) japan:nicola_f_bs = +jp(nicola_f_bs) japan:hztg_escape = +jp(hztg_escape) kpdl:dot = +kpdl(dot) kpdl:comma = +kpdl(comma) kpdl:dotoss = +kpdl(dotoss) kpdl:dotoss_latin9 = +kpdl(dotoss_latin9) kpdl:commaoss = +kpdl(commaoss) kpdl:momayyezoss = +kpdl(momayyezoss) kpdl:kposs = +kpdl(kposs) kpdl:semi = +kpdl(semi) shift:breaks_caps = +shift(breaks_caps) esperanto:qwerty = +epo(qwerty) esperanto:dvorak = +epo(dvorak) terminate:ctrl_alt_bksp = +terminate(ctrl_alt_bksp) keypad:pointerkeys = +keypad(pointerkeys) apple:alupckeys = +macintosh_vndr/apple(alupckeys) shift:both_capslock = +shift(both_capslock) shift:lshift_both_capslock = +shift(lshift_both_capslock) shift:rshift_both_capslock = +shift(rshift_both_capslock) shift:both_capslock_cancel = +shift(both_capslock_cancel) shift:lshift_both_capslock_cancel = +shift(lshift_both_capslock_cancel) shift:rshift_both_capslock_cancel = +shift(rshift_both_capslock_cancel) shift:both_shiftlock = +shift(both_shiftlock) shift:lshift_both_shiftlock = +shift(lshift_both_shiftlock) shift:rshift_both_shiftlock = +shift(rshift_both_shiftlock) lv3:caps_switch = +level3(caps_switch) lv3:bksl_switch = +level3(bksl_switch) lv3:lsgt_switch = +level3(lsgt_switch) lv3:caps_switch_latch = +level3(caps_switch_latch) lv3:bksl_switch_latch = +level3(bksl_switch_latch) lv3:lsgt_switch_latch = +level3(lsgt_switch_latch) lv5:lsgt_switch_lock = +level5(lsgt_switch_lock) lv5:ralt_switch_lock = +level5(ralt_switch_lock) lv5:lwin_switch_lock = +level5(lwin_switch_lock) lv5:rwin_switch_lock = +level5(rwin_switch_lock) lv5:lsgt_switch_lock_cancel = +level5(lsgt_switch_lock_cancel) lv5:ralt_switch_lock_cancel = +level5(ralt_switch_lock_cancel) lv5:lwin_switch_lock_cancel = +level5(lwin_switch_lock_cancel) lv5:rwin_switch_lock_cancel = +level5(rwin_switch_lock_cancel) ! option = compat grp_led:num = +lednum(group_lock) grp_led:caps = +ledcaps(group_lock) grp_led:scroll = +ledscroll(group_lock) caps:shiftlock = +ledcaps(shift_lock) grab:break_actions = +xfree86(grab_break) xkbcommon-libxkbcommon-54ee7ac/test/data/rules/evdev.extras.xml000066400000000000000000001255261510033435100250600ustar00rootroot00000000000000 apl apl APL eng dyalog dlg APL symbols (Dyalog APL) sax sax APL symbols (SAX, Sharp APL for Unix) unified ufd APL symbols (unified) apl2 apl2 APL symbols (IBM APL2) aplplusII aplII APL symbols (Manugistics APL*PLUS II) aplx aplx APL symbols (APLX unified) ca fr French (Canada) fra kut kut Kutenai shs shs Secwepemctsin sun_type6 Multilingual (Canada, Sun Type 6/7) de de German ger us German (US) eng hu German (with Hungarian letters, no dead keys) ger hun pl Polish (Germany, no dead keys) ger pol sun_type6 German (Sun Type 6/7) adnw German (Aus der Neo-Welt) koy German (KOY) bone German (Bone) bone_eszett_home German (Bone, eszett in the home row) neo_qwertz German (Neo, QWERTZ) neo_qwerty German (Neo, QWERTY) ru-recom ru Russian (Germany, recommended) rus ru-translit ru Russian (Germany, transliteration) rus lld de_lld German (Ladin) ger lld eg ⲕⲏⲙⲉ Coptic cop egy hu Hungarian oldhun oldhun Old Hungarian ohu_lig ohu_lig Old Hungarian (for ligatures) ir fa Persian per ave Avestan ave lt lt Lithuanian lit us_dvorak Lithuanian (Dvorak) sun_type6 Lithuanian (Sun Type 6/7) lv lv Latvian lav dvorak Latvian (Dvorak) ykeydvorak Latvian (Dvorak, with Y) minuskeydvorak Latvian (Dvorak, with minus) dvorakprogr Latvian (programmer Dvorak) ykeydvorakprogr Latvian (programmer Dvorak, with Y) minuskeydvorakprogr Latvian (programmer Dvorak, with minus) colemak Latvian (Colemak) apostrophecolemak Latvian (Colemak, with apostrophe) sun_type6 Latvian (Sun Type 6/7) us en English (US) eng intl-unicode English (US, intl., AltGr Unicode combining) alt-intl-unicode English (US, intl., AltGr Unicode combining, alt.) ats Atsina crd Coeur d'Alene Salish crd cz_sk_de Czech Slovak and German (US) eng cze slo ger drix English (Drix) de_se_fi German, Swedish and Finnish (US) eng ger swe fin ibm238l English (US, IBM Arabic 238_L) sun_type6 English (US, Sun Type 6/7) carpalx English (Carpalx) carpalx-intl English (Carpalx, intl., with dead keys) carpalx-altgr-intl English (Carpalx, intl., with AltGr dead keys) carpalx-full English (Carpalx, full optimization) carpalx-full-intl English (Carpalx, full optimization, intl., with dead keys) carpalx-full-altgr-intl English (Carpalx, full optimization, intl., with AltGr dead keys) 3l English (3l) 3l-cros English (3l, Chromebook) 3l-emacs English (3l, emacs) scn Sicilian (US keyboard) eng ita scn pl pl Polish pol intl Polish (intl., with dead keys) colemak Polish (Colemak) sun_type6 Polish (Sun Type 6/7) glagolica Polish (Glagolica) ro ro Romanian rum crh_dobruja crh Crimean Tatar (Dobruja Q) crh ergonomic Romanian (ergonomic Touchtype) sun_type6 Romanian (Sun Type 6/7) rs sr Serbian srp combiningkeys Serbian (combining accents instead of dead keys) ru ru Russian chu Church Slavonic chu ruu ru Russian (with Ukrainian-Belorussian layout) rus ukr bel rulemak Russian (Rulemak, phonetic Colemak) phonetic_mac Russian (phonetic Macintosh) sun_type6 Russian (Sun Type 6/7) unipunct Russian (with US punctuation) prxn ru Russian (Polyglot and Reactionary) RU RS BA ME MK BG MD UA BY KZ MN KG TJ UZ TM AZ rus rus-petr1708 ukr bel srp mkd bul chu rum-Cyrl kaz kir uzb bak aze tat uig kdr tyv kjh crh tgk abk sah mon kal sjd chv oss krl ale wbl kur niv dng kom udm sel ulc ude oac oaa gld eve evn kca itl yrk neg am hy Armenian hye olpc-phonetic Armenian (OLPC, phonetic) il he Hebrew heb biblicalSIL Hebrew (Biblical, SIL phonetic) heb ara ar Arabic sun_type6 Arabic (Sun Type 6/7) basic_ext Arabic (Arabic numerals, extensions in the 4th level) basic_ext_digits Arabic (Eastern Arabic numerals, extensions in the 4th level) uga Ugaritic instead of Arabic be be Belgian sun_type6 Belgian (Sun Type 6/7) br pt Portuguese (Brazil) sun_type6 Portuguese (Brazil, Sun Type 6/7) cz cs Czech sun_type6 Czech (Sun Type 6/7) prog Czech (programming) typo Czech (typographic) coder Czech (coder) prog_typo Czech (programming, typographic) dk da Danish sun_type6 Danish (Sun Type 6/7) nl nl Dutch sun_type6 Dutch (Sun Type 6/7) ee et Estonian sun_type6 Estonian (Sun Type 6/7) fi fi Finnish sun_type6 Finnish (Sun Type 6/7) das Finnish (DAS) fidvorak Finnish (Dvorak) fr fr French sun_type6 French (Sun Type 6/7) us-alt French (US with dead keys, alt.) us-azerty French (US, AZERTY) gr gr Greek sun_type6 Greek (Sun Type 6/7) colemak Greek (Colemak) it it Italian sun_type6 Italian (Sun Type 6/7) lld it_lld Italian (Ladin) it lld jp ja Japanese sun_type6 Japanese (Sun Type 6) sun_type7 Japanese (Sun Type 7, PC-compatible) sun_type7_suncompat Japanese (Sun Type 7, Sun-compatible) no no Norwegian sun_type6 Norwegian (Sun Type 6/7) pt pt Portuguese sun_type6 Portuguese (Sun Type 6/7) pt pt Portuguese colemak Portuguese (Colemak) sk sk Slovak acc Slovak (ACC layout, only accented letters) sun_type6 Slovak (Sun Type 6/7) es es Spanish sun_type6 Spanish (Sun Type 6/7) se sv Swedish dvorak_a5 Swedish (Dvorak A5) sun_type6 Swedish (Sun Type 6/7) ovd Elfdalian (Swedish, with combining ogonek) ovd ch de German (Switzerland) sun_type6_de German (Switzerland, Sun Type 6/7) sun_type6_fr French (Switzerland, Sun Type 6/7) tr tr Turkish sun_type6 Turkish (Sun Type 6/7) ua uk Ukrainian sun_type6 Ukrainian (Sun Type 6/7) gb en English (UK) sun_type6 English (UK, Sun Type 6/7) kr ko Korean sun_type6 Korean (Sun Type 6/7) vn vi Vietnamese vie aderty Vietnamese (AÐERTY) qderty Vietnamese (QĐERTY) eu eu EurKEY (US) cat dan eng est fao fin ger gre gsw ita lav lit nld nor por spa swe cm cm English (Cameroon) mmuock Mmuock trans International Phonetic Alphabet in in Indian modi-kagapa mr Modi (KaGaPa phonetic) mar lv3 Key to choose the 3rd level parens Parentheses position xkbcommon-libxkbcommon-54ee7ac/test/data/rules/evdev.xml000066400000000000000000007133111510033435100235460ustar00rootroot00000000000000 pc86 Generic 86-key PC Generic pc101 Generic 101-key PC Generic pc102 Generic 102-key PC Generic pc104 Generic 104-key PC Generic pc104alt Generic 104-key PC with L-shaped Enter key Generic pc105 Generic 105-key PC Generic dell101 Dell 101-key PC Dell latitude Dell Latitude laptop Dell dellm65 Dell Precision M65 laptop Dell everex Everex STEPnote Everex flexpro Keytronic FlexPro Keytronic microsoft Microsoft Natural Microsoft omnikey101 Northgate OmniKey 101 Northgate winbook Winbook Model XP5 Generic pc98 PC-98 Generic a4techKB21 A4Tech KB-21 A4Tech a4techKBS8 A4Tech KBS-8 A4Tech a4_rfkb23 A4Tech Wireless Desktop RFKB-23 A4Tech airkey Acer AirKey V Acer azonaRF2300 Azona RF2300 wireless Internet Azona scorpius Advance Scorpius KI Scorpius brother Brother Internet Brother btc5113rf BTC 5113RF Multimedia BTC btc5126t BTC 5126T BTC btc6301urf BTC 6301URF BTC btc9000 BTC 9000 BTC btc9000a BTC 9000A BTC btc9001ah BTC 9001AH BTC btc5090 BTC 5090 BTC btc9019u BTC 9019U BTC btc9116u BTC 9116U Mini Wireless Internet and Gaming cherryblue Cherry Blue Line CyBo@rd cherryblueb Cherry CyMotion Master XPress Cherry cherrybluea Cherry Blue Line CyBo@rd (alt.) Cherry cherrycyboard Cherry CyBo@rd USB-Hub Cherry cherrycmexpert Cherry CyMotion Expert Cherry cherrybunlim Cherry B.UNLIMITED Cherry chicony Chicony Internet Chicony chicony0108 Chicony KU-0108 Chicony chicony0420 Chicony KU-0420 Chicony chicony9885 Chicony KB-9885 Chicony compaqeak8 Compaq Easy Access Compaq compaqik7 Compaq Internet (7 keys) Compaq compaqik13 Compaq Internet (13 keys) Compaq compaqik18 Compaq Internet (18 keys) Compaq cymotionlinux Cherry CyMotion Master Linux Cherry armada Compaq Armada laptop Compaq presario Compaq Presario laptop Compaq ipaq Compaq iPaq Compaq dell Dell Dell dellsk8125 Dell SK-8125 Dell dellsk8135 Dell SK-8135 Dell dellusbmm Dell USB Multimedia Dell inspiron Dell Inspiron 6000/8000 laptop Dell precision_m Dell Precision M laptop Dell dexxa Dexxa Wireless Desktop Dexxa diamond Diamond 9801/9802 Diamond dtk2000 DTK2000 ennyah_dkb1008 Ennyah DKB-1008 Ennyah fscaa1667g Fujitsu-Siemens Amilo laptop Fujitsu-Siemens genius Genius Comfy KB-16M/Multimedia KWD-910 Genius geniuscomfy Genius Comfy KB-12e Genius geniuscomfy2 Genius Comfy KB-21e-Scroll Genius geniuskb19e Genius KB-19e NB Genius geniuskkb2050hs Genius KKB-2050HS Genius gyration Gyration Gyration kinesis Kinesis Kinesis logitech_base Logitech Logitech logitech_g15 Logitech G15 extra keys via G15daemon Logitech hpi6 Hewlett-Packard Internet Hewlett-Packard hp250x Hewlett-Packard NEC SK-2500 Multimedia Hewlett-Packard hpxe3gc Hewlett-Packard Omnibook XE3 GC Hewlett-Packard hpxe3gf Hewlett-Packard Omnibook XE3 GF Hewlett-Packard hpxt1000 Hewlett-Packard Omnibook XT1000 Hewlett-Packard hpdv5 Hewlett-Packard Pavilion dv5 Hewlett-Packard hpzt11xx Hewlett-Packard Pavilion ZT1100 Hewlett-Packard hp500fa Hewlett-Packard Omnibook 500 FA Hewlett-Packard hp5xx Hewlett-Packard Omnibook 500 Hewlett-Packard hpnx9020 Hewlett-Packard nx9020 Hewlett-Packard hp6000 Hewlett-Packard Omnibook 6000/6100 Hewlett-Packard honeywell_euroboard Honeywell Euroboard Hewlett-Packard hpmini110 Hewlett-Packard Mini 110 laptop Hewlett-Packard rapidaccess IBM Rapid Access Lenovo (previously IBM) rapidaccess2 IBM Rapid Access II Lenovo (previously IBM) thinkpad IBM ThinkPad 560Z/600/600E/A22E Lenovo (previously IBM) thinkpad60 IBM ThinkPad R60/T60/R61/T61 Lenovo (previously IBM) thinkpadz60 IBM ThinkPad Z60m/Z60t/Z61m/Z61t Lenovo (previously IBM) ibm_spacesaver IBM Space Saver Lenovo (previously IBM) logiaccess Logitech Access Logitech logiclx300 Logitech Cordless Desktop LX-300 Logitech logii350 Logitech Internet 350 Logitech 046d:c313 logimel Logitech Internet 350 Logitech logicd Logitech Cordless Desktop Logitech logicd_it Logitech Cordless Desktop iTouch Logitech logicd_nav Logitech Cordless Desktop Navigator Logitech logicd_opt Logitech Cordless Desktop Optical Logitech logicda Logitech Cordless Desktop (alt.) Logitech logicdpa2 Logitech Cordless Desktop Pro (2nd alt.) Logitech logicfn Logitech Cordless Freedom/Desktop Navigator Logitech logicdn Logitech Cordless Desktop Navigator Logitech logiitc Logitech iTouch Cordless Y-RB6 Logitech logiik Logitech Internet Logitech itouch Logitech iTouch Logitech logicink Logitech Internet Navigator Logitech logiex110 Logitech Cordless Desktop EX110 Logitech logiinkse Logitech iTouch Internet Navigator SE Logitech logiinkseusb Logitech iTouch Internet Navigator SE USB Logitech logiultrax Logitech Ultra-X Logitech logiultraxc Logitech Ultra-X Cordless Media Desktop Logitech logidinovo Logitech diNovo Logitech logidinovoedge Logitech diNovo Edge Logitech mx1998 Memorex MX1998 Memorex mx2500 Memorex MX2500 EZ-Access Memorex mx2750 Memorex MX2750 Memorex microsoft4000 Microsoft Natural Ergonomic 4000 Microsoft microsoft7000 Microsoft Natural Wireless Ergonomic 7000 Microsoft microsoftinet Microsoft Internet Microsoft microsoftpro Microsoft Natural Pro/Internet Pro Microsoft microsoftprousb Microsoft Natural Pro USB/Internet Pro Microsoft microsoftprooem Microsoft Natural Pro OEM Microsoft vsonku306 ViewSonic KU-306 Internet ViewSonic microsoftprose Microsoft Internet Pro (Swedish) Microsoft microsoftoffice Microsoft Office Keyboard Microsoft microsoftmult Microsoft Wireless Multimedia 1.0A Microsoft microsoftsurface Microsoft Surface Microsoft microsoftelite Microsoft Natural Elite Microsoft microsoftccurve2k Microsoft Comfort Curve 2000 Microsoft oretec Ortek Multimedia/Internet MCK-800 Ortek propeller Propeller Voyager KTEZ-1000 KeyTronic qtronix QTronix Scorpius 98N+ QTronix samsung4500 Samsung SDM 4500P Samsung samsung4510 Samsung SDM 4510P Samsung sanwaskbkg3 Sanwa Supply SKB-KG3 Sanwa Supply Inc. sk1300 NEC SK-1300 NEC sk2500 NEC SK-2500 NEC sk6200 NEC SK-6200 NEC sk7100 NEC SK-7100 NEC sp_inet Super Power Multimedia Generic sven SVEN Ergonomic 2500 SVEN sven303 SVEN Slim 303 SVEN symplon Symplon PaceBook tablet Symplon toshiba_s3000 Toshiba Satellite S3000 Toshiba trust Trust Wireless Classic Trust trustda Trust Direct Access Trust trust_slimline Trust Slimline Trust tm2020 TypeMatrix EZ-Reach 2020 TypeMatrix tm2030PS2 TypeMatrix EZ-Reach 2030 PS2 TypeMatrix tm2030USB TypeMatrix EZ-Reach 2030 USB TypeMatrix tm2030USB-102 TypeMatrix EZ-Reach 2030 USB (102/105:EU mode) TypeMatrix tm2030USB-106 TypeMatrix EZ-Reach 2030 USB (106:JP mode) TypeMatrix yahoo Yahoo! Internet Yahoo! macbook78 MacBook/MacBook Pro Apple macbook79 MacBook/MacBook Pro (intl.) Apple macintosh Macintosh Apple macintosh_old Macintosh Old Apple macintosh_hhk Happy Hacking for Mac Fujitsu acer_c300 Acer C300 Acer acer_ferrari4k Acer Ferrari 4000 Acer acer_laptop Acer laptop Acer asus_laptop Asus laptop Asus apple Apple Apple apple_laptop Apple laptop Apple applealu_ansi Apple Aluminium (ANSI) Apple applealu_iso Apple Aluminium (ISO) Apple applealu_jis Apple Aluminium (JIS) Apple silvercrest Silvercrest Multimedia Wireless Silvercrest emachines eMachines m6800 laptop eMachines benqx BenQ X-Touch BenQ benqx730 BenQ X-Touch 730 BenQ benqx800 BenQ X-Touch 800 BenQ hhk Happy Hacking Fujitsu classmate Classmate PC Intel olpc OLPC OLPC sun_type7_usb Sun Type 7 USB Sun Microsystems sun_type7_euro_usb Sun Type 7 USB (European) Sun Microsystems sun_type7_unix_usb Sun Type 7 USB (Unix) Sun Microsystems sun_type7_jp_usb Sun Type 7 USB (Japanese)/Japanese 106-key Sun Microsystems sun_type6_usb Sun Type 6/7 USB Sun Microsystems sun_type6_euro_usb Sun Type 6/7 USB (European) Sun Microsystems sun_type6_unix_usb Sun Type 6 USB (Unix) Sun Microsystems sun_type6_jp_usb Sun Type 6 USB (Japanese) Sun Microsystems sun_type6_jp Sun Type 6 (Japanese) Sun Microsystems targa_v811 Targa Visionary 811 Targa unitekkb1925 Unitek KB-1925 Unitek Group compalfl90 FL90 Compal Electronics creativedw7000 Creative Desktop Wireless 7000 Creative teck227 Truly Ergonomic 227 Truly Ergonomic teck229 Truly Ergonomic 229 Truly Ergonomic apex300 SteelSeries Apex 300 (Apex RAW) SteelSeries chromebook Chromebook Google teck227 Truly Ergonomic Computer Keyboard Model 227 (Wide Alt keys) Megawin Technology teck229 Truly Ergonomic Computer Keyboard Model 229 (Standard sized Alt keys, additional Super and Menu key) Megawin Technology us en English (US) eng chr chr Cherokee chr haw haw Hawaiian haw euro English (US, euro on 5) intl English (US, intl., with dead keys) alt-intl English (US, alt. intl.) colemak English (Colemak) dvorak English (Dvorak) dvorak-intl English (Dvorak, intl., with dead keys) dvorak-alt-intl English (Dvorak, alt. intl.) dvorak-l English (Dvorak, left-handed) dvorak-r English (Dvorak, right-handed) dvorak-classic English (classic Dvorak) dvp English (programmer Dvorak) rus ru Russian (US, phonetic) rus mac English (Macintosh) altgr-intl English (intl., with AltGr dead keys) eng fra deu olpc2 English (the divide/multiply toggle the layout) hbs Serbo-Croatian (US) eng bos hbs hrv srp norman English (Norman) workman English (Workman) workman-intl English (Workman, intl., with dead keys) af fa Afghani ps ps Pashto pus uz uz Uzbek (Afghanistan) uzb olpc-ps ps Pashto (Afghanistan, OLPC) pus fa-olpc fa Persian (Afghanistan, Dari OLPC) uz-olpc uz Uzbek (Afghanistan, OLPC) uzb ara ar Arabic AE BH DZ EG EH JO KW LB LY MA MR OM PS QA SA SD SY TN YE ara azerty Arabic (AZERTY) azerty_digits Arabic (AZERTY, Eastern Arabic numerals) digits Arabic (Eastern Arabic numerals) qwerty Arabic (QWERTY) qwerty_digits Arabic (QWERTY, Eastern Arabic numerals) buckwalter Arabic (Buckwalter) olpc Arabic (OLPC) mac Arabic (Macintosh) al sq Albanian sqi plisi Albanian (Plisi) veqilharxhi Albanian (Veqilharxhi) am hy Armenian hye phonetic Armenian (phonetic) phonetic-alt Armenian (alt. phonetic) eastern Armenian (eastern) western Armenian (western) eastern-alt Armenian (alt. eastern) at de German (Austria) deu nodeadkeys German (Austria, no dead keys) sundeadkeys German (Austria, Sun dead keys) mac German (Austria, Macintosh) au en English (Australian) eng az az Azerbaijani aze cyrillic Azerbaijani (Cyrillic) by by Belarusian bel legacy Belarusian (legacy) latin Belarusian (Latin) ru Russian (Belarus) intl Belarusian (intl.) be be Belgian deu nld fra oss Belgian (alt.) oss_latin9 Belgian (Latin-9 only, alt.) oss_sundeadkeys Belgian (Sun dead keys, alt.) iso-alternate Belgian (ISO, alt.) nodeadkeys Belgian (no dead keys) sundeadkeys Belgian (Sun dead keys) wang Belgian (Wang 724 AZERTY) bd bn Bangla ben sat probhat Bangla (Probhat) in in Indian ben bn Bangla (India) ben sat ben_probhat bn Bangla (India, Probhat) ben sat ben_baishakhi Bangla (India, Baishakhi) ben sat ben_bornona Bangla (India, Bornona) ben sat ben_gitanjali Bangla (India, Gitanjali) ben sat ben_inscript Bangla (India, Baishakhi Inscript) ben sat eeyek Manipuri (Eeyek) mni guj gu Gujarati guj guru pa Punjabi (Gurmukhi) pan jhelum pa Punjabi (Gurmukhi Jhelum) pan kan kn Kannada kan kan-kagapa kn Kannada (KaGaPa, phonetic) kan mal ml Malayalam mal mal_lalitha ml Malayalam (Lalitha) mal mal_enhanced ml Malayalam (enhanced Inscript, with rupee) mal ori or Oriya ori sat olck sat Ol Chiki sat tam_tamilnet ta Tamil (TamilNet '99) tam tam_tamilnet_with_tam_nums ta Tamil (TamilNet '99 with Tamil numerals) tam tam_tamilnet_TAB ta Tamil (TamilNet '99, TAB encoding) tam tam_tamilnet_TSCII ta Tamil (TamilNet '99, TSCII encoding) tam tam ta Tamil (Inscript) tam tel te Telugu tel tel-kagapa te Telugu (KaGaPa, phonetic) tel tel-sarala te Telugu (Sarala) tel tel-kagapa te Telugu (KaGaPa, phonetic) tel urd-phonetic ur Urdu (phonetic) urd urd-phonetic3 ur Urdu (alt. phonetic) urd urd-winkeys ur Urdu (Windows) urd bolnagri hi Hindi (Bolnagri) hin hin-wx hi Hindi (Wx) hin hin-kagapa hi Hindi (KaGaPa, phonetic) hin san-kagapa sa Sanskrit (KaGaPa, phonetic) san mar-kagapa mr Marathi (KaGaPa, phonetic) mar eng en English (India, with rupee) eng iipa iipa Indic IPA (IIPA) eng marathi ins मराठी इन्स्क्रिप्ट eng ba bs Bosnian bos alternatequotes Bosnian (with guillemets) unicode Bosnian (with Bosnian digraphs) unicodeus Bosnian (US, with Bosnian digraphs) us Bosnian (US) br pt Portuguese (Brazil) por nodeadkeys Portuguese (Brazil, no dead keys) dvorak Portuguese (Brazil, Dvorak) nativo Portuguese (Brazil, Nativo) nativo-us Portuguese (Brazil, Nativo for US keyboards) nativo-epo Esperanto (Brazil, Nativo) epo thinkpad Portuguese (Brazil, IBM/Lenovo ThinkPad) bg bg Bulgarian bul phonetic Bulgarian (traditional phonetic) bas_phonetic Bulgarian (new phonetic) dz kab Kabylian (azerty layout, no dead keys) azerty-deadkeys kab Kabylian (azerty layout, with dead keys) kab qwerty-gb-deadkeys kab Kabylian (qwerty-gb layout, with dead keys) kab qwerty-us-deadkeys kab Kabylian (qwerty-us layout, with dead keys) kab ber kab Kabylian (Algeria, Tifinagh) kab ar ar Arabic (Algeria) ara ma ar Arabic (Morocco) french fr French (Morocco) fra tifinagh ber Berber (Morocco, Tifinagh) ber tifinagh-alt ber Berber (Morocco, Tifinagh alt.) ber tifinagh-alt-phonetic ber Berber (Morocco, Tifinagh phonetic, alt.) ber tifinagh-extended ber Berber (Morocco, Tifinagh extended) ber tifinagh-phonetic ber Berber (Morocco, Tifinagh phonetic) ber tifinagh-extended-phonetic ber Berber (Morocco, Tifinagh extended phonetic) ber cm cm English (Cameroon) eng french French (Cameroon) fra qwerty Cameroon Multilingual (QWERTY, intl.) eng bas nmg fub ewo xmd mfh bkm ozm lns sox pny wes lem nyj mfk mcp ass xed dua anv bum btb bfd azo ken yam yat yas azerty Cameroon (AZERTY, intl.) fra bas nmg fub ewo xmd mfh bkm ozm lns sox pny wes lem nyj mfk mcp ass xed dua anv bum btb bfd azo ken yam yat yas dvorak Cameroon (Dvorak, intl.) mmuock Mmuock mm my Burmese mya zawgyi zg Burmese Zawgyi ca fr French (Canada) fra fr-dvorak fr French (Canada, Dvorak) fr-legacy fr French (Canada, legacy) multix Canadian (intl.) multi Canadian (intl., 1st part) multi-2gr Canadian (intl., 2nd part) ike ike Inuktitut iku eng en English (Canada) eng cd fr French (Democratic Republic of the Congo) fra cn zh Chinese zho mon_trad Mongolian (Bichig) mvf mon_trad_todo Mongolian (Todo) mvf mon_trad_xibe Mongolian (Xibe) sjo mon_trad_manchu Mongolian (Manchu) mnc mon_trad_galik Mongolian (Galik) mvf mon_todo_galik Mongolian (Todo Galik) mvf mon_manchu_galik Mongolian (Manchu Galik) mnc tib Tibetan tib tib_asciinum Tibetan (with ASCII numerals) tib ug ug Uyghur uig altgr-pinyin Hanyu Pinyin (with AltGr dead keys) zho hr hr Croatian hrv alternatequotes Croatian (with guillemets) unicode Croatian (with Croatian digraphs) unicodeus Croatian (US, with Croatian digraphs) us Croatian (US) cz cs Czech ces bksl Czech (with <\|> key) qwerty Czech (QWERTY) qwerty_bksl Czech (QWERTY, extended backslash) qwerty-mac Czech (QWERTY, Macintosh) ucw Czech (UCW, only accented letters) dvorak-ucw Czech (US, Dvorak, UCW support) rus ru Russian (Czech, phonetic) rus dk da Danish dan nodeadkeys Danish (no dead keys) winkeys Danish (Windows) mac Danish (Macintosh) mac_nodeadkeys Danish (Macintosh, no dead keys) dvorak Danish (Dvorak) nl nl Dutch nld sundeadkeys Dutch (Sun dead keys) mac Dutch (Macintosh) std Dutch (standard) bt dz Dzongkha dzo ee et Estonian est nodeadkeys Estonian (no dead keys) dvorak Estonian (Dvorak) us Estonian (US) ir fa Persian fas pes_keypad Persian (with Persian keypad) ku ku Kurdish (Iran, Latin Q) kur ku_f ku Kurdish (Iran, F) kur ku_alt ku Kurdish (Iran, Latin Alt-Q) kur ku_ara ku Kurdish (Iran, Arabic-Latin) kur iq ar Iraqi ara kur ku ku Kurdish (Iraq, Latin Q) kur ku_f ku Kurdish (Iraq, F) kur ku_alt ku Kurdish (Iraq, Latin Alt-Q) kur ku_ara ku Kurdish (Iraq, Arabic-Latin) kur fo fo Faroese fao nodeadkeys Faroese (no dead keys) fi fi Finnish fin winkeys Finnish (Windows) classic Finnish (classic) nodeadkeys Finnish (classic, no dead keys) smi Northern Saami (Finland) sme mac Finnish (Macintosh) fr fr French fra nodeadkeys French (no dead keys) sundeadkeys French (Sun dead keys) oss French (alt.) oss_latin9 French (alt., Latin-9 only) oss_nodeadkeys French (alt., no dead keys) oss_sundeadkeys French (alt., Sun dead keys) latin9 French (legacy, alt.) latin9_nodeadkeys French (legacy, alt., no dead keys) latin9_sundeadkeys French (legacy, alt., Sun dead keys) bepo French (BEPO) bepo_latin9 French (BEPO, Latin-9 only) bepo_afnor French (BEPO, AFNOR) dvorak French (Dvorak) mac French (Macintosh) azerty French (AZERTY) afnor French (AZERTY, AFNOR) bre French (Breton) oci Occitan oci geo Georgian (France, AZERTY Tskapo) kat us French (US) gh en English (Ghana) eng generic English (Ghana, multilingual) akan ak Akan aka ewe ee Ewe ewe fula ff Fula ful ga gaa Ga gaa hausa ha Hausa (Ghana) hau avn avn Avatime avn gillbt English (Ghana, GILLBT) gn fr French (Guinea) fra ge ka Georgian kat ergonomic Georgian (ergonomic) mess Georgian (MESS) ru ru Russian (Georgia) rus os Ossetian (Georgia) oss de de German deu deadacute German (dead acute) deadgraveacute German (dead grave acute) nodeadkeys German (no dead keys) T3 German (T3) ro Romanian (Germany) ron ro_nodeadkeys Romanian (Germany, no dead keys) ron dvorak German (Dvorak) sundeadkeys German (Sun dead keys) neo German (Neo 2) mac German (Macintosh) mac_nodeadkeys German (Macintosh, no dead keys) dsb Lower Sorbian dsb dsb_qwertz Lower Sorbian (QWERTZ) dsb qwerty German (QWERTY) tr Turkish (Germany) tr ru ru Russian (Germany, phonetic) rus deadtilde German (dead tilde) gr gr Greek ell simple Greek (simple) extended Greek (extended) nodeadkeys Greek (no dead keys) polytonic Greek (polytonic) hu hu Hungarian hun standard Hungarian (standard) nodeadkeys Hungarian (no dead keys) qwerty Hungarian (QWERTY) 101_qwertz_comma_dead Hungarian (QWERTZ, 101-key, comma, dead keys) 101_qwertz_comma_nodead Hungarian (QWERTZ, 101-key, comma, no dead keys) 101_qwertz_dot_dead Hungarian (QWERTZ, 101-key, dot, dead keys) 101_qwertz_dot_nodead Hungarian (QWERTZ, 101-key, dot, no dead keys) 101_qwerty_comma_dead Hungarian (QWERTY, 101-key, comma, dead keys) 101_qwerty_comma_nodead Hungarian (QWERTY, 101-key, comma, no dead keys) 101_qwerty_dot_dead Hungarian (QWERTY, 101-key, dot, dead keys) 101_qwerty_dot_nodead Hungarian (QWERTY, 101-key, dot, no dead keys) 102_qwertz_comma_dead Hungarian (QWERTZ, 102-key, comma, dead keys) 102_qwertz_comma_nodead Hungarian (QWERTZ, 102-key, comma, no dead keys) 102_qwertz_dot_dead Hungarian (QWERTZ, 102-key, dot, dead keys) 102_qwertz_dot_nodead Hungarian (QWERTZ, 102-key, dot, no dead keys) 102_qwerty_comma_dead Hungarian (QWERTY, 102-key, comma, dead keys) 102_qwerty_comma_nodead Hungarian (QWERTY, 102-key, comma, no dead keys) 102_qwerty_dot_dead Hungarian (QWERTY, 102-key, dot, dead keys) 102_qwerty_dot_nodead Hungarian (QWERTY, 102-key, dot, no dead keys) is is Icelandic isl Sundeadkeys Icelandic (Sun dead keys) nodeadkeys Icelandic (no dead keys) mac_legacy Icelandic (Macintosh, legacy) mac Icelandic (Macintosh) dvorak Icelandic (Dvorak) il he Hebrew heb lyx Hebrew (lyx) phonetic Hebrew (phonetic) biblical Hebrew (Biblical, Tiro) it it Italian ita nodeadkeys Italian (no dead keys) winkeys Italian (Windows) mac Italian (Macintosh) us Italian (US) geo Georgian (Italy) kat ibm Italian (IBM 142) intl Italian (intl., with dead keys) deu fra ita slk srd nap scn fur scn Sicilian ita scn fur Friulian (Italy) fur jp ja Japanese jpn kana Japanese (Kana) kana86 Japanese (Kana 86) OADG109A Japanese (OADG 109A) mac Japanese (Macintosh) dvorak Japanese (Dvorak) kg ki Kyrgyz kir phonetic Kyrgyz (phonetic) kh km Khmer (Cambodia) khm kz kk Kazakh kaz ruskaz ru Russian (Kazakhstan, with Kazakh) kaz rus kazrus Kazakh (with Russian) kaz rus ext Kazakh (extended) kaz latin Kazakh (Latin) kaz la lo Lao lao stea Lao (STEA) lao latam es Spanish (Latin American) AR BO CL CO CR CU DO EC GT HN HT MX NI PA PE PR PY SV US UY VE spa nodeadkeys Spanish (Latin American, no dead keys) deadtilde Spanish (Latin American, dead tilde) sundeadkeys Spanish (Latin American, Sun dead keys) dvorak Spanish (Latin American, Dvorak) colemak Spanish (Latin American, Colemak) colemak-gaming Spanish (Latin American, Colemak for gaming) lt lt Lithuanian lit std Lithuanian (standard) us Lithuanian (US) ibm Lithuanian (IBM LST 1205-92) lekp Lithuanian (LEKP) lekpa Lithuanian (LEKPa) sgs Samogitian sgs lv lv Latvian lav apostrophe Latvian (apostrophe) tilde Latvian (tilde) fkey Latvian (F) modern Latvian (modern) ergonomic Latvian (ergonomic, ŪGJRMV) adapted Latvian (adapted) mao mi Maori mri me sr Montenegrin srp cyrillic Montenegrin (Cyrillic) cyrillicyz Montenegrin (Cyrillic, ZE and ZHE swapped) latinunicode Montenegrin (Latin, Unicode) latinyz Montenegrin (Latin, QWERTY) latinunicodeyz Montenegrin (Latin, Unicode, QWERTY) cyrillicalternatequotes Montenegrin (Cyrillic, with guillemets) latinalternatequotes Montenegrin (Latin, with guillemets) mk mk Macedonian mkd nodeadkeys Macedonian (no dead keys) mt mt Maltese mlt us Maltese (US) alt-us Maltese (US layout with AltGr overrides) alt-gb Maltese (UK, with AltGr overrides) mn mn Mongolian mon no no Norwegian nor nob nno nodeadkeys Norwegian (no dead keys) winkeys Norwegian (Windows) dvorak Norwegian (Dvorak) smi Northern Saami (Norway) sme smi_nodeadkeys Northern Saami (Norway, no dead keys) sme mac Norwegian (Macintosh) mac_nodeadkeys Norwegian (Macintosh, no dead keys) colemak Norwegian (Colemak) pl pl Polish pol legacy Polish (legacy) qwertz Polish (QWERTZ) dvorak Polish (Dvorak) dvorak_quotes Polish (Dvorak, with Polish quotes on quotemark key) dvorak_altquotes Polish (Dvorak, with Polish quotes on key 1) csb Kashubian csb szl Silesian szl ru_phonetic_dvorak ru Russian (Poland, phonetic Dvorak) rus dvp Polish (programmer Dvorak) pt pt Portuguese por nodeadkeys Portuguese (no dead keys) sundeadkeys Portuguese (Sun dead keys) mac Portuguese (Macintosh) mac_nodeadkeys Portuguese (Macintosh, no dead keys) mac_sundeadkeys Portuguese (Macintosh, Sun dead keys) nativo Portuguese (Nativo) nativo-us Portuguese (Nativo for US keyboards) nativo-epo Esperanto (Portugal, Nativo) epo ro ro Romanian ron cedilla Romanian (cedilla) std Romanian (standard) std_cedilla Romanian (standard cedilla) winkeys Romanian (Windows) ru ru Russian rus phonetic Russian (phonetic) phonetic_winkeys Russian (phonetic, Windows) phonetic_YAZHERTY Russian (phonetic, YAZHERTY) typewriter Russian (typewriter) legacy Russian (legacy) typewriter-legacy Russian (typewriter, legacy) tt Tatar tat os_legacy Ossetian (legacy) oss os_winkeys Ossetian (Windows) oss cv Chuvash chv cv_latin Chuvash (Latin) chv udm Udmurt udm kom Komi kom sah Yakut sah xal Kalmyk xal dos Russian (DOS) mac Russian (Macintosh) srp Serbian (Russia) rus srp bak Bashkirian bak chm Mari chm phonetic_azerty Russian (phonetic, AZERTY) phonetic_dvorak Russian (phonetic, Dvorak) phonetic_fr Russian (phonetic, French) rs sr Serbian srp yz Serbian (Cyrillic, ZE and ZHE swapped) latin Serbian (Latin) latinunicode Serbian (Latin, Unicode) latinyz Serbian (Latin, QWERTY) latinunicodeyz Serbian (Latin, Unicode, QWERTY) alternatequotes Serbian (Cyrillic, with guillemets) latinalternatequotes Serbian (Latin, with guillemets) rue Pannonian Rusyn rue si sl Slovenian slv alternatequotes Slovenian (with guillemets) us Slovenian (US) sk sk Slovak slk bksl Slovak (extended backslash) qwerty Slovak (QWERTY) qwerty_bksl Slovak (QWERTY, extended backslash) es es Spanish spa nodeadkeys Spanish (no dead keys) winkeys Spanish (Windows) deadtilde Spanish (dead tilde) sundeadkeys Spanish (Sun dead keys) dvorak Spanish (Dvorak) ast ast Asturian (Spain, with bottom-dot H and L) ast cat ca Catalan (Spain, with middle-dot L) cat mac Spanish (Macintosh) se sv Swedish swe nodeadkeys Swedish (no dead keys) dvorak Swedish (Dvorak) rus ru Russian (Sweden, phonetic) rus rus_nodeadkeys ru Russian (Sweden, phonetic, no dead keys) rus smi Northern Saami (Sweden) sme mac Swedish (Macintosh) svdvorak Swedish (Svdvorak) us_dvorak Swedish (Dvorak, intl.) us Swedish (US) swl Swedish Sign Language swl ch de German (Switzerland) deu gsw legacy German (Switzerland, legacy) de_nodeadkeys de German (Switzerland, no dead keys) de_sundeadkeys de German (Switzerland, Sun dead keys) fr fr French (Switzerland) fra fr_nodeadkeys fr French (Switzerland, no dead keys) fra fr_sundeadkeys fr French (Switzerland, Sun dead keys) fra fr_mac fr French (Switzerland, Macintosh) fra de_mac de German (Switzerland, Macintosh) sy ar Arabic (Syria) syr syc syc Syriac syc_phonetic syc Syriac (phonetic) ku ku Kurdish (Syria, Latin Q) kur ku_f ku Kurdish (Syria, F) kur ku_alt ku Kurdish (Syria, Latin Alt-Q) kur tj tg Tajik tgk legacy Tajik (legacy) lk si Sinhala (phonetic) sin tam_unicode ta Tamil (Sri Lanka, TamilNet '99) tam tam_TAB Tamil (Sri Lanka, TamilNet '99, TAB encoding) tam us us Sinhala (US) th th Thai tha tis Thai (TIS-820.2538) pat Thai (Pattachote) tr tr Turkish tur f Turkish (F) alt Turkish (Alt-Q) sundeadkeys Turkish (Sun dead keys) ku ku Kurdish (Turkey, Latin Q) kur ku_f ku Kurdish (Turkey, F) kur ku_alt ku Kurdish (Turkey, Latin Alt-Q) kur intl Turkish (intl., with dead keys) crh crh Crimean Tatar (Turkish Q) crh crh_f crh Crimean Tatar (Turkish F) crh crh_alt crh Crimean Tatar (Turkish Alt-Q) crh tw zh Taiwanese fox indigenous Taiwanese (indigenous) ami tay bnn ckv pwn pyu dru ais ssf tao tsu trv xnb sxr uun fos saisiyat xsy Saisiyat (Taiwan) xsy ua uk Ukrainian ukr phonetic Ukrainian (phonetic) typewriter Ukrainian (typewriter) winkeys Ukrainian (Windows) legacy Ukrainian (legacy) rstu Ukrainian (standard RSTU) rstu_ru Russian (Ukraine, standard RSTU) homophonic Ukrainian (homophonic) gb en English (UK) eng extd English (UK, extended, Windows) intl English (UK, intl., with dead keys) dvorak English (UK, Dvorak) dvorakukp English (UK, Dvorak, with UK punctuation) mac English (UK, Macintosh) mac_intl English (UK, Macintosh, intl.) colemak English (UK, Colemak) pl pl Polish (British keyboard) pol uz uz Uzbek uzb latin Uzbek (Latin) vn vi Vietnamese vie us Vietnamese (US) fr Vietnamese (French) kr ko Korean kor kr104 Korean (101/104-key compatible) nec_vndr/jp ja Japanese (PC-98) JP jpn ie ie Irish eng CloGaelach CloGaelach gle UnicodeExpert Irish (UnicodeExpert) ogam Ogham sga ogam_is434 Ogham (IS434) sga pk ur Urdu (Pakistan) urd urd-crulp Urdu (Pakistan, CRULP) urd-nla Urdu (Pakistan, NLA) ara ar Arabic (Pakistan) ara snd sd Sindhi snd mv dv Dhivehi div za en English (South Africa) eng epo eo Esperanto epo legacy Esperanto (legacy) np ne Nepali nep sat ng en English (Nigeria) eng igbo ig Igbo ibo yoruba yo Yoruba yor hausa ha Hausa (Nigeria) hau et am Amharic amh sn wo Wolof wol brai brl Braille left_hand Braille (left-handed) left_hand_invert Braille (left-handed inverted thumb) right_hand Braille (right-handed) right_hand_invert Braille (right-handed inverted thumb) tm tk Turkmen tuk alt Turkmen (Alt-Q) ml bm Bambara bam fr-oss fr French (Mali, alt.) fra us-mac en English (Mali, US, Macintosh) eng us-intl en English (Mali, US, intl.) eng tz sw Swahili (Tanzania) swa tg fr-tg French (Togo) fra ajg blo kpo ewe fon fue gej ife kbp las dop mfg nmz bud gng kdh soy ke sw Swahili (Kenya) swa kik ki Kikuyu kik bw tn Tswana tsn ph ph Filipino eng bik ceb fil hil ilo pam pag phi tgl war qwerty-bay Filipino (QWERTY, Baybayin) bik ceb fil hil ilo pam pag phi tgl war capewell-dvorak Filipino (Capewell-Dvorak, Latin) capewell-dvorak-bay Filipino (Capewell-Dvorak, Baybayin) bik ceb fil hil ilo pam pag phi tgl war capewell-qwerf2k6 Filipino (Capewell-QWERF 2006, Latin) capewell-qwerf2k6-bay Filipino (Capewell-QWERF 2006, Baybayin) bik ceb fil hil ilo pam pag phi tgl war colemak Filipino (Colemak, Latin) colemak-bay Filipino (Colemak, Baybayin) bik ceb fil hil ilo pam pag phi tgl war dvorak Filipino (Dvorak, Latin) dvorak-bay Filipino (Dvorak, Baybayin) bik ceb fil hil ilo pam pag phi tgl war md md Moldavian ron gag gag Moldavian (Gagauz) gag id id Indonesian (Arab Melayu, phonetic) ind msa min ace bjn tsg mfa phoneticx Indonesian (Arab Melayu, extended phonetic) jv jv Indonesian (Javanese) jv my ms Malay (Jawi, Arabic Keyboard) ind msa min ace bjn tsg mfa phonetic Malay (Jawi, phonetic) grp Switching to another layout lv3 Key to choose the 3rd level ctrl Ctrl position grp_led Use keyboard LED to show alternative layout mod_led Use keyboard LED to indicate modifiers keypad Layout of numeric keypad kpdl Numeric keypad Delete behavior caps Caps Lock behavior altwin Alt and Win behavior Compose key Position of Compose key compat Compatibility options currencysign Currency signs lv5 Key to choose 5th level nbsp Non-breaking space input japan Japanese keyboard options korean Korean Hangul/Hanja keys esperanto Esperanto letters with superscripts solaris Old Solaris keycodes compatibility terminate Key sequence to kill the X server xkbcommon-libxkbcommon-54ee7ac/test/data/rules/extended-wild-cards000066400000000000000000000015071510033435100254620ustar00rootroot00000000000000! model = keycodes * = evdev ! model = compat * = complete ! model = types * = complete ! model = symbols * = pc ! layout[any] variant[any] = symbols l1 = +l10:%i // compatibity mapping: l1, no variant l1 v1 = +l20:%i // compatibity mapping: l1, specific variant l1 = +l30%(v[%i]):%i // compatibity mapping: l1, some variant l2 * = +l40%(v[%i]):%i // compatibity mapping: l2, some variant (legacy) l3 = +l50%(v[%i]):%i // compatibity mapping: l3, any variant (catch-all) * v2 = +%l[%i](v20):%i // compatibity mapping: specific variant * = +%l[%i]%(v[%i]):%i // catch-all ! option = symbols opt1 = +opt1 xkbcommon-libxkbcommon-54ee7ac/test/data/rules/groups000066400000000000000000000011261510033435100231470ustar00rootroot00000000000000! $model_group = pc101 pc102 \ pc104\ pc105\ pc106 ! $layout_group = ar br cr us ! $variant_group = ! model = keycodes $model_group = something(%m) * = default_keycodes ! layout variant = symbols $layout_group * = my_symbols+%(v) * * = default_symbols ! layout = symbols $layout_group = my_symbols+%(v) * = default_symbols ! model = types * = default_types ! model = compat * = default_compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-dst-loop-twice000066400000000000000000000007021510033435100252500ustar00rootroot00000000000000! model = keycodes * = default_keycodes ! layout variant = symbols my_layout my_variant = my_symbols+extra_variant ! layout = symbols my_layout = my_symbols * = default_symbols ! model = types * = default_types ! model = compat * = default_compat ! option = compat my_option = |some:compat ! include %S/inc-src-loop-twice xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-dst-simple000066400000000000000000000006421510033435100244620ustar00rootroot00000000000000! model = keycodes my_model = my_keycodes * = default_keycodes ! layout variant = symbols my_layout my_variant = my_symbols+extra_variant ! layout = symbols * = default_symbols ! model = types * = default_types ! model = compat * = default_compat ! option = compat my_option = |some:compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-no-newline000066400000000000000000000001121510033435100244440ustar00rootroot00000000000000! include %S/inc-dst-simple !include %S/inc-dst-simple ! layout = symbols xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-src-before-after000066400000000000000000000002161510033435100255240ustar00rootroot00000000000000! model = keycodes before_model = my_keycodes ! include %S/inc-dst-simple ! layout = symbols after_layout = my_symbols xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-src-loop-twice000066400000000000000000000001321510033435100252420ustar00rootroot00000000000000! model = keycodes my_model = my_keycodes ! include %S/inc-dst-loop-twice xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-src-looped000066400000000000000000000000341510033435100244430ustar00rootroot00000000000000! include %S/inc-src-looped xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-src-nested000066400000000000000000000000341510033435100244430ustar00rootroot00000000000000! include %S/inc-src-simple xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-src-options000066400000000000000000000003671510033435100246650ustar00rootroot00000000000000! option = compat option111 = +substring option1 = +some:compat option11 = +group(bla) ! include %S/inc-dst-simple ! option = symbols option3 = +compose(foo)+keypad(bar) colon:opt = +altwin(menu) xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-src-relative-path000066400000000000000000000001211510033435100257230ustar00rootroot00000000000000! layout = symbols my_layout = my_symbols ! include inc-dst-simple xkbcommon-libxkbcommon-54ee7ac/test/data/rules/inc-src-simple000066400000000000000000000001241510033435100244520ustar00rootroot00000000000000! layout = symbols my_layout = my_symbols ! include %S/inc-dst-simple xkbcommon-libxkbcommon-54ee7ac/test/data/rules/index000066400000000000000000000013641510033435100227430ustar00rootroot00000000000000! $layouts = al az br cn us ! layout option = symbols $layouts some:opt = +extra ! layout[1] option = symbols $layouts some:opt = +extra:1 ! layout[2] option = symbols $layouts some:opt = +extra:2 ! layout[3] option = symbols $layouts some:opt = +extra:3 ! layout[4] option = symbols $layouts some:opt = +extra:4 ! model = symbols * = default_symbols ! model = keycodes * = default_keycodes ! model = types * = default_types ! model = compat * = default_compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/invalid-group-index000066400000000000000000000006321510033435100255160ustar00rootroot00000000000000! model = keycodes * = default_keycodes ! layout = symbols * = default_symbols // Invalid group index ! layout[+1] = symbols * = default_symbols // Invalid group index ! layout[+2] = symbols * = +default_symbols:2 ! model = types * = default_types ! model = compat * = default_compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/invalid-group-qualifier000066400000000000000000000006101510033435100263640ustar00rootroot00000000000000! model = keycodes * = default_keycodes ! layout = symbols * = default_symbols ! layout[1] = symbols * = default_symbols ! layout[2] = symbols // Invalid group qualifier * = +default_symbols:+2 ! model = types * = default_types ! model = compat * = default_compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/layout-specific-options000066400000000000000000000010441510033435100264200ustar00rootroot00000000000000! model = keycodes * = evdev ! model = compat * = complete ! model = types * = complete ! layout[first] = symbols * = pc ! layout[any] = symbols * = +%l[%i]:%i ! layout[first] option = symbols * opt1 = +s1:%i l2 opt2 = +s2:%i // Example from the commit introducing the feature ! layout[any] option = symbols * opt3 = +s3:%i l2 opt4 = +s4:%i ! layout[1] option = symbols * opt5 = +s5:%i ! layout[2] option = symbols * opt6 = +s6:%i // Never layout-specific ! option = symbols opt7 = +s7 xkbcommon-libxkbcommon-54ee7ac/test/data/rules/merge-mode-replace000066400000000000000000000010111510033435100252530ustar00rootroot00000000000000! model = keycodes * = evdev ! model = types * = complete ! model = compat * = complete ! layout = symbols * = pc+%l ! layout[1] = symbols * = pc+%l[1] ! layout[2] = symbols * = +%l[2]:2 ! option = symbols replace:single = ^level3(ralt_alt) replace:first = ^level3(ralt_alt)|empty replace:later = +level3(ralt_switch)^level3(ralt_alt)|empty grp:menu_toggle = +group(menu_toggle) xkbcommon-libxkbcommon-54ee7ac/test/data/rules/multiple-groups000066400000000000000000000003221510033435100247750ustar00rootroot00000000000000// Insert US layout before a single layout ! model layout = symbols * us = pc+%l%(v) * * = pc+us+%l%(v):2 ! option = symbols multiple-groups = +multiple-groups ! include evdev xkbcommon-libxkbcommon-54ee7ac/test/data/rules/multiple-options000066400000000000000000000012301510033435100251500ustar00rootroot00000000000000! model = keycodes my_model = my_keycodes * = default_keycodes ! layout variant = symbols my_layout my_variant = my_symbols+extra_variant ! layout = symbols my_layout = my_symbols * = default_symbols ! model = types my_model = my_types * = default_types ! model = compat my_model = my_compat * = default_compat ! option = compat option111 = +substring option1 = +some:compat option11 = +group(bla) ! option = symbols option3 = +compose(foo)+keypad(bar) colon:opt = +altwin(menu) xkbcommon-libxkbcommon-54ee7ac/test/data/rules/simple000066400000000000000000000007661510033435100231320ustar00rootroot00000000000000! model = keycodes my_model = my_keycodes * = default_keycodes ! layout variant = symbols my_layout my_variant = my_symbols+extra_variant ! layout = symbols my_layout = my_symbols * = default_symbols ! model = types my_model = my_types * = default_types ! model = compat my_model = my_compat * = default_compat ! option = compat my_option = |some:compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/special_indices000066400000000000000000000052551510033435100247550ustar00rootroot00000000000000! model = keycodes my_model = my_keycodes * = default_keycodes ! layout[single] variant = symbols // valid layout_a my_variant = a+extra_variant ! layout[single] = symbols layout_a = A ! layout = symbols layout_b = B layout_c = C:%i // valid, but unusual layout_d = D layout_e = E * = %l[%i]%(v[%i]) // valid, but unusual ! layout[first] = symbols layout_a = a:1 layout_b = b:1 layout_c = c:1 layout_d = d:%i // valid, but unusual layout_e = e:1 * = %l[%i]%(v[%i]) // valid, cannot be easily expressed otherwise ! layout[first] = symbols layout_e = %+l // different output if single or multiple layouts ! layout[later] = symbols layout_a = +x:%i layout_b = +y:%i * = +%l[%i]%(v[%i]):%i ! layout[any] = symbols layout_c = +z:%i ! layout[any] variant[any] = symbols * extra = +foo:%i|bar:%i ! layout[1] variant = symbols // invalid mapping * * = +AAA:%i ! layout variant[1] = symbols // invalid mapping * * = +BBB:%i ! layout[1] variant[2] = symbols // invalid mapping * * = +CCC:%i ! layout[any] variant = symbols // invalid mapping * * = +DDD:%i ! layout variant[any] = symbols // invalid mapping * * = +EEE:%i ! layout[any] variant[1] = symbols // invalid mapping * * = +FFF:%i ! layout[any] variant[first] = symbols // invalid mapping * * = +GGG:%i ! model = types my_model = my_types * = default_types ! model = compat my_model = my_compat * = default_compat ! option = symbols my_option = +extra_option // Used to check that special indices merge the KcCGST values in the // expected order. ! layout[any] option = symbols layout_c option_2 = +HHH:%i layout_b option_1 = +III:%i // should be skipped (no explicit merge mode) and // should not interact with other rules layout_b option_2 = skip layout_b option_3 = +JJJ:%i layout_c option_1 = +KKK:%i ! layout[first] option = compat symbols * option_1 = skip1 skip * option_2 = skip2 +LLL ! layout[later] option = symbols compat layout_c option_2 = +MMM:%i skip1 layout_c option_1 = +NNN:%i skip2 layout_b option_1 = +OOO:%i skip3 // Invalid %i (no layout nor variant): always discarded ! model = symbols * = +invalid:%i // Invalid %i (no layout nor variant): always discarded ! option = symbols * = +invalid-too:%i xkbcommon-libxkbcommon-54ee7ac/test/data/rules/special_indices-limit000066400000000000000000000004611510033435100260630ustar00rootroot00000000000000! model = keycodes * = default_keycodes ! layout[first] = symbols * = x:1 ! layout[later] = symbols * = +x:%i ! model = types * = default_types ! model = compat * = default_compat ! option = symbols xkbcommon-libxkbcommon-54ee7ac/test/data/rules/utf-16be_with_bom000066400000000000000000000021721510033435100250530ustar00rootroot00000000000000// NOTE: this file is encoded in UTF-16LE with a leading BOM (U+FEFF) ! model = keycodes my_model = my_keycodes * = default_keycodes ! layout variant = symbols my_layout my_variant = my_symbols+extra_variant ! layout = symbols my_layout = my_symbols * = default_symbols ! model = types my_model = my_types * = default_types ! model = compat my_model = my_compat * = default_compat ! option = compat my_option = |some:compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/utf-16le_with_bom000066400000000000000000000021721510033435100250650ustar00rootroot00000000000000// NOTE: this file is encoded in UTF-16LE with a leading BOM (U+FEFF) ! model = keycodes my_model = my_keycodes * = default_keycodes ! layout variant = symbols my_layout my_variant = my_symbols+extra_variant ! layout = symbols my_layout = my_symbols * = default_symbols ! model = types my_model = my_types * = default_types ! model = compat my_model = my_compat * = default_compat ! option = compat my_option = |some:compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/utf-32be000066400000000000000000000043601510033435100231620ustar00rootroot00000000000000// NOTE: this file is encoded in UTF-16LE with a leading BOM (U+FEFF) ! model = keycodes my_model = my_keycodes * = default_keycodes ! layout variant = symbols my_layout my_variant = my_symbols+extra_variant ! layout = symbols my_layout = my_symbols * = default_symbols ! model = types my_model = my_types * = default_types ! model = compat my_model = my_compat * = default_compat ! option = compat my_option = |some:compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/utf-8_with_bom000066400000000000000000000010741510033435100244650ustar00rootroot00000000000000// NOTE: this file is encoded in UTF-8 with a leading BOM (U+FEFF) ! model = keycodes my_model = my_keycodes * = default_keycodes ! layout variant = symbols my_layout my_variant = my_symbols+extra_variant ! layout = symbols my_layout = my_symbols * = default_symbols ! model = types my_model = my_types * = default_types ! model = compat my_model = my_compat * = default_compat ! option = compat my_option = |some:compat xkbcommon-libxkbcommon-54ee7ac/test/data/rules/wildcard000066400000000000000000000011711510033435100234210ustar00rootroot00000000000000! model = keycodes * = evdev ! model = geometry * = pc(pc104) ! layout variant = symbols * * = pc+%l%(v) ! layout[1] variant[1] = symbols * * = pc+%l[1]%(v[1]) ! layout[2] variant[2] = symbols * * = +%l[2]%(v[2]):2 ! layout[3] variant[3] = symbols * * = +%l[3]%(v[3]):3 ! layout[4] variant[3] = symbols * * = +%l[4]%(v[4]):4 ! model layout = compat * * = complete ! model layout[1] = compat * * = complete ! model layout[2] = compat * * = complete ! model = types * = complete xkbcommon-libxkbcommon-54ee7ac/test/data/rules/xkb.dtd000066400000000000000000000021451510033435100231700ustar00rootroot00000000000000 xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/000077500000000000000000000000001510033435100222435ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/altwin000066400000000000000000000066361510033435100234770ustar00rootroot00000000000000// Meta is mapped to second level of Alt. partial modifier_keys xkb_symbols "meta_alt" { key { [ Alt_L, Meta_L ] }; key { type[Group1] = "TWO_LEVEL", symbols[Group1] = [ Alt_R, Meta_R ] }; modifier_map Mod1 { Alt_L, Alt_R, Meta_L, Meta_R }; // modifier_map Mod4 {}; }; // Alt is mapped to the Super and the usual Alt. partial modifier_keys xkb_symbols "alt_win" { key { [ Alt_L ] }; key { [ Alt_R ] }; modifier_map Mod1 { , }; }; // Ctrl is mapped to the Super and the usual Ctrl keys. partial modifier_keys xkb_symbols "ctrl_win" { key { [ Control_L ] }; key { [ Control_R ] }; modifier_map Control { , }; }; // Ctrl is mapped to the Alt, Alt to the Super, and Win to the Ctrl keys. partial modifier_keys xkb_symbols "ctrl_alt_win" { key { [ Control_L, Control_L ] }; key { type[Group1] = "TWO_LEVEL", symbols[Group1] = [ Control_R, Control_R ] }; key { [ Alt_L, Meta_L ] }; key { [ Alt_R, Meta_R ] }; key { [ Super_L ] }; key { [ Super_R ] }; modifier_map Control { , }; modifier_map Mod1 { , }; modifier_map Mod4 { , }; }; // Meta is mapped to the Super. partial modifier_keys xkb_symbols "meta_win" { key { [ Alt_L, Alt_L ] }; key { type[Group1] = "TWO_LEVEL", symbols[Group1] = [ Alt_R, Alt_R ] }; key { [ Meta_L ] }; key { [ Meta_R ] }; modifier_map Mod1 { Alt_L, Alt_R }; modifier_map Mod4 { , Meta_L, Meta_R }; }; // Meta is mapped to the left Win key. partial modifier_keys xkb_symbols "left_meta_win" { key { [ Alt_L, Alt_L ] }; key { [ Meta_L ] }; modifier_map Mod1 { Alt_L }; modifier_map Mod4 { , Meta_L }; }; // Hyper is mapped to the Super. partial modifier_keys xkb_symbols "hyper_win" { key { [ Hyper_L ] }; key { [ Hyper_R ] }; modifier_map Mod4 { Hyper_L, Hyper_R }; }; // Menu is mapped to the Menu key. partial modifier_keys xkb_symbols "menu" { key

{ [ Menu ] }; }; // Menu is mapped to the right Win key. partial modifier_keys xkb_symbols "menu_win" { key { [ Super_R ] }; }; // Layout for Tux key caps with additional right Alt key partial modifier_keys xkb_symbols "alt_super_win" { key { [ Alt_L, Meta_L ] }; key { [ Alt_R, Meta_R ] }; key { [ Super_L ]}; key { [ Super_R ] }; modifier_map Mod1 { Alt_L, Alt_R, Meta_L, Meta_R }; modifier_map Mod4 { Super_L, Super_R }; }; // Swap the Alt and Super. partial modifier_keys xkb_symbols "swap_alt_win" { include "altwin(swap_lalt_lwin)" include "altwin(swap_ralt_rwin)" }; // Swap the left Alt and Super. partial modifier_keys xkb_symbols "swap_lalt_lwin" { key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ Super_L ] }; key { [ Alt_L, Meta_L ] }; }; // Swap the right Alt and Super. hidden partial modifier_keys xkb_symbols "swap_ralt_rwin" { key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ Super_R ] }; key { [ Alt_R, Meta_R ] }; }; // Win is mapped to the PrtSc key (and the usual Win key). partial modifier_keys xkb_symbols "prtsc_rwin" { replace key { [ Super_R, Super_R ] }; modifier_map Mod4 { , }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/awesome000066400000000000000000000023151510033435100236270ustar00rootroot00000000000000default alphanumeric_keys modifier_keys function_keys alternate_group xkb_symbols "awesome" { include "us" name[Group1]= "My Awesome Layout"; key { [ 2, at, Page_Up, Page_Up ] }; key { [ 3, numbersign, Page_Down, Page_Down ] }; key { [ {q, a, b}, Q, Escape, Escape ] }; key { [ w, W, Home, Home ] }; key { type="THREE_LEVEL", symbols=[ e, {E, F}, Up] }; key { [ r, R, End, End ] }; key { [ t, T, Tab, Tab ] }; // Unknown keysyms key { [{notAKeysym, ydiaeresis}, {thisEither, norThis} ] }; key { [ a, A, Return, Return ] }; key { [ s, S, Left] }; key { [ d, D, Down] }; key { [ f, F, Right] }; key { [ g, G, BackSpace, BackSpace ] }; key { [ b, B, Delete, Delete ] }; key { symbols[1] = [ {Control_L, ISO_Next_Group } ], actions[1] = [ {SetMods(modifiers=Control), SetGroup(group=+1) } ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/banana000066400000000000000000000001271510033435100234060ustar00rootroot00000000000000xkb_symbols "1" { key <> { ["🍌"] }; }; xkb_symbols "2" { key <> { ["🍊"] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/ca000066400000000000000000000517761510033435100225710ustar00rootroot00000000000000default partial xkb_symbols "fr" { name[Group1] = "French (Canada)"; key { [ numbersign, bar, backslash ] }; key { [ 1, exclam, plusminus ] }; key { [ 2, quotedbl, at ] }; key { [ 3, slash, sterling ] }; key { [ 4, dollar, cent ] }; key { [ 5, percent, currency ] }; key { [ 6, question, notsign ] }; key { [ 7, ampersand, brokenbar ] }; key { [ 8, asterisk, twosuperior ] }; key { [ 9, parenleft, threesuperior ] }; key { [ 0, parenright, onequarter ] }; key { [ minus, underscore, onehalf ] }; key { [ equal, plus, threequarters ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E ] }; key { [ r, R ] }; key { [ t, T ] }; key { [ y, Y ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ o, O, section ] }; key { [ p, P, paragraph ] }; key { [dead_circumflex, dead_circumflex, bracketleft ] }; key { [ dead_cedilla, dead_diaeresis, bracketright ] }; key { [ a, A ] }; key { [ s, S ] }; key { [ d, D ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ h, H ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ l, L ] }; key { [ semicolon, colon, asciitilde ] }; key { [dead_grave, dead_grave, braceleft ] }; key { [ less, greater, braceright ] }; key { [guillemotleft, guillemotright, degree] }; key { [ z, Z ] }; key { [ x, X ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ b, B ] }; key { [ n, N ] }; key { [ m, M, mu ] }; key { [ comma, apostrophe, macron ] }; key { [ period, period, hyphen ] }; key { [ eacute, Eacute, dead_acute ] }; key { [ space, space, nobreakspace ] }; include "level3(ralt_switch)" }; xkb_symbols "fr-dvorak" { name[Group1] = "French (Canada, Dvorak)"; key { [ numbersign, bar, backslash ] }; key { [ 1, exclam, plusminus ] }; key { [ 2, quotedbl, at ] }; key { [ 3, slash, sterling ] }; key { [ 4, dollar, cent ] }; key { [ 5, percent, currency ] }; key { [ 6, question, notsign ] }; key { [ 7, ampersand, brokenbar ] }; key { [ 8, asterisk, twosuperior ] }; key { [ 9, parenleft, threesuperior ] }; key { [ 0, parenright, onequarter ] }; key { [dead_circumflex, dead_circumflex, bracketleft ] }; key { [ dead_cedilla, dead_diaeresis, bracketright ] }; key { [dead_grave, dead_grave, braceleft ] }; key { [ comma, apostrophe, macron ] }; key { [ period, period, hyphen ] }; key { [ p, P, paragraph ] }; key { [ y, Y ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ c, C ] }; key { [ r, R ] }; key { [ l, L ] }; key { [ eacute, Eacute, dead_acute ] }; key { [ equal, plus, threequarters ] }; key { [ a, A ] }; key { [ o, O, section ] }; key { [ e, E ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ d, D ] }; key { [ h, H ] }; key { [ t, T ] }; key { [ n, N ] }; key { [ s, S ] }; key { [ minus, underscore, onehalf ] }; key { [ less, greater, braceright ] }; key { [guillemotleft, guillemotright, degree] }; key { [ semicolon, colon, asciitilde ] }; key { [ q, Q ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ x, X ] }; key { [ b, B ] }; key { [ m, M, mu ] }; key { [ w, W ] }; key { [ v, V ] }; key { [ z, Z ] }; key { [ space, space, nobreakspace ] }; include "level3(ralt_switch)" }; partial xkb_symbols "fr-legacy" { include "ca(fr)" name[Group1] = "French (Canada, legacy)"; key { [ degree, degree, notsign ] }; key { [ 1, exclam, onesuperior ] }; key { [ 3, numbersign, threesuperior ] }; key { [ 4, dollar, onequarter ] }; key { [ 5, percent, onehalf ] }; key { [ 6, question, threequarters ] }; key { [ 7, ampersand, braceleft ] }; key { [ 8, asterisk, bracketleft ] }; key { [ 9, parenleft, bracketright, plusminus ] }; key { [ 0, parenright, braceright ] }; key { [ minus, underscore, bar, questiondown] }; key { [ equal, plus, dead_cedilla ] }; key { [ r, R, paragraph, registered ] }; key { [ y, Y, yen ] }; key { [ o, O, oslash, Ooblique ] }; key { [ p, P, thorn, THORN ] }; key { [dead_circumflex, dead_circumflex, degree ] }; key { [ ccedilla, Ccedilla, dead_tilde, dead_diaeresis ] }; key { [ a, A, ae, AE ] }; key { [ s, S, ssharp, section ] }; key { [ d, D, eth, ETH ] }; key { [ f, F, ordfeminine ] }; key { [ semicolon, colon, dead_acute, dead_acute ] }; key { [ egrave, Egrave ] }; key { [ agrave, Agrave, dead_grave ] }; key { [ ugrave, Ugrave, backslash, bar ] }; key { [ z, Z, guillemotleft ] }; key { [ x, X, guillemotright ] }; key { [ c, C, cent, copyright ] }; key { [ m, M, mu, masculine ] }; key { [ comma, apostrophe, less ] }; key { [ period, period, greater ] }; key { [ eacute, Eacute, slash ] }; }; partial xkb_symbols "multi" { include "ca(fr)" name[Group1] = "Canadian (intl., 1st part)"; key { [ slash, backslash, bar ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ 5, percent ] }; key { [ 6, question ] }; key { [ 7, ampersand, braceleft ] }; key { [ 8, asterisk, braceright ] }; key { [ 9, parenleft, bracketleft ] }; key { [ 0, parenright, bracketright ] }; key { [ minus, underscore ] }; key { [ equal, plus, notsign ] }; key { [ o, O ] }; key { [ p, P ] }; key { [dead_circumflex, dead_diaeresis, dead_grave ] }; key { [ ccedilla, Ccedilla, asciitilde ] }; key { [ semicolon, colon, degree ] }; key { [ egrave, Egrave ] }; key { [ agrave, Agrave ] }; key { [ ugrave, Ugrave ] }; key { [ z, Z, guillemotleft ] }; key { [ x, X, guillemotright ] }; key { [ comma, apostrophe, less ] }; key { [ period, quotedbl, greater ] }; key { [ eacute, Eacute ] }; }; partial xkb_symbols "multi-2gr" { name[Group1] = "Canadian (intl., 2nd part)"; key { [ NoSymbol, hyphen ] }; key { [ onesuperior, exclamdown ] }; key { [ twosuperior, NoSymbol ] }; key { [ threesuperior, sterling ] }; key { [ onequarter, currency ] }; key { [ onehalf,threeeighths ] }; key { [ threequarters, fiveeighths ] }; key { [ NoSymbol,seveneighths ] }; key { [ NoSymbol, trademark ] }; key { [ NoSymbol, plusminus ] }; key { [ NoSymbol, questiondown] }; key { [ dead_cedilla, dead_ogonek ] }; key { [ NoSymbol, Greek_OMEGA ] }; key { [ lstroke, Lstroke ] }; key { [ oe, OE ] }; key { [ paragraph, registered ] }; key { [ tslash, Tslash ] }; key { [ leftarrow, yen ] }; key { [ downarrow, uparrow ] }; key { [ rightarrow, idotless ] }; key { [ oslash, Ooblique ] }; key { [ thorn, THORN ] }; key { [ NoSymbol, dead_abovering ] }; key { [ dead_tilde, dead_macron ] }; key { [ ae, AE ] }; key { [ ssharp, section ] }; key { [ eth, ETH ] }; key { [ NoSymbol, ordfeminine ] }; key { [ eng, ENG ] }; key { [ hstroke, Hstroke ] }; key { [ U0133, U0132 ] }; key { [ kra, NoSymbol ] }; key { [ U0140, U013F ] }; key { [ dead_acute, dead_doubleacute ] }; key { [ NoSymbol, dead_caron ] }; key { [ NoSymbol, dead_breve ] }; key { [ NoSymbol, brokenbar ] }; key { [ cent, copyright ] }; key { [ leftdoublequotemark, leftsinglequotemark ] }; key { [ rightdoublequotemark, rightsinglequotemark ] }; key { [ U0149, U266A ] }; key { [ mu, masculine ] }; key { [ Greek_horizbar, multiply ] }; key { [ periodcentered, division ] }; key { [ NoSymbol, dead_abovedot ] }; }; // based on // Inuktitut keyboard for X11 // written by Pablo Saratxaga alphanumeric_keys xkb_symbols "ike" { name[Group1]= "Inuktitut"; key { [ 0x01001595, 1 ] }; key { [ 0x01001449, 2 ] }; key { [ 0x01001550, 3 ] }; key { [ 0x01001483, 4 ] }; key { [ 0x01001466, 5 ] }; key { [ 0x01001585, 6 ] }; key { [ 0x010014bb, 7 ] }; key { [ 0x010014d0, 8 ] }; key { [ 0x010014ea, 9 ] }; key { [ 0x0100153e, 0 ] }; key { [ minus, underscore ] }; key { [ 0x0100155d, equal ] }; key { [ 0x0100158f, 0x0100148b ] }; key { [ 0x01001403, 0x01001431 ] }; key { [ 0x0100157f, 0x01001546 ] }; key { [ 0x0100146d, 0x01001596 ] }; key { [ 0x0100144e, 0x01001671 ] }; key { [ 0x010014ef, 0x01001673 ] }; key { [ 0x010014a5, 0x01001675 ] }; key { [ 0x010014c2, 0x010015a4 ] }; key { [ 0x010014d5, 0x010015a0 ] }; key { [ 0x01001528, 0x010015a6 ] }; key { [ 0x010014a1, 0x01001505 ] }; key { [ dead_abovedot, 0x0100141e] }; key { [ 0x01001591, 0x0100148d ] }; key { [ 0x01001405, 0x01001433 ] }; key { [ 0x01001581, 0x01001548 ] }; key { [ 0x0100146f, 0x01001555 ] }; key { [ 0x01001450, parenleft ] }; key { [ 0x010014f1, parenright ] }; key { [ 0x010014a7, 0x0100152a ] }; key { [ 0x010014c4, 0x01001557 ] }; key { [ 0x010014d7, 0x010015a2 ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ 0x01001593, 0x01001490 ] }; key { [ 0x0100140a, 0x01001438 ] }; key { [ 0x01001583, 0x0100154b ] }; key { [ 0x01001472, question ] }; key { [ 0x01001455, 0x0100157c ] }; key { [ 0x010014f4, 0x010014c7 ] }; key { [ 0x010014aa, 0x010014da ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ 0x0100152d, 0x01001559 ] }; key { [ 0x0100157b, 0x01001575 ] }; key { [ 0x01001579, 0x01001577 ] }; key { [ backslash, bar ] }; }; partial xkb_symbols "multix" { name[Group1] = "Canadian (intl.)"; key.type[group1]="EIGHT_LEVEL_SEMIALPHABETIC"; key { [ slash, backslash, bar, NoSymbol, NoSymbol, hyphen ] }; key { [ 1, exclam, plusminus, NoSymbol, onesuperior, exclamdown ] }; key { [ 2, at, at, NoSymbol, twosuperior, NoSymbol ] }; key { [ 3, numbersign, sterling, NoSymbol, threesuperior, sterling ] }; key { [ 4, dollar, cent, NoSymbol, onequarter, currency ] }; key { [ 5, percent, currency, NoSymbol, onehalf, threeeighths ] }; key { [ 6, question, notsign, NoSymbol, threequarters, fiveeighths ] }; key { [ 7, ampersand, braceleft, NoSymbol, NoSymbol, seveneighths ] }; key { [ 8, asterisk, braceright, NoSymbol, NoSymbol, trademark ] }; key { [ 9, parenleft, bracketleft, NoSymbol, NoSymbol, plusminus ] }; key { [ 0, parenright, bracketright, NoSymbol ] }; key { [ minus, underscore, onehalf, NoSymbol, NoSymbol, questiondown] }; key { [ equal, plus, notsign, NoSymbol, dead_cedilla, dead_ogonek ] }; key.type[group1]="EIGHT_LEVEL_SEMIALPHABETIC"; key { [ q, Q, NoSymbol, NoSymbol, NoSymbol, Greek_OMEGA ] }; key { [ w, W, NoSymbol, NoSymbol, lstroke, Lstroke ] }; key { [ e, E, NoSymbol, NoSymbol, oe, OE ] }; key { [ r, R, NoSymbol, NoSymbol, paragraph, registered ] }; key { [ t, T, NoSymbol, NoSymbol, tslash, Tslash ] }; key { [ y, Y, NoSymbol, NoSymbol, leftarrow, yen ] }; key { [ u, U, NoSymbol, NoSymbol, downarrow, uparrow ] }; key { [ i, I, NoSymbol, NoSymbol, rightarrow, idotless ] }; key { [ o, O, section, NoSymbol, oslash, Ooblique ] }; key { [ p, P, paragraph, NoSymbol, thorn, THORN ] }; key.type[group1]="EIGHT_LEVEL"; key { [dead_circumflex, dead_diaeresis, dead_grave, NoSymbol, NoSymbol, dead_abovering ] }; key.type[group1]="EIGHT_LEVEL_SEMIALPHABETIC"; key { [ ccedilla, Ccedilla, asciitilde, NoSymbol, dead_tilde, dead_macron ] }; key { [ a, A, NoSymbol, NoSymbol, ae, AE ] }; key { [ s, S, NoSymbol, NoSymbol, ssharp, section ] }; key { [ d, D, NoSymbol, NoSymbol, eth, ETH ] }; key { [ f, F, NoSymbol, NoSymbol, NoSymbol, ordfeminine ] }; key { [ g, G, NoSymbol, NoSymbol, eng, ENG ] }; key { [ h, H, NoSymbol, NoSymbol, hstroke, Hstroke ] }; key { [ j, J, NoSymbol, NoSymbol, U0133, U0132 ] }; key { [ k, K, NoSymbol, NoSymbol, kra, NoSymbol ] }; key { [ l, L, NoSymbol, NoSymbol, U0140, U013F ] }; key.type[group1]="EIGHT_LEVEL"; key { [ semicolon, colon, degree, NoSymbol, dead_acute, dead_doubleacute ] }; key.type[group1]="EIGHT_LEVEL_SEMIALPHABETIC"; key { [ egrave, Egrave, braceleft, NoSymbol, NoSymbol, dead_caron ] }; key { [ agrave, Agrave, braceright, NoSymbol, NoSymbol, dead_breve ] }; key { [ ugrave, Ugrave, degree, NoSymbol, NoSymbol, brokenbar ] }; key.type[group1]="FOUR_LEVEL_SEMIALPHABETIC"; key { [ z, Z, guillemotleft, NoSymbol ] }; key { [ x, X, guillemotright, NoSymbol ] }; key.type[group1]="EIGHT_LEVEL_SEMIALPHABETIC"; key { [ c, C, NoSymbol, NoSymbol, cent, copyright ] }; key { [ v, V, NoSymbol, NoSymbol, leftdoublequotemark, leftsinglequotemark ] }; key { [ b, B, NoSymbol, NoSymbol, rightdoublequotemark, rightsinglequotemark ] }; key { [ n, N, NoSymbol, NoSymbol, U0149, U266A ] }; key { [ m, M, mu, NoSymbol, mu, masculine ] }; key { [ comma, apostrophe, less, NoSymbol, Greek_horizbar, multiply ] }; key { [ period, quotedbl, greater, NoSymbol, periodcentered, division ] }; key { [ eacute, Eacute, dead_acute, NoSymbol, NoSymbol, dead_abovedot ] }; include "nbsp(level3s)" modifier_map Control{ Control_L }; include "level3(ralt_switch)" include "level5(rctrl_switch)" }; // OLPC Section xkb_symbols "olpc" { include "ca(fr)" key { [ 2, quotedbl, ograve, Ograve ] }; key { [ 3, slash, at, VoidSymbol ] }; key { [ e, E, EuroSign, VoidSymbol] }; key { [ period, period, 0x1002010 ] }; key { [ guillemotleft, guillemotright, degree, VoidSymbol ] }; }; partial alphanumeric_keys xkb_symbols "eng" { include "us(basic)" name[Group1] = "English (Canada)"; key { [ backslash, bar, VoidSymbol, VoidSymbol ] }; }; // EXTRAS: partial alphanumeric_keys xkb_symbols "kut" { // Ejective U0313 and acute accents are taken from shs layout. include "ca(shs)" name[Group1]= "Kutenai"; // Alveolar Click key { [ t, T,U01C2 ,U01C2 ] }; //Cent sign key { [ c, C,U00A2,U00A2 ] }; //Mid dot key { [ period, greater,U00B7 ] }; //Glottal stop key { [ slash, question, U0294 ] }; //COMBINING COMMA ABOVE RIGHT key { [ apostrophe, quotedbl, U0315,U0315 ] }; //MODIFIER LETTER RIGHT HALF RING key { [ semicolon, colon,U02BE,U02BE ] }; }; // Secwepemctsin keyboard for X11 // written by Neskie Manuel partial alphanumeric_keys xkb_symbols "shs" { include "us" name[Group1]= "Secwepemctsin"; // Using a "dead key" to get a COMBINING COMMA ABOVE // for ejectives on q, l, t, s, m, g, k, p, w, y, r. // The Compose key is used for the other acutes and grave. key { [ comma, less, U0313 ] }; key { [ a, A, aacute, Aacute ] }; key { [ e, E, eacute, Eacute ] }; key { [ u, U, uacute, Uacute ] }; key { [ i, I, iacute, Iacute ] }; key { [ o, O, oacute, Oacute ] }; include "level3(ralt_switch)" include "compose(rctrl)" }; partial alphanumeric_keys xkb_symbols "sun_type6" { include "sun_vndr/ca(sun_type6)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/capslock000066400000000000000000000037201510033435100237670ustar00rootroot00000000000000default hidden partial modifier_keys xkb_symbols "capslock" { replace key { [ Caps_Lock ] }; modifier_map Lock { Caps_Lock }; }; hidden partial modifier_keys xkb_symbols "shiftlock" { replace key { [ Shift_Lock ] }; modifier_map Shift { Shift_Lock }; }; hidden partial modifier_keys xkb_symbols "grouplock" { replace key { [ ISO_Next_Group, Caps_Lock ] }; }; hidden partial modifier_keys xkb_symbols "groupshift" { key { type[Group1] = "PC_ALT_LEVEL2", [ Mode_switch, Caps_Lock ] }; }; hidden partial modifier_keys xkb_symbols "swapescape" { key { [ Escape ] }; key { [ Caps_Lock ] }; }; hidden partial modifier_keys xkb_symbols "escape" { key { [ Escape ] }; }; hidden partial modifier_keys xkb_symbols "escape_shifted_capslock" { key { type[Group1] = "TWO_LEVEL", symbols[Group1] = [ Escape, Caps_Lock ], actions[Group1] = [ NoAction(), LockMods(modifiers = Lock) ] }; }; hidden partial modifier_keys xkb_symbols "backspace" { key { [ BackSpace ] }; }; hidden partial modifier_keys xkb_symbols "super" { key { [ Super_L ] }; modifier_map Mod4 { }; }; hidden partial modifier_keys xkb_symbols "hyper" { key { [ Hyper_L ] }; modifier_map Mod4 { }; }; hidden partial modifier_keys xkb_symbols "menu" { key { [ Menu ] }; }; hidden partial modifier_keys xkb_symbols "numlock" { key { [ Num_Lock ] }; }; // This changes the key to become a Control modifier, // but it will still produce the Caps_Lock keysym. hidden partial modifier_keys xkb_symbols "ctrl_modifier" { replace key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ Caps_Lock ], actions[Group1] = [ SetMods(modifiers=Control) ] }; modifier_map Control { }; }; hidden partial modifier_keys xkb_symbols "none" { key { [ VoidSymbol ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/ch000066400000000000000000000201301510033435100225540ustar00rootroot00000000000000default partial alphanumeric_keys xkb_symbols "basic" { include "latin" name[Group1]= "German (Switzerland)"; key { [ section, degree ] }; key { [ 1, plus, bar, exclamdown ] }; key { [ 2, quotedbl, at, oneeighth ] }; key { [ 3, asterisk, numbersign ] }; key { [ 4, ccedilla ] }; key { [ 5, percent ] }; key { [ 6, ampersand, notsign ] }; key { [ 7, slash, bar ] }; key { [ 8, parenleft, cent ] }; key { [ 9, parenright ] }; key { [ 0, equal ] }; key { [ apostrophe, question, dead_acute ] }; key { [ dead_circumflex, dead_grave, dead_tilde ] }; key { [ e, E, EuroSign ] }; key { [ z, Z ] }; key { [ o, O, oe, OE ] }; key { [ udiaeresis, egrave, bracketleft ] }; key { [ dead_diaeresis, exclam, bracketright ] }; key { [ odiaeresis, eacute ] }; key { [ adiaeresis, agrave, braceleft ] }; key { [ dollar, sterling, braceright ] }; key { [ less, greater, backslash, brokenbar ] }; key { [ y, Y ] }; key { [ comma, semicolon ] }; key { [ period, colon ] }; key { [ minus, underscore ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "legacy" { include "ch(basic)" name[Group1]= "German (Switzerland, legacy)"; key { [ 7, slash, brokenbar ] }; }; partial alphanumeric_keys xkb_symbols "de" { include "ch(basic)" }; partial alphanumeric_keys xkb_symbols "de_Sundeadkeys" { // modify the basic Swiss German layout to use Sun dead keys include "ch(basic)" key { [ apostrophe, question, dead_acute ] }; key { [ dead_circumflex, dead_grave, dead_tilde ] }; key { [ dead_diaeresis, exclam, bracketright ] }; }; partial alphanumeric_keys xkb_symbols "de_sundeadkeys" { include "ch(de_Sundeadkeys)" name[Group1]= "German (Switzerland, Sun dead keys)"; }; partial alphanumeric_keys xkb_symbols "de_nodeadkeys" { // modify the basic Swiss German layout not to have any dead keys include "ch(basic)" name[Group1]= "German (Switzerland, no dead keys)"; key { [ apostrophe, question, acute ] }; key { [ asciicircum, grave, asciitilde ] }; key { [ diaeresis, exclam, bracketright ] }; }; partial alphanumeric_keys xkb_symbols "fr" { include "ch(basic)" name[Group1]= "French (Switzerland)"; override key { [ egrave, udiaeresis, bracketleft ] }; override key { [ eacute, odiaeresis ] }; override key { [ agrave, adiaeresis, braceleft ] }; }; partial alphanumeric_keys xkb_symbols "fr_Sundeadkeys" { // modify the basic Swiss French layout to use Sun dead keys include "ch(fr)" key { [ apostrophe, question, dead_acute ] }; key { [ dead_circumflex, dead_grave, dead_tilde ] }; key { [ dead_diaeresis, exclam, bracketright ] }; }; partial alphanumeric_keys xkb_symbols "fr_sundeadkeys" { include "ch(fr_Sundeadkeys)" name[Group1]= "French (Switzerland, Sun dead keys)"; }; partial alphanumeric_keys xkb_symbols "fr_nodeadkeys" { // modify the basic Swiss French layout not to have any dead keys include "ch(fr)" name[Group1]= "French (Switzerland, no dead keys)"; key { [ apostrophe, question, acute ] }; key { [ asciicircum, grave, asciitilde ] }; key { [ diaeresis, exclam, bracketright ] }; }; // Copied from macintosh_vndr/ch // 03.01.2003 // Andreas Tobler // modified for Swiss German Apple Extended Keyboard II partial alphanumeric_keys xkb_symbols "de_mac" { name[Group1]= "German (Switzerland, Macintosh)"; key { [ 1, plus, plusminus, infinity ] }; key { [ 2, quotedbl, leftdoublequotemark, rightdoublequotemark ] }; key { [ 3, asterisk, numbersign, leftcaret ] }; // not displayed here key { [ 4, ccedilla, Ccedilla, slash ] }; key { [ 5, percent, bracketleft ] }; key { [ 6, ampersand, bracketright ] }; key { [ 7, slash, bar, backslash ] }; key { [ 8, parenleft, braceleft, Ograve ] }; key { [ 9, parenright, braceright, Ocircumflex ] }; key { [ 0, equal, notequal, Uacute ] }; key { [ apostrophe, question, questiondown, NoSymbol ] }; key { [ dead_circumflex,dead_grave, dead_acute, asciicircum ] }; key { [ q, Q, oe, OE ] }; key { [ w, W, Greek_SIGMA, Aacute ] }; key { [ e, E, EuroSign, Ediaeresis ] }; key { [ r, R, registered, Egrave ] }; key { [ t, T, dagger, Icircumflex ] }; key { [ z, Z, Greek_OMEGA, Iacute ] }; key { [ u, U, degree, Ugrave ] }; key { [ i, I, exclamdown, idotless ] }; key { [ o, O, oslash, Ooblique ] }; key { [ p, P, Greek_pi, Greek_PI ] }; key { [ udiaeresis, egrave, section, ydiaeresis ] }; key { [ dead_diaeresis, exclam, grave, apostrophe ] }; key { [ a, A, aring, Aring ] }; key { [ s, S, ssharp, U1E9E ] }; // ligature fl key { [ d, D, Greek_sigma, NoSymbol ] }; // partialderivative is not available here att key { [ f, F, function, doubledagger ] }; key { [ g, G, at, comma ] }; key { [ h, H, ordfeminine, periodcentered ] }; key { [ j, J, masculine, eth ] }; key { [ k, K, Greek_DELTA, macron ] }; key { [ l, L, notsign, caret ] }; key { [ odiaeresis, eacute, cent, breve ] }; key { [ adiaeresis, agrave, ae, AE ] }; key { [ y, Y, yen, Ydiaeresis ] }; key { [ x, X, similarequal, trademark ] }; key { [ c, C, copyright, NoSymbol ] }; key { [ v, V, radical, diamond ] }; key { [ b, B, integral, NoSymbol ] }; key { [ n, N, dead_tilde, enopencircbullet ] }; // to be fixed att key { [ m, M, mu, dead_abovering ] }; // not sure att key { [ comma, semicolon, guillemotleft, guillemotright ] }; key { [ period, colon, ellipsis, division ] }; key { [ minus, underscore, hyphen, emdash ] }; key { [ section, degree, NoSymbol, NoSymbol ] }; // ligature fi // per mille key { [ space, nobreakspace, nobreakspace ] }; key { [ less, greater, lessthanequal, greaterthanequal ] }; key { [ dollar, sterling, paragraph, enfilledcircbullet ] }; include "kpdl(comma)" include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "fr_mac" { include "ch(de_mac)" name[Group1]= "French (Switzerland, Macintosh)"; override key { [ egrave, udiaeresis, bracketleft ] }; override key { [ eacute, odiaeresis ] }; override key { [ agrave, adiaeresis, braceleft ] }; }; // EXTRAS: partial alphanumeric_keys xkb_symbols "sun_type6_de" { include "sun_vndr/ch(sun_type6_de)" }; partial alphanumeric_keys xkb_symbols "sun_type6_fr" { include "sun_vndr/ch(sun_type6_fr)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/compose000066400000000000000000000043771510033435100236460ustar00rootroot00000000000000partial modifier_keys xkb_symbols "ralt" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "lwin" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "lwin-altgr" { key { type[Group1]="FOUR_LEVEL", [ Super_L, Super_L, Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "rwin" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "rwin-altgr" { key { type[Group1]="FOUR_LEVEL", [ Super_R, Super_R, Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "menu" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "menu-altgr" { key { type[Group1]="FOUR_LEVEL", [ Menu, Menu, Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "rctrl" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "rctrl-altgr" { key { type[Group1]="FOUR_LEVEL", [ Control_R, Control_R, Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "lctrl" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "lctrl-altgr" { key { type[Group1]="FOUR_LEVEL", [ Control_L, Control_L, Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "caps" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "caps-altgr" { key { type[Group1]="FOUR_LEVEL", [ Caps_Lock, Caps_Lock, Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "102" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "102-altgr" { key { type[Group1]="FOUR_LEVEL", [ less, greater, Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "paus" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "prsc" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; partial modifier_keys xkb_symbols "sclk" { key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/ctrl000066400000000000000000000075741510033435100231470ustar00rootroot00000000000000// Eliminate CapsLock, making it another Ctrl. partial modifier_keys xkb_symbols "nocaps" { replace key { [ Control_L, Control_L ] }; modifier_map Control { , }; }; // Make the left Ctrl key a left Meta. xkb_symbols "lctrl_meta" { replace key { [ Meta_L ] }; modifier_map Mod4 { }; }; // Swap the functions of the CapsLock key and the left Ctrl key. partial modifier_keys xkb_symbols "swapcaps" { replace key { [ Control_L ] }; replace key { [ Caps_Lock ] }; modifier_map Control { }; modifier_map Lock { }; }; // Swap the functions of the CapsLock key and the left Ctrl key, // but make the Ctrl key a 'Hyper' modifier partial modifier_keys xkb_symbols "swapcaps_hyper" { replace key { [ Control_L ] }; replace key { [ Hyper_L ] }; modifier_map Control { }; modifier_map Mod3 { }; }; // Set CapsLock to left Ctrl and left Ctrl to switch layout. partial modifier_keys xkb_symbols "swapcaps_and_switch_layout" { replace key { [ Control_L ] }; replace key { [ ISO_Next_Group ] }; modifier_map Control { }; modifier_map Lock { }; }; // Move Ctrl to the leftmost key on the middle row and CapsLock to the // leftmost key on the bottom row. Only works if the geometry or keycodes // file has defined appropriate aliases for the keys in question. partial modifier_keys xkb_symbols "ac_ctrl" { replace key { [ Control_L ] }; replace key { [ Caps_Lock ] }; modifier_map Control { }; modifier_map Lock { }; }; // Move Ctrl to the leftmost key on the bottom row and CapsLock to the // leftmost key on the middle row. Only works if the geometry or keycodes // file has defined appropriate aliases for the keys in question. partial modifier_keys xkb_symbols "aa_ctrl" { replace key { [ Control_L ] }; replace key { [ Caps_Lock ] }; modifier_map Control { }; modifier_map Lock { }; }; // Right Ctrl functions as another right Alt. partial modifier_keys xkb_symbols "rctrl_ralt" { key { symbols[Group1]= [ Alt_R ] }; modifier_map Mod1{ }; }; // Menu key functions as another right Ctrl. partial modifier_keys xkb_symbols "menu_rctrl" { replace key { [ Control_R, Control_R ] }; modifier_map Control { Control_L, }; }; // Right Alt key functions as another right Ctrl. partial modifier_keys xkb_symbols "ralt_rctrl" { replace key { type[Group1] = "TWO_LEVEL", symbols[Group1] = [ Control_R, Control_R ] }; modifier_map Control { }; }; // Swap the functions of the left Alt key and the left Ctrl key. partial modifier_keys xkb_symbols "swap_lalt_lctl" { replace key { [ Control_L, Control_L ] }; replace key { [ Alt_L, Meta_L ] }; modifier_map Mod1 { }; modifier_map Control { }; }; // Swap the functions of the left Win key and the left Ctrl key. partial modifier_keys xkb_symbols "swap_lwin_lctl" { replace key { [ Control_L ] }; replace key { [ Super_L ] }; modifier_map Mod4 { }; modifier_map Control { }; }; // Swap the functions of the right Win key and the right Ctrl key. partial modifier_keys xkb_symbols "swap_rwin_rctl" { replace key { [ Control_R ] }; replace key { [ Super_R ] }; modifier_map Mod4 { }; modifier_map Control { }; }; // Map Ctrl to the left Alt key, Alt to the left Win key, // and Super to the left Ctrl key. partial modifier_keys xkb_symbols "swap_lalt_lctl_lwin" { replace key { [ Control_L, Control_L ] }; replace key { [ Alt_L, Meta_L ] }; replace key { [ Super_L ] }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Control { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/cz000066400000000000000000000571621510033435100226150ustar00rootroot00000000000000default partial alphanumeric_keys xkb_symbols "basic" { // This layout conforms to a new Czech compromise standard // designed to satisfy most Unix, Windows and Mac users. // 2001 by Kamil Toman include "latin" name[Group1]= "Czech"; key { [ semicolon, dead_abovering, grave, asciitilde ] }; key { [ plus, 1, exclam, dead_tilde ] }; key { [ ecaron, 2, at, dead_caron ] }; key { [ scaron, 3, numbersign, dead_circumflex ] }; key { [ ccaron, 4, dollar, dead_breve ] }; key { [ rcaron, 5, percent, dead_abovering]}; key { [ zcaron, 6, asciicircum, dead_ogonek ] }; key { [ yacute, 7, ampersand, dead_grave ] }; key { [ aacute, 8, asterisk, dead_abovedot] }; key { [ iacute, 9, braceleft, dead_acute ] }; key { [ eacute, 0, braceright, dead_doubleacute ] }; key { [ equal, percent, NoSymbol, dead_diaeresis]}; key { [dead_acute, dead_caron, dead_macron, dead_cedilla ] }; key { [ q, Q, backslash, NoSymbol ] }; key { [ w, W, bar, Nosymbol ] }; key { [ e, E, EuroSign, NoSymbol ] }; key { [ r, R, NoSymbol, NoSymbol ] }; key { [ t, T, NoSymbol, NoSymbol ] }; key { [ z, Z, NoSymbol, NoSymbol ] }; key { [ u, U, NoSymbol, NoSymbol ] }; key { [ i, I, NoSymbol, NoSymbol ] }; key { [ o, O, NoSymbol, NoSymbol ] }; key { [ p, P, NoSymbol, NoSymbol ] }; key { [ uacute, slash, bracketleft, division ] }; key { [parenright, parenleft, bracketright, multiply ] }; key { [ a, A, asciitilde, NoSymbol ] }; key { [ s, S, dstroke, NoSymbol ] }; key { [ d, D, Dstroke, NoSymbol ] }; key { [ f, F, bracketleft, NoSymbol ] }; key { [ g, G, bracketright, NoSymbol ] }; key { [ h, H, grave, NoSymbol ] }; key { [ j, J, apostrophe, NoSymbol ] }; key { [ k, K, lstroke, NoSymbol ] }; key { [ l, L, Lstroke, NoSymbol ] }; key { [ uring, quotedbl, dollar, NoSymbol ] }; key { [ section, exclam, apostrophe, ssharp ] }; key { [ EuroSign, dead_diaeresis, NoSymbol, NoSymbol ] }; key { [dead_diaeresis, apostrophe, backslash, bar ] }; key { [ backslash, bar, slash, NoSymbol ] }; key { [ y, Y, degree, NoSymbol ] }; key { [ x, X, numbersign, Nosymbol ] }; key { [ c, C, ampersand, NoSymbol ] }; key { [ v, V, at, NoSymbol ] }; key { [ b, B, braceleft, NoSymbol ] }; key { [ n, N, braceright, NoSymbol ] }; key { [ m, M, asciicircum, NoSymbol ] }; key { [ comma, question, less, NoSymbol ] }; key { [ period, colon, greater, NoSymbol ] }; key { [ minus, underscore, asterisk, NoSymbol ] }; key { [ space, space, space, space ] }; include "level3(ralt_switch)" }; xkb_symbols "bksl" { // Use instead of (useful for keyboards without key). include "cz(basic)" name[Group1]= "Czech (with <\|> key)"; key { [ backslash, bar, slash, NoSymbol ] }; }; partial alphanumeric_keys xkb_symbols "qwerty" { // This layout represents the actual Czech keyboards; // it complies with the symbols printed on the keys. // 2011 by Lukáš Mojžíš include "cz(basic)" name[Group1]= "Czech (QWERTY)"; key { [ z, Z, degree, NoSymbol ] }; key { [ uring, quotedbl, semicolon, colon ] }; key { [ section, exclam, apostrophe, ssharp ] }; key { [ y, Y, NoSymbol, NoSymbol ] }; key { [ uacute, slash, bracketleft, braceleft ] }; key { [parenright, parenleft, bracketright, braceright ] }; key { [ iacute, 9, parenleft, dead_acute ] }; key { [ eacute, 0, parenright, dead_doubleacute ] }; }; xkb_symbols "qwerty_bksl" { // Use instead of (useful for keyboards without key). include "cz(qwerty)" name[Group1]= "Czech (QWERTY, extended backslash)"; key { [ backslash, bar, slash, NoSymbol ] }; }; partial alphanumeric_keys xkb_symbols "qwerty-mac" { // This layout corresponds to the Apple's Czech - QWERTY. // 2018 by Jakub Jirutka include "latin" name[Group1]= "Czech (QWERTY, Macintosh)"; key { [ less, greater, lessthanequal, greaterthanequal]}; key { [ plus, 1, grave, notsign ] }; key { [ ecaron, 2, at, enfilledcircbullet]}; key { [ scaron, 3, numbersign, notequal ] }; key { [ ccaron, 4, dollar, sterling ] }; key { [ rcaron, 5, asciitilde, U25CA ] }; key { [ zcaron, 6, asciicircum, dagger ] }; key { [ yacute, 7, ampersand, paragraph ] }; key { [ aacute, 8, asterisk, division ] }; key { [ iacute, 9, braceleft, guillemotleft] }; key { [ eacute, 0, braceright, guillemotright]}; key { [ equal, percent, dead_abovering, dead_cedilla]}; key { [dead_acute, dead_caron, dead_circumflex, dead_macron]}; key { [ q, Q, NoSymbol, NoSymbol ] }; key { [ w, W, eabovedot, Eabovedot ] }; key { [ e, E, eogonek, Eogonek ] }; key { [ r, R, EuroSign, registered ] }; key { [ t, T, NoSymbol, trademark ] }; key { [ y, Y, NoSymbol, NoSymbol ] }; key { [ u, U, NoSymbol, NoSymbol ] }; key { [ i, I, NoSymbol, NoSymbol ] }; key { [ o, O, NoSymbol, NoSymbol ] }; key { [ p, P, NoSymbol, NoSymbol ] }; key { [ uacute, slash, bracketleft, less ] }; key { [parenright, parenleft, bracketright, greater ] }; key { [ a, A, aogonek, Aogonekl ] }; key { [ s, S, ssharp, U2211 ] }; key { [ d, D, partialderivate, U2206 ] }; key { [ f, F, NoSymbol, NoSymbol ] }; key { [ g, G, NoSymbol, NoSymbol ] }; key { [ h, H, leftsinglequotemark, leftdoublequotemark]}; key { [ j, J, rightsinglequotemark, rightdoublequotemark]}; key { [ k, K, NoSymbol, NoSymbol ] }; key { [ l, L, lstroke, Lstroke ] }; key { [ uring, quotedbl, semicolon, ellipsis ] }; key { [ section, exclam, apostrophe, dead_tilde ] }; key { [dead_diaeresis, grave, dead_diaeresis, dead_doubleacute]}; key { [ backslash, bar, NoSymbol, NoSymbol ] }; key { [ z, Z, zabovedot, Zabovedot ] }; key { [ x, X, NoSymbol, NoSymbol ] }; key { [ c, C, NoSymbol, copyright ] }; key { [ v, V, NoSymbol, squareroot ] }; key { [ b, B, NoSymbol, NoSymbol ] }; key { [ n, N, singlelowquotemark, doublelowquotemark]}; key { [ m, M, NoSymbol, NoSymbol ] }; key { [ comma, question, less, lessthanequal] }; key { [ period, colon, greater, greaterthanequal]}; key { [ minus, underscore, endash, emdash ] }; key { [ space, space, nobreakspace, nobreakspace ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys alternate_group xkb_symbols "ucw" { // This layout is usually used as the second group, // it contains accented characters only, no 'latin' set. // 2008 by Milan Vancura name[Group1]= "Czech (UCW, only accented letters)"; key { [zcaron, Zcaron ] }; key { [ssharp, U1E9E ] }; key { [ccaron, Ccaron ] }; key { [ccedilla, Ccedilla ] }; key { [ntilde, Ntilde ] }; key { [ncaron, Ncaron ] }; key { [lacute, Lacute ] }; key { [aacute, Aacute ] }; key { [scaron, Scaron ] }; key { [dcaron, Dcaron ] }; key { [ediaeresis, Ediaeresis ] }; key { [racute, Racute ] }; key { [uacute, Uacute ] }; key { [udiaeresis, Udiaeresis ] }; key { [ocircumflex, Ocircumflex ] }; key { [lcaron, Lcaron ] }; key { [adiaeresis, Adiaeresis ] }; key { [ecaron, Ecaron ] }; key { [eacute, Eacute ] }; key { [rcaron, Rcaron ] }; key { [tcaron, Tcaron ] }; key { [yacute, Yacute ] }; key { [uring, Uring ] }; key { [iacute, Iacute ] }; key { [oacute, Oacute ] }; key { [odiaeresis, Odiaeresis ] }; }; partial alphanumeric_keys xkb_symbols "dvorak-ucw" { // US Dvorak layout extended with UCW, // AltGr produces accented characters. include "us(dvorak)" name[Group1]= "Czech (US, Dvorak, UCW support)"; key { [ j, J, eacute, Eacute ] }; key { [ k, K, uacute, Uacute ] }; key { [ z, Z, zcaron, Zcaron ] }; key { [ a, A, aacute, Aacute ] }; key { [ o, O, oacute, Oacute ] }; key { [ e, E, ecaron, Ecaron ] }; key { [ u, U, uring, Uring ] }; key { [ i, I, iacute, Iacute ] }; key { [ d, D, dcaron, Dcaron ] }; key { [ t, T, tcaron, Tcaron ] }; key { [ n, N, ncaron, Ncaron ] }; key { [ s, S, scaron, Scaron ] }; key { [ y, Y, yacute, Yacute ] }; key { [ c, C, ccaron, Ccaron ] }; key { [ r, R, rcaron, Rcaron ] }; include "level3(ralt_switch)" }; // phonetic layout for Russian letters on an CZ (QWERTY) keyboard // originaly created by Pavel Sorejs partial alphanumeric_keys xkb_symbols "rus" { include "cz(qwerty)" name[Group1]= "Russian (Czech, phonetic)"; key { [ plus, ampersand, 1 , 1 ] }; key { [ Cyrillic_hardsign, 2, 2 , 2 ] }; key { [ Cyrillic_sha, Cyrillic_SHA, 3 , 3 ] }; key { [ Cyrillic_che, Cyrillic_CHE, 4 , 4 ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA, 5 , 5 ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE, 6 , 6 ] }; key { [ quotedbl, 4, 7 , 7 ] }; key { [ section, 5, 8 , 8 ] }; key { [ dollar, 6, 9 , 9 ] }; key { [ equal, 7, 0 , 0 ] }; key { [ percent, 8 ] }; key { [ apostrophe, 9 ] }; key { [ comma, question ] }; key { [ period, exclam ] }; key { [ minus, slash ] }; key { [ semicolon, colon ] }; key { [ bar, brokenbar ] }; key { [ Cyrillic_io, Cyrillic_IO ] }; key { [ numerosign, 1, q, Q ] }; key { [ Cyrillic_yu, Cyrillic_YU, w, W ] }; key { [ Cyrillic_ie, Cyrillic_IE, e, E ] }; key { [ Cyrillic_er, Cyrillic_ER, r, R ] }; key { [ Cyrillic_te, Cyrillic_TE, t, T ] }; key { [ Cyrillic_yeru, Cyrillic_YERU, y, Y ] }; key { [ Cyrillic_u, Cyrillic_U, u, U ] }; key { [ Cyrillic_i, Cyrillic_I, i, I ] }; key { [ Cyrillic_o, Cyrillic_O, o, O ] }; key { [ Cyrillic_pe, Cyrillic_PE, p, P ] }; key { [ Cyrillic_e, Cyrillic_E, bracketleft, division ] }; key { [ parenright, parenleft, bracketright, multiply ] }; key { [ Cyrillic_a, Cyrillic_A, a, A ] }; key { [ Cyrillic_es, Cyrillic_ES, s, S ] }; key { [ Cyrillic_de, Cyrillic_DE, d, D ] }; key { [ Cyrillic_ef, Cyrillic_EF, f, F ] }; key { [ Cyrillic_ghe, Cyrillic_GHE, g, G ] }; key { [ Cyrillic_ha, Cyrillic_HA, h, H ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI, j, J ] }; key { [ Cyrillic_ka, Cyrillic_KA, k, K ] }; key { [ Cyrillic_el, Cyrillic_EL, l, L ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN, less, greater ] }; key { [ Cyrillic_ze, Cyrillic_ZE, z, Z ] }; key { [ Cyrillic_ya, Cyrillic_YA, x, X ] }; key { [ Cyrillic_tse, Cyrillic_TSE, c, C ] }; key { [ Cyrillic_ve, Cyrillic_VE, v, V ] }; key { [ Cyrillic_be, Cyrillic_BE, b, B ] }; key { [ Cyrillic_en, Cyrillic_EN, n, N ] }; key { [ Cyrillic_em, Cyrillic_EM, m, M ] }; key { [ backslash, brokenbar ] }; include "level3(ralt_switch)" }; // EXTRAS: partial alphanumeric_keys xkb_symbols "sun_type6" { include "sun_vndr/cz(sun_type6)" }; xkb_symbols "prog" { // cz-prog 1.0 2019-05-15 by Viktor Grešák and Tomáš Hudec // // Programmer keyboard. Based on the US layout with accented Czech letters and dead keys. // Using AltGr and a key from the 1st row generates original level 2 US key as level 3 except TLDE and AE12. // Using AltGr+Shift on accented letters generates its uppercase variant. // Using AltGr or AltGr+Shift on letters which have accent in Czech but are not on the 1st row directly accessible generate accented letters, // i.e. [d, D], [t, T], [n, N], [o, O] generate with AltGr and AltGr+Shift: [dcaron, Dcaron], [tcaron, Tcaron], [ncaron, Ncaron], [oacute, Oacute]. // Other Czech letters besides alphanumeric keys (like uacute, uring) are generated using AltGr. name[Group1]="Czech (programming)"; key { [ z, Z ] }; key { [ x, X ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ b, B ] }; key { [ n, N, ncaron, Ncaron ] }; key { [ m, M ] }; key { [ comma, less, multiply ] }; key { [ period, greater, division ] }; key { [ slash, question, dead_abovedot ] }; key { [ a, A ] }; key { [ s, S ] }; key { [ d, D, dcaron, Dcaron ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ h, H ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ l, L ] }; key { [ semicolon, colon, uring, Uring ] }; key { [ apostrophe, quotedbl, section ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E ] }; key { [ r, R ] }; key { [ t, T, tcaron, Tcaron ] }; key { [ y, Y ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ o, O, oacute, Oacute ] }; key { [ p, P ] }; key { [ bracketleft, braceleft, uacute, Uacute ] }; key { [ bracketright, braceright ] }; key { [ plus, 1, exclam, NoSymbol ] }; key { [ ecaron, 2, at, Ecaron ] }; key { [ scaron, 3, numbersign, Scaron ] }; key { [ ccaron, 4, dollar, Ccaron ] }; key { [ rcaron, 5, percent, Rcaron ] }; key { [ zcaron, 6, asciicircum, Zcaron ] }; key { [ yacute, 7, ampersand, Yacute ] }; key { [ aacute, 8, asterisk, Aacute ] }; key { [ iacute, 9, parenleft, Iacute ] }; key { [ eacute, 0, parenright, Eacute ] }; key { [ equal, minus, underscore, U2212 ] }; key { [ dead_acute, dead_caron, plusminus, notequal ] }; key { [ backslash, bar, dead_diaeresis ] }; key { [ BackSpace, BackSpace ] }; key { [ Caps_Lock ] }; key { [ Menu, Multi_key ] }; key { [ Alt_L, Meta_L ] }; key { [ Control_L ] }; key { [ Shift_L ] }; key { [ Super_L ] }; key { [ ISO_Level3_Shift ] }; key { [ Control_R ] }; key { [ Return ] }; key { [ Shift_R ] }; key { [ Super_R ] }; key { [ space ] }; key { [ Tab, ISO_Left_Tab ] }; key { [ grave, asciitilde ] }; include "level3(ralt_switch)" }; xkb_symbols "typo" { // cz-typo 1.0 2019-05-15 by Viktor Grešák and Tomáš Hudec // // Contains typographic symbols in third and fourth level. // It is intended to be used in conjuction with other existing layout, e.g. setxkbmap -symbols "pc+cz(basic)+cz(typo)+inet(evdev)" name[Group1]="Czech (typographic)"; key { [ NoSymbol, NoSymbol, degree, U2300 ] }; key { [ NoSymbol, NoSymbol, multiply, U22C5 ] }; key { [ NoSymbol, NoSymbol, ampersand, copyright ] }; key { [ NoSymbol, NoSymbol, at, ordfeminine ] }; key { [ NoSymbol, NoSymbol, enfilledcircbullet, enopencircbullet ] }; key { [ NoSymbol, NoSymbol, U203A, U2039 ] }; key { [ NoSymbol, NoSymbol, doublelowquotemark, leftdoublequotemark ] }; key { [ NoSymbol, NoSymbol, ellipsis, rightdoublequotemark ] }; key { [ NoSymbol, NoSymbol, endash, emdash ] }; key { [ NoSymbol, NoSymbol, UFB00, UFB05 ] }; key { [ NoSymbol, NoSymbol, U2010, U2011 ] }; key { [ NoSymbol, NoSymbol, guillemotright, guillemotleft ] }; key { [ NoSymbol, NoSymbol, dagger, doubledagger ] }; key { [ NoSymbol, NoSymbol, UFB02, UFB04 ] }; key { [ NoSymbol, NoSymbol, NoSymbol, UFB03 ] }; key { [ NoSymbol, NoSymbol, U2030, registered ] }; key { [ NoSymbol, NoSymbol, leftarrow ] }; key { [ NoSymbol, NoSymbol, downarrow, uparrow ] }; key { [ NoSymbol, NoSymbol, rightarrow, UFB01 ] }; key { [ NoSymbol, NoSymbol, minutes, seconds ] }; key { [ NoSymbol, NoSymbol, NoSymbol, rightsinglequotemark ] }; key { [ NoSymbol, NoSymbol, underscore, U2212 ] }; key { [ space, space, space, nobreakspace ] }; key { [ NoSymbol, NoSymbol, singlelowquotemark, leftsinglequotemark ] }; }; xkb_symbols "coder" { // US layout with Czech chars under AltGr // for touch-typing programmers who need to write Czech occasionally // https://github.com/michalkahle/czech-coder-xkb include "us" name[Group1]= "Czech (coder)"; key {[ grave, asciitilde, semicolon, dead_abovering ]}; key {[ 2, at, ecaron, Ecaron ]}; key {[ 3, numbersign, scaron, Scaron ]}; key {[ 4, dollar, ccaron, Ccaron ]}; key {[ 5, percent, rcaron, Rcaron ]}; key {[ 6, asciicircum, zcaron, Zcaron ]}; key {[ 7, ampersand, yacute, Yacute ]}; key {[ 8, asterisk, aacute, Aacute ]}; key {[ 9, parenleft, iacute, Iacute ]}; key {[ 0, parenright, eacute, Eacute ]}; key {[ equal, plus, dead_acute, dead_caron ]}; key {[ e, E, e, EuroSign ]}; key {[ bracketleft, braceleft, uacute, Uacute ]}; key {[ semicolon, colon, uring, Uring ]}; key {[ apostrophe, quotedbl, section, quotedbl ]}; key {[ backslash, bar, dead_diaeresis, apostrophe ]}; include "level3(ralt_switch)" }; xkb_symbols "prog_typo" { // cz-prog-typo 1.0 2019-06-17 by Viktor Grešák and Tomáš Hudec // // Programmer + Typographic keyboard. Based on the US layout with accented Czech letters and dead keys. // Using AltGr and a key from the 1st row generates original level 2 US key as level 3 except TLDE and AE12. // Using AltGr+Shift on accented letters generates its uppercase variant. // Using AltGr or AltGr+Shift on letters which have accent in Czech but are not on the 1st row directly accessible generate accented letters, // i.e. [d, D], [t, T], [n, N], [o, O] generate with AltGr and AltGr+Shift: [dcaron, Dcaron], [tcaron, Tcaron], [ncaron, Ncaron], [oacute, Oacute]. // Other Czech letters besides alphanumeric keys (like uacute, uring) are generated using AltGr. // // Contains typographic symbols in third and fourth level. name[Group1]="Czech (programming, typographic)"; include "cz(prog)" include "cz(typo)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/de000066400000000000000000002503641510033435100225700ustar00rootroot00000000000000// based on a keyboard map from an 'xkb/symbols/de' file default xkb_symbols "basic" { include "latin(type4)" name[Group1]="German"; key { [ 2, quotedbl, twosuperior, oneeighth ] }; key { [ 3, section, threesuperior, sterling ] }; key { [ 4, dollar, onequarter, currency ] }; key {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]= [ssharp, question, backslash, questiondown, 0x1001E9E ]}; key { [dead_acute, dead_grave, dead_cedilla, dead_ogonek ] }; key { [ e, E, EuroSign, EuroSign ] }; key { [ z, Z, leftarrow, yen ] }; key { [udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] }; key { [ plus, asterisk, asciitilde, macron ] }; key { [ s, S, U017F, U1E9E ] }; key { [ j, J, dead_belowdot, dead_abovedot ] }; key { [odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] }; key { [adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] }; key { [dead_circumflex, degree, U2032, U2033 ] }; key { [numbersign, apostrophe, rightsinglequotemark, dead_breve ] }; key { [ y, Y, guillemotright, U203A ] }; key { [ x, X, guillemotleft, U2039 ] }; key { [ v, V, doublelowquotemark, singlelowquotemark ] }; key { [ b, B, leftdoublequotemark, leftsinglequotemark ] }; key { [ n, N, rightdoublequotemark, rightsinglequotemark ] }; key { [ comma, semicolon, periodcentered, multiply ] }; key { [ period, colon, U2026, division ] }; key { [ minus, underscore, endash, emdash ] }; key { [ less, greater, bar, dead_belowmacron ] }; include "kpdl(comma)" include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "deadtilde" { // previous standard German layout with tilde as dead key include "de(basic)" name[Group1]="German (dead tilde)"; key { [ plus, asterisk, dead_tilde, dead_macron ] }; }; partial alphanumeric_keys xkb_symbols "nodeadkeys" { // modify the basic German layout to not have any dead keys include "de(basic)" name[Group1]="German (no dead keys)"; key { [asciicircum, degree, notsign, notsign ] }; key { [ acute, grave, cedilla, cedilla ] }; key { [ udiaeresis, Udiaeresis, diaeresis, diaeresis ] }; key { [ plus, asterisk, asciitilde, macron ] }; key { [ odiaeresis, Odiaeresis, doubleacute, doubleacute ] }; key { [ adiaeresis, Adiaeresis, asciicircum, asciicircum ] }; key { [ numbersign, apostrophe, rightsinglequotemark, grave ] }; }; partial alphanumeric_keys xkb_symbols "deadgraveacute" { // modify the basic German layout to have only acute and grave // as dead keys (tilde and circumflex are needed as spacing characters // in many programming languages) include "de(basic)" name[Group1]="German (dead grave acute)"; key { [asciicircum, degree, notsign, notsign ] }; key { [ plus, asterisk, asciitilde, dead_macron ] }; key { [ numbersign, apostrophe, rightsinglequotemark, grave ] }; }; partial alphanumeric_keys xkb_symbols "deadacute" { // modify the basic German layout to have only acute as // dead keys (ASCII grave, tilde and circumflex are needed as // spacing characters in many programming languages and text formatters) include "de(deadgraveacute)" name[Group1]="German (dead acute)"; key { [dead_acute, grave, dead_cedilla, dead_ogonek ] }; key { [numbersign, apostrophe, rightsinglequotemark, dead_grave ] }; }; partial alphanumeric_keys xkb_symbols "T3" { name[Group1]="German (T3)"; key.type[Group1] = "EIGHT_LEVEL"; key { [ dead_circumflex, degree, multiply, NoSymbol, U204A, hyphen, bar, NoSymbol ] }; key { [ 1, exclam, rightsinglequotemark, NoSymbol, onesuperior, exclamdown, U02B9, NoSymbol ] }; key { [ 2, quotedbl, twosuperior, NoSymbol, twosuperior, currency, U02BA, NoSymbol ] }; key { [ 3, section, threesuperior, NoSymbol, threesuperior, sterling, U02BF, NoSymbol ] }; key { [ 4, dollar, emdash, NoSymbol, onequarter, 0x20AC, U02BE, NoSymbol ] }; key { [ 5, percent, exclamdown, NoSymbol, onehalf, uparrow, U02C1, NoSymbol ] }; key { [ 6, ampersand, questiondown, NoSymbol, threequarters, downarrow, U02C0, NoSymbol ] }; key { [ 7, slash, braceleft, NoSymbol, oneeighth, leftarrow, braceleft, NoSymbol ] }; key { [ 8, parenleft, bracketleft, NoSymbol, threeeighths, rightarrow, braceright, NoSymbol ] }; key { [ 9, parenright, bracketright, NoSymbol, fiveeighths, plusminus, bracketleft, NoSymbol ] }; key { [ 0, equal, braceright, NoSymbol, seveneighths, trademark, bracketright, NoSymbol ] }; key { [ ssharp, question, backslash, NoSymbol, backslash, questiondown, U02BB, NoSymbol ] }; key { [ dead_acute, dead_grave, dead_abovedot, NoSymbol, dead_cedilla, dead_ogonek, notsign, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; key { [ q, Q, at, NoSymbol, U0242, U0241, U030D, NoSymbol ] }; key { [ w, W, dead_caron, NoSymbol, U02B7, U2126, dead_abovedot, NoSymbol ] }; key { [ e, E, EuroSign, NoSymbol, oe, OE, dead_breve, NoSymbol ] }; key { [ r, R, dead_diaeresis, NoSymbol, paragraph, registered, dead_circumflex, NoSymbol ] }; key { [ t, T, dead_macron, NoSymbol, UA78C, UA78B, dead_diaeresis, NoSymbol ] }; key { [ z, Z, dead_doubleacute, NoSymbol, U027C, yen, dead_invertedbreve, NoSymbol ] }; key { [ u, U, dead_breve, NoSymbol, U0223, U0222, dead_caron, NoSymbol ] }; key { [ i, I, dead_tilde, NoSymbol, idotless, U214D, dead_abovecomma, NoSymbol ] }; key { [ o, O, dead_abovering, NoSymbol, oslash, Oslash, dead_horn, NoSymbol ] }; key { [ p, P, dead_hook, NoSymbol, thorn, THORN, dead_hook, NoSymbol ] }; key { [ udiaeresis, Udiaeresis, dead_horn, NoSymbol, U017F, dead_abovering, dead_grave, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL"; key { [ plus, asterisk, asciitilde, NoSymbol, dead_tilde, dead_macron, at, NoSymbol ] }; key.type[Group1] = "ONE_LEVEL"; key { [ Caps_Lock ] }; key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; key { [ a, A, lessthanequal, NoSymbol, ae, AE, U0329, NoSymbol ] }; key { [ s, S, greaterthanequal, NoSymbol, ssharp, section, dead_belowdot, NoSymbol ] }; key { [ d, D, U2300, NoSymbol, eth, ETH, dead_belowbreve, NoSymbol ] }; key { [ f, F, minutes, NoSymbol, U0294, ordfeminine, dead_belowcircumflex, NoSymbol ] }; key { [ g, G, seconds, NoSymbol, eng, ENG, dead_belowmacron, NoSymbol ] }; key { [ h, H, U1E9E, NoSymbol, U0272, U019D, U0332, NoSymbol ] }; key { [ j, J, dead_cedilla, NoSymbol, U0133, U0132, dead_belowring, NoSymbol ] }; key { [ k, K, dead_belowcomma, NoSymbol, kra, dead_belowcomma, dead_stroke, NoSymbol ] }; key { [ l, L, dead_ogonek, NoSymbol, lstroke, Lstroke, U0338, NoSymbol ] }; key { [ odiaeresis, Odiaeresis, dead_belowdot, NoSymbol, dead_acute, dead_doubleacute, degree, NoSymbol ] }; key { [ adiaeresis, Adiaeresis, dead_stroke, NoSymbol, U019B, U1E9E, minutes, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL"; key { [ numbersign, apostrophe, registered, NoSymbol, schwa, SCHWA, seconds, NoSymbol ] }; key { [ less, greater, bar, NoSymbol, U0149, brokenbar, U266A, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; key { [ y, Y, U203A, NoSymbol, U0292, U01B7, guillemotleft, NoSymbol ] }; key { [ x, X, guillemotright, NoSymbol, doublelowquotemark, singlelowquotemark, guillemotright, NoSymbol ] }; key { [ c, C, copyright, NoSymbol, cent, copyright, Greek_horizbar, NoSymbol ] }; key { [ v, V, guillemotleft, NoSymbol, leftdoublequotemark, leftsinglequotemark, U2039, NoSymbol ] }; key { [ b, B, U2039, NoSymbol, rightdoublequotemark, rightsinglequotemark, U203A, NoSymbol ] }; key { [ n, N, endash, NoSymbol, U019E, U0220, endash, NoSymbol ] }; key { [ m, M, mu, NoSymbol, mu, masculine, emdash, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL"; key { [ comma, semicolon, U02BB, NoSymbol, ellipsis, multiply, dollar, NoSymbol ] }; key { [ period, colon, U200C, NoSymbol, periodcentered, division, numbersign, NoSymbol ] }; key { [ minus, underscore, hyphen, NoSymbol, U0140, U013F, U2011, NoSymbol ] }; key { [ space, space, nobreakspace, NoSymbol, U202F, U200C, nobreakspace, NoSymbol ] }; include "kpdl(comma)" include "level5(modifier_mapping)" include "level3(modifier_mapping)" key.type[Group1] = "THREE_LEVEL"; key { [ Shift_L, Shift_L, ISO_Level5_Latch ] }; key { [ Shift_R, Shift_R, ISO_Level5_Latch ] }; key { [ ISO_Level3_Shift, ISO_Level5_Latch, ISO_Level5_Latch ] }; }; partial alphanumeric_keys xkb_symbols "ro" { // add romanian-specific letters to the basic German layout. // Romanian symbols are accessible with combination of and // 'a', 's', 't', 'i', 'ä (ä)' (+ for capital letters). // To view romanian-specific symbols, add "export LC_CTYPE=ro_RO" // or "export LC_CTYPE=de_DE.utf8" to your .profile. include "de(basic)" name[Group1]="Romanian (Germany)"; key { [ t, T, tcedilla, Tcedilla ] }; key { [ i, I, icircumflex, Icircumflex ] }; key { [ a, A, acircumflex, Acircumflex ] }; key { [ s, S, scedilla, Scedilla ] }; key { [ adiaeresis, Adiaeresis, abreve, Abreve ] }; }; partial alphanumeric_keys xkb_symbols "ro_nodeadkeys" { // add romanian-specific letters to the German nodeadkeys layout. // Read the comment for de_ro ! include "de(nodeadkeys)" name[Group1]="Romanian (Germany, no dead keys)"; key { [ t, T, tcedilla, Tcedilla ] }; key { [ i, I, icircumflex, Icircumflex ] }; key { [ a, A, acircumflex, Acircumflex ] }; key { [ s, S, scedilla, Scedilla ] }; key { [ adiaeresis, Adiaeresis, abreve, Abreve ] }; }; // German Dvorak keymap by Thorsten Staerk (www.staerk.de/thorsten) // Have acute and grave as dead keys, tilde and circumflex alive as they are needed // in many programming languages. // to use this keymap, use a 105-key-keyboard and the command setxkbmap -model pc105 -layout dvorak -variant de // source: http://www-lehre.informatik.uni-osnabrueck.de/~rfreund/dvorak.php partial alphanumeric_keys xkb_symbols "dvorak" { include "us(dvorak)" name[Group1]="German (Dvorak)"; key { [ asciicircum, degree ] }; key { [ 1, exclam, onesuperior ] }; key { [ 2, quotedbl, twosuperior ] }; key { [ 3, section, threesuperior ] }; key { [ 4, dollar, bar ] }; key { [ 5, percent, bar ] }; key { [ 6, ampersand, brokenbar ] }; key { [ 7, slash, braceleft ] }; key { [ 8, parenleft, bracketleft ] }; key { [ 9, parenright, bracketright ] }; key { [ 0, equal, braceright ] }; key { [ plus, asterisk, asciitilde ] }; key { [ less, greater, dead_grave ] }; key { [ udiaeresis, Udiaeresis, at ] }; key { [ comma, semicolon, dead_diaeresis ] }; key { [ period, colon ] }; key { [ c, C, copyright, Cacute ] }; key { [ t, T, trademark ] }; key { [ z, Z, zabovedot, Zabovedot ] }; key { [ question, ssharp ] }; key { [ slash, backslash, dead_acute ] }; key { [ a, A, at, aogonek ] }; key { [ o, O, oacute, Oacute ] }; key { [ e, E, EuroSign, eogonek ] }; key { [ i, I ] }; key { [ u, U ] }; key { [ h, H ] }; key { [ d, D ] }; key { [ r, R, registered ] }; key { [ n, N, nacute, Nacute ] }; key { [ s, S, sacute, Sacute] }; key { [ l, L, lstroke, Lstroke ] }; key { [ odiaeresis, Odiaeresis ] }; key { [ q, Q, at ] }; key { [ m, M, mu ] }; key { [ numbersign, apostrophe ] }; key { [ minus, underscore, hyphen, diaeresis] }; key { [ adiaeresis, Adiaeresis, bar ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "Sundeadkeys" { // For naming consistency include "de(basic)" }; partial alphanumeric_keys xkb_symbols "sundeadkeys" { // For naming consistency include "de(Sundeadkeys)" name[Group1]="German (Sun dead keys)"; }; // German Neo-Layout Version 2 // adopted 2004 by Hanno Behrens // inspired by Dvorak/de-ergo http://www.goebel-consult.de/de-ergo/ // // Authors: // Stephan Hilb // // Benjamin Kellermann // Erik Streb // and many other contributors // // http://www.neo-layout.org // // $Revision$, $Date$ partial alphanumeric_keys modifier_keys keypad_keys xkb_symbols "neo_base" { // Levels in Neo jargon // -------------------------------------------------------------- // Ebene 1: normal // Ebene 2: Shift // Ebene 3: Mod3 // Ebene 4: Mod4 (for marking something use Shift + Mod4) // Ebene 5: Shift + Mod3 // Ebene 6: Mod3 + Mod4 // Compose (not a level): Mod3 + Tab // Feststelltaste (Capslock): Shift + Shift // Mod4-Lock: Mod4 + Mod4 // Mod4-Lock: Shift + Mod3 + Tab // Legend // =============== // Levels in Xkbmap jargon to be found here in the definitions. // These are the levels used, and Xorg's translations: // -------------------------------------------------------------- // Xorg: Level1 Level2 Level3 Level4 Level5 Level6 Level7 Level8 // Neo: Ebene1 Ebene2 Ebene3 Ebene5 Ebene4 Pseudo-Ebene Ebene6 ??? // Keys (Neo): None Shift Mod3 Mod3 + Shift Mod4 Mod4 + Shift Mod3 + Mod4 Mod3 + Mod4 + Shift // Alphanumeric-keys // =============== key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; // Tab as Multi_key (Compose) // -------------------------------------------------------------- key { [ Tab, ISO_Left_Tab, Multi_key, ISO_Level5_Lock, NoSymbol, NoSymbol, NoSymbol, ISO_Level5_Lock ] }; // Number row // -------------------------------------------------------------- key { [ dead_circumflex, dead_caron, U21BB, U02DE, dead_abovedot, Pointer_EnableKeys, dead_belowdot, NoSymbol ] }; key { [ 1, degree, onesuperior, onesubscript, ordfeminine, NoSymbol, notsign, NoSymbol ] }; key { [ 2, section, twosuperior, twosubscript, masculine, NoSymbol, logicalor, NoSymbol ] }; key { [ 3, U2113, threesuperior, threesubscript, numerosign, NoSymbol, logicaland, NoSymbol ] }; key { [ 4, guillemotright, U203A, femalesymbol, NoSymbol, NoSymbol, U22A5, NoSymbol ] }; key { [ 5, guillemotleft, U2039, malesymbol, periodcentered, NoSymbol, U2221, NoSymbol ] }; key { [ 6, dollar, cent, U26A5, sterling, NoSymbol, U2225, NoSymbol ] }; key { [ 7, EuroSign, yen, U03F0, currency, NoSymbol, rightarrow, NoSymbol ] }; key { [ 8, doublelowquotemark, singlelowquotemark, U27E8, Tab, ISO_Left_Tab, U221E, NoSymbol ] }; key { [ 9, leftdoublequotemark, leftsinglequotemark, U27E9, KP_Divide, KP_Divide, variation, NoSymbol ] }; key { [ 0, rightdoublequotemark, rightsinglequotemark, zerosubscript, KP_Multiply, KP_Multiply, emptyset, NoSymbol ] }; key { [ minus, emdash, NoSymbol, U2011, KP_Subtract, KP_Subtract, hyphen, NoSymbol ] }; key { [ dead_grave, dead_cedilla, dead_abovering, dead_dasia, dead_diaeresis, NoSymbol, dead_macron, NoSymbol ] }; // Top row // -------------------------------------------------------------- key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ x, X, ellipsis, Greek_xi, Prior, Prior, Greek_XI, NoSymbol ] }; key { [ v, V, underscore, NoSymbol, BackSpace, BackSpace, radical, NoSymbol ] }; key { [ l, L, bracketleft, Greek_lambda, Up, Up, Greek_LAMBDA, NoSymbol ] }; key { [ c, C, bracketright, Greek_chi, Delete, Delete, U2102, NoSymbol ] }; key { [ w, W, asciicircum, Greek_omega, Next, Next, Greek_OMEGA, NoSymbol ] }; key { [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] }; key { [ h, H, less, Greek_psi, KP_7, KP_7, Greek_PSI, NoSymbol ] }; key { [ g, G, greater, Greek_gamma, KP_8, KP_8, Greek_GAMMA, NoSymbol ] }; key { [ f, F, equal, Greek_phi, KP_9, KP_9, Greek_PHI, NoSymbol ] }; key { [ q, Q, ampersand, U03D5, KP_Add, KP_Add, U211A, NoSymbol ] }; key { [ ssharp, U1E9E, U017F, Greek_finalsmallsigma, U2212, NoSymbol, jot, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; key { [ dead_acute, dead_tilde, dead_stroke, dead_psili, dead_doubleacute, NoSymbol, dead_breve, NoSymbol ] }; // Middle row // -------------------------------------------------------------- key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ u, U, backslash, NoSymbol, Home, Home, includedin, NoSymbol ] }; key { [ i, I, slash, Greek_iota, Left, Left, integral, NoSymbol ] }; key { [ a, A, braceleft, Greek_alpha, Down, Down, U2200, NoSymbol ] }; key { [ e, E, braceright, Greek_epsilon, Right, Right, U2203, NoSymbol ] }; key { [ o, O, asterisk, Greek_omicron, End, End, elementof, NoSymbol ] }; key { [ s, S, question, Greek_sigma, questiondown, NoSymbol, Greek_SIGMA, NoSymbol ] }; key { [ n, N, parenleft, Greek_nu, KP_4, KP_4, U2115, NoSymbol ] }; key { [ r, R, parenright, Greek_rho, KP_5, KP_5, U211D, NoSymbol ] }; key { [ t, T, minus, Greek_tau, KP_6, KP_6, partialderivative, NoSymbol ] }; key { [ d, D, colon, Greek_delta, KP_Separator, comma, Greek_DELTA, NoSymbol ] }; key { [ y, Y, at, Greek_upsilon, period, KP_Decimal, nabla, NoSymbol ] }; // Bottom row // -------------------------------------------------------------- key { [ udiaeresis, Udiaeresis, numbersign, NoSymbol, Escape, Escape, union, NoSymbol ] }; key { [ odiaeresis, Odiaeresis, dollar, U03F5, Tab, Tab, intersection, NoSymbol ] }; key { [ adiaeresis, Adiaeresis, bar, Greek_eta, Insert, Insert, U2135, NoSymbol ] }; key { [ p, P, asciitilde, Greek_pi, Return, Return, Greek_PI, NoSymbol ] }; key { [ z, Z, grave, Greek_zeta, Undo, Redo, U2124, NoSymbol ] }; key { [ b, B, plus, Greek_beta, colon, NoSymbol, U21D0, NoSymbol ] }; key { [ m, M, percent, Greek_mu, KP_1, KP_1, ifonlyif, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; key { [ comma, endash, quotedbl, U03F1, KP_2, KP_2, U21D2, NoSymbol ] }; key { [ period, enfilledcircbullet, apostrophe, U03D1, KP_3, KP_3, U21A6, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ j, J, semicolon, Greek_theta, semicolon, NoSymbol, Greek_THETA, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; // Space key // -------------------------------------------------------------- key { [ space, space, space, nobreakspace, KP_0, KP_0, U202F, NoSymbol ] }; // Keypad-keys // =============== // The former Numlock key: key { [ Tab, ISO_Left_Tab, equal, approxeq, notequal, Pointer_EnableKeys, identical, NoSymbol ] }; // Topmost row // -------------------------------------------------------------- key { [ KP_Divide, KP_Divide, division, U2300, U2215, NoSymbol, U2223, NoSymbol ] }; key { [ KP_Multiply, KP_Multiply, U22C5, U2299, multiply, NoSymbol, U2297, NoSymbol ] }; key { [ KP_Subtract, KP_Subtract, U2212, U2296, U2216, NoSymbol, U2238, NoSymbol ] }; // Top row // -------------------------------------------------------------- key { [ KP_7, U2714, U2195, U226A, KP_Home, KP_Home, upstile, NoSymbol ] }; key { [ KP_8, U2718, uparrow, intersection, KP_Up, KP_Up, U22C2, NoSymbol ] }; key { [ KP_9, dagger, U20D7, U226B, KP_Prior, KP_Prior, U2309, NoSymbol ] }; key { [ KP_Add, KP_Add, plusminus, U2295, U2213, NoSymbol, U2214, NoSymbol ] }; // Middle row // -------------------------------------------------------------- key { [ KP_4, club, leftarrow, includedin, KP_Left, KP_Left, U2286, NoSymbol ] }; key { [ KP_5, EuroSign, colon, U22B6, KP_Begin, KP_Begin, U22B7, NoSymbol ] }; key { [ KP_6, U2023, rightarrow, includes, KP_Right, KP_Right, U2287, NoSymbol ] }; // Bottom row // -------------------------------------------------------------- key { [ KP_1, diamond, U2194, lessthanequal, KP_End, KP_End, downstile, NoSymbol ] }; key { [ KP_2, heart, downarrow, union, KP_Down, KP_Down, U22C3, NoSymbol ] }; key { [ KP_3, U2660, U21CC, greaterthanequal, KP_Next, KP_Next, U230B, NoSymbol ] }; key { [ KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, NoSymbol ] }; key { [ KP_Equal, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; // Bottommost row // -------------------------------------------------------------- key { [ KP_0, U2423, percent, U2030, KP_Insert, KP_Insert, U25A1, NoSymbol ] }; key { [ KP_Separator, period, comma, minutes, KP_Delete, KP_Delete, seconds, NoSymbol ] }; }; partial alphanumeric_keys modifier_keys keypad_keys xkb_symbols "neo" { include "de(neo_base)" name[Group1]= "German (Neo 2)"; include "shift(both_capslock)" include "level3(caps_switch)" include "level3(bksl_switch)" include "level5(lsgt_switch_lock)" include "level5(ralt_switch_lock)" }; // Copied from macintosh_vndr/de // olh@suse.de very close to MacOS map partial alphanumeric_keys xkb_symbols "mac" { include "de" name[Group1]= "German (Macintosh)"; key { [ 1, exclam, exclamdown, at ] }; key { [ 5, percent, bracketleft ] }; key { [ 6, ampersand, bracketright ] }; key { [ 7, slash, bar, backslash ] }; key { [ 8, parenleft, braceleft, asciitilde ] }; key { [ 9, parenright, braceright ] }; key { [ q, Q, guillemotleft, guillemotright ] }; key { [ r, R, registered ] }; key { [ u, U, diaeresis, Aacute ] }; key { [ i, I, slash, Ucircumflex ] }; key { [ udiaeresis, Udiaeresis, periodcentered, degree ] }; key { [ plus, asterisk, asciitilde ] }; key { [ a, A, aring, Aring ] }; key { [ g, G, copyright ] }; key { [ h, H, ordfeminine ] }; key { [ l, L, at ] }; key { [ odiaeresis, Odiaeresis, dead_acute ] }; key { [ n, N, asciitilde ] }; }; partial alphanumeric_keys xkb_symbols "mac_nodeadkeys" { // modify the standard German mac layout to not have any dead keys include "de(mac)" name[Group1]= "German (Macintosh, no dead keys)"; key { [ asciicircum, degree, notsign ] }; key { [ 4, dollar, onequarter, currency ] }; key { [ acute, grave, cedilla ] }; key { [ udiaeresis, Udiaeresis, diaeresis ] }; key { [ plus, asterisk, asciitilde, macron ] }; key { [ odiaeresis, Odiaeresis, acute ] }; key { [ adiaeresis, Adiaeresis, asciicircum ] }; key { [ numbersign, apostrophe, rightsinglequotemark ] }; }; partial alphanumeric_keys xkb_symbols "dsb" { include "latin(basic)" name[Group1] = "Lower Sorbian"; key { [ z, Z, zcaron, Zcaron ] }; key { [ x, X, zacute, Zacute ] }; key { [ c, C, cacute, Cacute ] }; key { [ v, V, ccaron, Ccaron ] }; key { [ n, N, nacute, Nacute ] }; key { [ s, S, sacute, Sacute ] }; key { [ d, D, scaron, Scaron ] }; key { [ f, F ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E, ecaron, Ecaron ] }; key { [ r, R, racute, Racute ] }; key { [ t, T, U20B5, EuroSign ] }; key { [ o, O, oacute, Oacute ] }; include "kpdl(comma)" include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "dsb_qwertz" { include "latin(basic)" name[Group1] = "Lower Sorbian (QWERTZ)"; key { [ y, Y ] }; key { [ x, X ] }; key { [ c, C, cacute, Cacute ] }; key { [ v, V, ccaron, Ccaron ] }; key { [ n, N, nacute, Nacute ] }; key { [ s, S, sacute, Sacute ] }; key { [ d, D, scaron, Scaron ] }; key { [ f, F ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E, ecaron, Ecaron ] }; key { [ r, R, racute, Racute ] }; key { [ t, T, U20B5, EuroSign ] }; key { [ z, Z, zcaron, Zcaron ] }; key { [ u, U, zacute, Zacute ] }; key { [ o, O, oacute, Oacute ] }; include "kpdl(comma)" include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "qwerty" { // This layout should work exactly as a de with the exception // of 'Z' and 'Y' keys, which are in the qwerty style (ie. swapped). // 2008 by Matej Košík include "de(basic)" name[Group1] = "German (QWERTY)"; key { [ z, Z, leftarrow, yen ] }; key { [ y, Y, guillemotleft, less ] }; }; // layout for Russian letters on an german keyboard // based on US-RU layout by Ivan Popov 2005-07-17 // adopted for german layout by Alexey Fisher 2010-08-19 partial alphanumeric_keys xkb_symbols "ru" { include "de(basic)" name[Group1]= "Russian (Germany, phonetic)"; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_ghe, Cyrillic_GHE ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_ie, Cyrillic_IE ] }; key { [ Cyrillic_io, Cyrillic_IO, asciitilde ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_ze, Cyrillic_ZE ] }; key { [ Cyrillic_i, Cyrillic_I ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_es, Cyrillic_ES ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_u, Cyrillic_U ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_sha, Cyrillic_SHA ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA, plus, asterisk ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; key { [ Cyrillic_e, Cyrillic_E ] }; key { [ Cyrillic_yu, Cyrillic_YU, numbersign, apostrophe ] }; key { [ Cyrillic_ya, Cyrillic_YA ] }; include "level3(ralt_switch)" }; // layout for Russian (recommended) letters on a german keyboard // based on "Russisch für Deutsche, empfohlen" by B. Bendixen und H. Rothe http://russisch.urz.uni-leipzig.de/key2000.htm 2016-02-01 // adapted for Linux by Niko Krause 2016-06-09 partial alphanumeric_keys xkb_symbols "ru-recom" { include "de(basic)" name[Group1]= "Russian (Germany, recommended)"; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_ghe, Cyrillic_GHE, Ukrainian_ghe_with_upturn, Ukrainian_GHE_WITH_UPTURN ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_ie, Cyrillic_IE ] }; key { [ Cyrillic_ya, Cyrillic_YA, asciicircum, degree ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_i, Cyrillic_I, Ukrainian_i, Ukrainian_I ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI, Ukrainian_yi, Ukrainian_YI ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_es, Cyrillic_ES, Cyrillic_ze, Cyrillic_ZE ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_u, Cyrillic_U ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_yu, Cyrillic_YU ] }; key { [ Cyrillic_sha, Cyrillic_SHA, plus, asterisk ] }; key { [ Cyrillic_ze, Cyrillic_ZE ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; key { [ Cyrillic_e, Cyrillic_E, Ukrainian_ie, Ukrainian_IE ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, numbersign, apostrophe ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ asciitilde, question, backslash, questiondown ] }; key { [ U0301, U0300, U0323, U0307 ] }; include "level3(ralt_switch)" }; // layout for Russian (transliteration) letters on a german keyboard // based on "Russisch für Deutsche, Transliteration" by B. Bendixen und H. Rothe http://russisch.urz.uni-leipzig.de/key2000.htm 2016-02-01 // adapted for Linux by Niko Krause 2016-06-09 partial alphanumeric_keys xkb_symbols "ru-translit" { include "de(basic)" name[Group1]= "Russian (Germany, transliteration)"; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_sha, Cyrillic_SHA ] }; key { [ Cyrillic_ghe, Cyrillic_GHE, Ukrainian_ghe_with_upturn, Ukrainian_GHE_WITH_UPTURN ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_ie, Cyrillic_IE ] }; key { [ Cyrillic_ya, Cyrillic_YA, asciicircum, degree ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_ze, Cyrillic_ZE ] }; key { [ Cyrillic_i, Cyrillic_I, Ukrainian_i, Ukrainian_I ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI, Ukrainian_yi, Ukrainian_YI ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_es, Cyrillic_ES, Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_u, Cyrillic_U ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_yu, Cyrillic_YU ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, plus, asterisk ] }; key { [ Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_e, Cyrillic_E, Ukrainian_ie, Ukrainian_IE ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN, numbersign, apostrophe ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ asciitilde, question, backslash, questiondown ] }; key { [ U0301, U0300, U0323, U0307 ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "pl" { // Combined layout for entering both German and Polish symbols on a German physical // keyboard. Based on German (no dead keys) and Polish (basic). Polish diacritics // on AltGr+"acelnosxz". EuroSign moved to AE04 (AltGr+dollar key) to avoid conflict // with Polish eogonek. // // https://github.com/kontextify/xkeyboard-config include "latin(type4)" name[Group1]= "Polish (Germany, no dead keys)"; include "de(nodeadkeys)" key { [ 4, dollar, EuroSign, currency ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E, eogonek, Eogonek ] }; key { [ o, O, oacute, Oacute ] }; key { [ a, A, aogonek, Aogonek ] }; key { [ s, S, sacute, Sacute ] }; key { [ f, F ] }; key { [ z, Z, zabovedot, Zabovedot ] }; key { [ x, X, zacute, Zacute ] }; key { [ c, C, cacute, Cacute ] }; key { [ n, N, nacute, Nacute ] }; include "kpdl(comma)" include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "tr" { // add turkish-specific letters to the basic German layout. // Turkish symbols are accessible with combination of and // 'i', 's', 'g', 'c'' (+ for capital letters). include "de(basic)" name[Group1]="Turkish (Germany)"; key { [ i, I, U0131, U0130 ] }; key { [ s, S, U015F, U015E ] }; key { [ g, G, U011F, U011E ] }; key { [ c, C, U0E7, U0C7 ] }; }; // EXTRAS: partial alphanumeric_keys xkb_symbols "us" { include "us" name[Group1]="German (US)"; key { [ a, A, adiaeresis, Adiaeresis ] }; key { [ s, S, ssharp, U1E9E ] }; key { [ semicolon, colon, odiaeresis, Odiaeresis ] }; key { [ apostrophe, quotedbl, adiaeresis, Adiaeresis ] }; key { [ e, E, EuroSign, EuroSign ] }; key { [ u, U, udiaeresis, Udiaeresis ] }; key { [ o, O, odiaeresis, Odiaeresis ] }; key { [ bracketleft, braceleft, udiaeresis, Udiaeresis ] }; key { [ 3, numbersign, section, section ] }; key { [ minus, underscore, ssharp, question ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "hu" { // modify the basic German layout to not have any dead keys and add Hungarian letters include "de(basic)" name[Group1]="German (with Hungarian letters, no dead keys)"; key { [ y, Y, guillemotleft, less ] }; key { [odiaeresis, Odiaeresis, eacute, Eacute ] }; key { [adiaeresis, Adiaeresis, aacute, Aacute] }; key { [ e, E, EuroSign, EuroSign ] }; key { [ z, Z, leftarrow, yen ] }; key { [ u, U, uacute, Uacute ] }; key { [ i, I, iacute, Iacute ] }; key { [ o, O, odoubleacute, Odoubleacute ] }; key { [udiaeresis, Udiaeresis, udoubleacute, Udoubleacute ] }; key { [ plus, asterisk, asciitilde, macron ] }; key { [ acute, grave, oacute, Oacute ] }; key { [numbersign, apostrophe, rightsinglequotemark, grave ] }; key { [asciicircum, degree, notsign, notsign ] }; }; partial alphanumeric_keys xkb_symbols "sun_type6" { include "sun_vndr/de(sun_type6)" }; partial alphanumeric_keys xkb_symbols "adnw_base" { include "de(neo_base)" key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; key { [ period, enfilledcircbullet, NoSymbol, U03D1, NoSymbol, NoSymbol, U21A6, NoSymbol ] }; key { [ comma, endash, NoSymbol, U03F1, NoSymbol, NoSymbol, U21D2, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ k, K, NoSymbol, Greek_kappa, NoSymbol, NoSymbol, multiply, NoSymbol ] }; key { [ u, U, NoSymbol, NoSymbol, NoSymbol, NoSymbol, includedin, NoSymbol ] }; key { [ udiaeresis, Udiaeresis, NoSymbol, NoSymbol, NoSymbol, NoSymbol, union, NoSymbol ] }; key { [ adiaeresis, Adiaeresis, NoSymbol, Greek_eta, NoSymbol, NoSymbol, U2135, NoSymbol ] }; key { [ v, V, NoSymbol, NoSymbol, NoSymbol, NoSymbol, radical, NoSymbol ] }; key { [ g, G, NoSymbol, Greek_gamma, NoSymbol, NoSymbol, Greek_GAMMA, NoSymbol ] }; key { [ c, C, NoSymbol, Greek_chi, NoSymbol, NoSymbol, U2102, NoSymbol ] }; key { [ l, L, NoSymbol, Greek_lambda, NoSymbol, NoSymbol, Greek_LAMBDA, NoSymbol ] }; key { [ j, J, NoSymbol, Greek_theta, NoSymbol, NoSymbol, Greek_THETA, NoSymbol ] }; key { [ f, F, NoSymbol, Greek_phi, NoSymbol, NoSymbol, Greek_PHI, NoSymbol ] }; key { [ h, H, NoSymbol, Greek_psi, NoSymbol, NoSymbol, Greek_PSI, NoSymbol ] }; key { [ i, I, NoSymbol, Greek_iota, NoSymbol, NoSymbol, integral, NoSymbol ] }; key { [ e, E, NoSymbol, Greek_epsilon, NoSymbol, NoSymbol, U2203, NoSymbol ] }; key { [ a, A, NoSymbol, Greek_alpha, NoSymbol, NoSymbol, U2200, NoSymbol ] }; key { [ o, O, NoSymbol, Greek_omicron, NoSymbol, NoSymbol, elementof, NoSymbol ] }; key { [ d, D, NoSymbol, Greek_delta, NoSymbol, NoSymbol, Greek_DELTA, NoSymbol ] }; key { [ t, T, NoSymbol, Greek_tau, NoSymbol, NoSymbol, partialderivative, NoSymbol ] }; key { [ r, R, NoSymbol, Greek_rho, NoSymbol, NoSymbol, U211D, NoSymbol ] }; key { [ n, N, NoSymbol, Greek_nu, NoSymbol, NoSymbol, U2115, NoSymbol ] }; key { [ s, S, NoSymbol, Greek_sigma, NoSymbol, NoSymbol, Greek_SIGMA, NoSymbol ] }; key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; key { [ x, X, NoSymbol, Greek_xi, NoSymbol, NoSymbol, Greek_XI, NoSymbol ] }; key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; key { [ odiaeresis, Odiaeresis, NoSymbol, U03F5, NoSymbol, NoSymbol, intersection, NoSymbol ] }; key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; key { [ b, B, NoSymbol, Greek_beta, NoSymbol, NoSymbol, U21D0, NoSymbol ] }; key { [ p, P, NoSymbol, Greek_pi, NoSymbol, NoSymbol, Greek_PI, NoSymbol ] }; key { [ w, W, NoSymbol, Greek_omega, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol ] }; key { [ m, M, NoSymbol, Greek_mu, NoSymbol, NoSymbol, ifonlyif, NoSymbol ] }; key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; }; partial alphanumeric_keys modifier_keys keypad_keys xkb_symbols "adnw" { include "de(adnw_base)" name[Group1]= "German (Aus der Neo-Welt)"; include "shift(both_capslock)" include "level3(caps_switch)" include "level3(bksl_switch)" include "level5(lsgt_switch_lock)" include "level5(ralt_switch_lock)" }; partial alphanumeric_keys xkb_symbols "koy_base" { include "de(neo_base)" key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; key { [ period, enfilledcircbullet, NoSymbol, U03D1, NoSymbol, NoSymbol, U21A6, NoSymbol ] }; key { [ comma, endash, NoSymbol, U03F1, NoSymbol, NoSymbol, U21D2, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ k, K, NoSymbol, Greek_kappa, NoSymbol, NoSymbol, multiply, NoSymbol ] }; key { [ o, O, NoSymbol, Greek_omicron, NoSymbol, NoSymbol, elementof, NoSymbol ] }; key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; key { [ v, V, NoSymbol, NoSymbol, NoSymbol, NoSymbol, radical, NoSymbol ] }; key { [ g, G, NoSymbol, Greek_gamma, NoSymbol, NoSymbol, Greek_GAMMA, NoSymbol ] }; key { [ c, C, NoSymbol, Greek_chi, NoSymbol, NoSymbol, U2102, NoSymbol ] }; key { [ l, L, NoSymbol, Greek_lambda, NoSymbol, NoSymbol, Greek_LAMBDA, NoSymbol ] }; key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; key { [ h, H, NoSymbol, Greek_psi, NoSymbol, NoSymbol, Greek_PSI, NoSymbol ] }; key { [ a, A, NoSymbol, Greek_alpha, NoSymbol, NoSymbol, U2200, NoSymbol ] }; key { [ e, E, NoSymbol, Greek_epsilon, NoSymbol, NoSymbol, U2203, NoSymbol ] }; key { [ i, I, NoSymbol, Greek_iota, NoSymbol, NoSymbol, integral, NoSymbol ] }; key { [ u, U, NoSymbol, NoSymbol, NoSymbol, NoSymbol, includedin, NoSymbol ] }; key { [ d, D, NoSymbol, Greek_delta, NoSymbol, NoSymbol, Greek_DELTA, NoSymbol ] }; key { [ t, T, NoSymbol, Greek_tau, NoSymbol, NoSymbol, partialderivative, NoSymbol ] }; key { [ r, R, NoSymbol, Greek_rho, NoSymbol, NoSymbol, U211D, NoSymbol ] }; key { [ n, N, NoSymbol, Greek_nu, NoSymbol, NoSymbol, U2115, NoSymbol ] }; key { [ s, S, NoSymbol, Greek_sigma, NoSymbol, NoSymbol, Greek_SIGMA, NoSymbol ] }; key { [ f, F, NoSymbol, Greek_phi, NoSymbol, NoSymbol, Greek_PHI, NoSymbol ] }; key { [ x, X, NoSymbol, Greek_xi, NoSymbol, NoSymbol, Greek_XI, NoSymbol ] }; key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; key { [ adiaeresis, Adiaeresis, NoSymbol, Greek_eta, NoSymbol, NoSymbol, U2135, NoSymbol ] }; key { [ udiaeresis, Udiaeresis, NoSymbol, NoSymbol, NoSymbol, NoSymbol, union, NoSymbol ] }; key { [ odiaeresis, Odiaeresis, NoSymbol, U03F5, NoSymbol, NoSymbol, intersection, NoSymbol ] }; key { [ b, B, NoSymbol, Greek_beta, NoSymbol, NoSymbol, U21D0, NoSymbol ] }; key { [ p, P, NoSymbol, Greek_pi, NoSymbol, NoSymbol, Greek_PI, NoSymbol ] }; key { [ w, W, NoSymbol, Greek_omega, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol ] }; key { [ m, M, NoSymbol, Greek_mu, NoSymbol, NoSymbol, ifonlyif, NoSymbol ] }; key { [ j, J, NoSymbol, Greek_theta, NoSymbol, NoSymbol, Greek_THETA, NoSymbol ] }; }; partial alphanumeric_keys modifier_keys keypad_keys xkb_symbols "koy" { include "de(koy_base)" name[Group1]= "German (KOY)"; include "shift(both_capslock)" include "level3(caps_switch)" include "level3(bksl_switch)" include "level5(lsgt_switch_lock)" include "level5(ralt_switch_lock)" }; partial alphanumeric_keys xkb_symbols "bone_base" { include "de(neo_base)" key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; key { [ comma, endash, NoSymbol, U03F1, NoSymbol, NoSymbol, U21D2, NoSymbol ] }; key { [ period, enfilledcircbullet, NoSymbol, U03D1, NoSymbol, NoSymbol, U21A6, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ j, J, NoSymbol, Greek_theta, NoSymbol, NoSymbol, Greek_THETA, NoSymbol ] }; key { [ d, D, NoSymbol, Greek_delta, NoSymbol, NoSymbol, Greek_DELTA, NoSymbol ] }; key { [ u, U, NoSymbol, NoSymbol, NoSymbol, NoSymbol, includedin, NoSymbol ] }; key { [ a, A, NoSymbol, Greek_alpha, NoSymbol, NoSymbol, U2200, NoSymbol ] }; key { [ x, X, NoSymbol, Greek_xi, NoSymbol, NoSymbol, Greek_XI, NoSymbol ] }; key { [ p, P, NoSymbol, Greek_pi, NoSymbol, NoSymbol, Greek_PI, NoSymbol ] }; key { [ h, H, NoSymbol, Greek_psi, NoSymbol, NoSymbol, Greek_PSI, NoSymbol ] }; key { [ l, L, NoSymbol, Greek_lambda, NoSymbol, NoSymbol, Greek_LAMBDA, NoSymbol ] }; key { [ m, M, NoSymbol, Greek_mu, NoSymbol, NoSymbol, ifonlyif, NoSymbol ] }; key { [ w, W, NoSymbol, Greek_omega, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol ] }; key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; key { [ c, C, NoSymbol, Greek_chi, NoSymbol, NoSymbol, U2102, NoSymbol ] }; key { [ t, T, NoSymbol, Greek_tau, NoSymbol, NoSymbol, partialderivative, NoSymbol ] }; key { [ i, I, NoSymbol, Greek_iota, NoSymbol, NoSymbol, integral, NoSymbol ] }; key { [ e, E, NoSymbol, Greek_epsilon, NoSymbol, NoSymbol, U2203, NoSymbol ] }; key { [ o, O, NoSymbol, Greek_omicron, NoSymbol, NoSymbol, elementof, NoSymbol ] }; key { [ b, B, NoSymbol, Greek_beta, NoSymbol, NoSymbol, U21D0, NoSymbol ] }; key { [ n, N, NoSymbol, Greek_nu, NoSymbol, NoSymbol, U2115, NoSymbol ] }; key { [ r, R, NoSymbol, Greek_rho, NoSymbol, NoSymbol, U211D, NoSymbol ] }; key { [ s, S, NoSymbol, Greek_sigma, NoSymbol, NoSymbol, Greek_SIGMA, NoSymbol ] }; key { [ g, G, NoSymbol, Greek_gamma, NoSymbol, NoSymbol, Greek_GAMMA, NoSymbol ] }; key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; key { [ f, F, NoSymbol, Greek_phi, NoSymbol, NoSymbol, Greek_PHI, NoSymbol ] }; key { [ v, V, NoSymbol, NoSymbol, NoSymbol, NoSymbol, radical, NoSymbol ] }; key { [ udiaeresis, Udiaeresis, NoSymbol, NoSymbol, NoSymbol, NoSymbol, union, NoSymbol ] }; key { [ adiaeresis, Adiaeresis, NoSymbol, Greek_eta, NoSymbol, NoSymbol, U2135, NoSymbol ] }; key { [ odiaeresis, Odiaeresis, NoSymbol, U03F5, NoSymbol, NoSymbol, intersection, NoSymbol ] }; key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; key { [ k, K, NoSymbol, Greek_kappa, NoSymbol, NoSymbol, multiply, NoSymbol ] }; }; partial alphanumeric_keys modifier_keys keypad_keys xkb_symbols "bone" { include "de(bone_base)" name[Group1]= "German (Bone)"; include "shift(both_capslock)" include "level3(caps_switch)" include "level3(bksl_switch)" include "level5(lsgt_switch_lock)" include "level5(ralt_switch_lock)" }; partial alphanumeric_keys xkb_symbols "bone_eszett_home_base" { include "de(bone_base)" key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; }; partial alphanumeric_keys modifier_keys keypad_keys xkb_symbols "bone_eszett_home" { include "de(bone_eszett_home_base)" name[Group1]= "German (Bone, eszett in the home row)"; include "shift(both_capslock)" include "level3(caps_switch)" include "level3(bksl_switch)" include "level5(lsgt_switch_lock)" include "level5(ralt_switch_lock)" }; partial alphanumeric_keys xkb_symbols "neo_qwertz_base" { include "de(neo_base)" key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; key { [ comma, endash, NoSymbol, U03F1, NoSymbol, NoSymbol, U21D2, NoSymbol ] }; key { [ period, enfilledcircbullet, NoSymbol, U03D1, NoSymbol, NoSymbol, U21A6, NoSymbol ] }; key { [ minus, emdash, NoSymbol, U2011, NoSymbol, NoSymbol, hyphen, NoSymbol ] }; key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ ssharp, U1E9E, NoSymbol, Greek_finalsmallsigma, NoSymbol, NoSymbol, jot, NoSymbol ] }; key { [ q, Q, NoSymbol, U03D5, NoSymbol, NoSymbol, U211A, NoSymbol ] }; key { [ w, W, NoSymbol, Greek_omega, NoSymbol, NoSymbol, Greek_OMEGA, NoSymbol ] }; key { [ e, E, NoSymbol, Greek_epsilon, NoSymbol, NoSymbol, U2203, NoSymbol ] }; key { [ r, R, NoSymbol, Greek_rho, NoSymbol, NoSymbol, U211D, NoSymbol ] }; key { [ t, T, NoSymbol, Greek_tau, NoSymbol, NoSymbol, partialderivative, NoSymbol ] }; key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; key { [ u, U, NoSymbol, NoSymbol, NoSymbol, NoSymbol, includedin, NoSymbol ] }; key { [ i, I, NoSymbol, Greek_iota, NoSymbol, NoSymbol, integral, NoSymbol ] }; key { [ o, O, NoSymbol, Greek_omicron, NoSymbol, NoSymbol, elementof, NoSymbol ] }; key { [ p, P, NoSymbol, Greek_pi, NoSymbol, NoSymbol, Greek_PI, NoSymbol ] }; key { [ udiaeresis, Udiaeresis, NoSymbol, NoSymbol, NoSymbol, NoSymbol, union, NoSymbol ] }; key { [ a, A, NoSymbol, Greek_alpha, NoSymbol, NoSymbol, U2200, NoSymbol ] }; key { [ s, S, NoSymbol, Greek_sigma, NoSymbol, NoSymbol, Greek_SIGMA, NoSymbol ] }; key { [ d, D, NoSymbol, Greek_delta, NoSymbol, NoSymbol, Greek_DELTA, NoSymbol ] }; key { [ f, F, NoSymbol, Greek_phi, NoSymbol, NoSymbol, Greek_PHI, NoSymbol ] }; key { [ g, G, NoSymbol, Greek_gamma, NoSymbol, NoSymbol, Greek_GAMMA, NoSymbol ] }; key { [ h, H, NoSymbol, Greek_psi, NoSymbol, NoSymbol, Greek_PSI, NoSymbol ] }; key { [ j, J, NoSymbol, Greek_theta, NoSymbol, NoSymbol, Greek_THETA, NoSymbol ] }; key { [ k, K, NoSymbol, Greek_kappa, NoSymbol, NoSymbol, multiply, NoSymbol ] }; key { [ l, L, NoSymbol, Greek_lambda, NoSymbol, NoSymbol, Greek_LAMBDA, NoSymbol ] }; key { [ odiaeresis, Odiaeresis, NoSymbol, U03F5, NoSymbol, NoSymbol, intersection, NoSymbol ] }; key { [ adiaeresis, Adiaeresis, NoSymbol, Greek_eta, NoSymbol, NoSymbol, U2135, NoSymbol ] }; key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; key { [ x, X, NoSymbol, Greek_xi, NoSymbol, NoSymbol, Greek_XI, NoSymbol ] }; key { [ c, C, NoSymbol, Greek_chi, NoSymbol, NoSymbol, U2102, NoSymbol ] }; key { [ v, V, NoSymbol, NoSymbol, NoSymbol, NoSymbol, radical, NoSymbol ] }; key { [ b, B, NoSymbol, Greek_beta, NoSymbol, NoSymbol, U21D0, NoSymbol ] }; key { [ n, N, NoSymbol, Greek_nu, NoSymbol, NoSymbol, U2115, NoSymbol ] }; key { [ m, M, NoSymbol, Greek_mu, NoSymbol, NoSymbol, ifonlyif, NoSymbol ] }; }; partial alphanumeric_keys modifier_keys keypad_keys xkb_symbols "neo_qwertz" { include "de(neo_qwertz_base)" name[Group1]= "German (Neo, QWERTZ)"; include "shift(both_capslock)" include "level3(caps_switch)" include "level3(bksl_switch)" include "level5(lsgt_switch_lock)" include "level5(ralt_switch_lock)" }; partial alphanumeric_keys xkb_symbols "neo_qwerty_base" { include "de(neo_qwertz_base)" key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; key { [ y, Y, NoSymbol, Greek_upsilon, NoSymbol, NoSymbol, nabla, NoSymbol ] }; key { [ z, Z, NoSymbol, Greek_zeta, NoSymbol, NoSymbol, U2124, NoSymbol ] }; }; partial alphanumeric_keys modifier_keys keypad_keys xkb_symbols "neo_qwerty" { include "de(neo_qwerty_base)" name[Group1]= "German (Neo, QWERTY)"; include "shift(both_capslock)" include "level3(caps_switch)" include "level3(bksl_switch)" include "level5(lsgt_switch_lock)" include "level5(ralt_switch_lock)" }; partial alphanumeric_keys xkb_symbols "lld" { include "de(basic)" name[Group1] = "German (Ladin)"; key { [ p, P, ediaeresis, Ediaeresis ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/empty000066400000000000000000000001441510033435100233230ustar00rootroot00000000000000default partial alphanumeric_keys modifier_keys xkb_symbols "basic" { name[Group1]= "Empty"; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/eurosign000066400000000000000000000011651510033435100240240ustar00rootroot00000000000000// Most keyboards have the EuroSign engraved on the E key partial xkb_symbols "e" { key { [ NoSymbol, NoSymbol, EuroSign, NoSymbol ] }; }; // Many Apple keyboards have the EuroSign engraved on the 2 key partial xkb_symbols "2" { key { [ NoSymbol, NoSymbol, EuroSign, NoSymbol ] }; }; // Some keyboards have the EuroSign engraved on the 4 key partial xkb_symbols "4" { key { [ NoSymbol, NoSymbol, EuroSign, NoSymbol ] }; }; // Many keyboards have the EuroSign engraved on the 5 key partial xkb_symbols "5" { key { [ NoSymbol, NoSymbol, EuroSign, NoSymbol ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/garbage000066400000000000000000000007141510033435100235600ustar00rootroot00000000000000default alphanumeric_keys xkb_symbols "garbage" { include "us" name[Group1]= "My garbage Layout"; // The garbage keysym will *not* override the corresponding symbol from the // 'us' layout key { [ keysym_is_garbage, exclam ] }; // AE13 is unused by 'us', use it to avoid fallback to the 'us' definition. // Define with 2 levels but first level is a garbage symbol. key { [ keysym_is_garbage, asciitilde ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/group000066400000000000000000000321751510033435100233320ustar00rootroot00000000000000// The right Alt key (while pressed) chooses the second keyboard group. partial modifier_keys xkb_symbols "switch" { key { symbols[Group1] = [ Mode_switch, Multi_key ], virtualMods= AltGr }; }; // The left Alt key (while pressed) chooses the second keyboard group. partial modifier_keys xkb_symbols "lswitch" { key { symbols[Group1] = [ Mode_switch, Multi_key ], virtualMods= AltGr }; }; // Either Win key (while pressed) chooses the second keyboard group. partial modifier_keys xkb_symbols "win_switch" { include "group(lwin_switch)" include "group(rwin_switch)" }; // The left Win key (while pressed) chooses the second keyboard group. // (Using this map, you should declare your keyboard as pc101 or pc102 // instead of pc104 or pc105.) partial modifier_keys xkb_symbols "lwin_switch" { key { symbols[Group1] = [ Mode_switch, Multi_key ], virtualMods= AltGr }; }; partial modifier_keys xkb_symbols "lwin_latch" { key { symbols[1] = [ ISO_Group_Latch ], actions[1] = [ LatchGroup(group=+1) ] }; }; // The right Win key (while pressed) chooses the second keyboard group. // (Using this map, you should declare your keyboard as pc101 or pc102 // instead of pc104 or pc105.) partial modifier_keys xkb_symbols "rwin_switch" { key { symbols[Group1] = [ Mode_switch, Multi_key ], virtualMods= AltGr }; }; partial modifier_keys xkb_symbols "rwin_latch_lock_clear" { key { symbols[1] = [ ISO_Group_Latch ], actions[1] = [ LatchGroup(group=+1, latchToLock, clearLocks) ] }; }; // The right Menu key (while pressed) chooses the second keyboard group. // while Shift+Menu acts as Menu. partial modifier_keys xkb_symbols "menu_switch" { key { symbols[Group1] = [ Mode_switch, Menu ], virtualMods= AltGr }; }; // The right Ctrl key (while pressed) chooses the second keyboard group. // (Needed mainly for the Canadian keyboard.) partial modifier_keys xkb_symbols "rctrl_switch" { key { symbols[Group1] = [ Mode_switch ] }; }; // Pressing the right Alt key switches to the next group. partial modifier_keys xkb_symbols "toggle" { virtual_modifiers AltGr; key { symbols[Group1] = [ ISO_Next_Group ], virtualMods= AltGr }; }; // Pressing both Shift keys switches to the next or previous group // (depending on which Shift is pressed first). partial modifier_keys xkb_symbols "shifts_toggle" { key { [ Shift_L, ISO_Prev_Group ] }; key { [ Shift_R, ISO_Next_Group ] }; }; // Pressing Shift+Caps_Lock switches to the next group. partial modifier_keys xkb_symbols "shift_caps_toggle" { key { [ Caps_Lock, ISO_Next_Group ] }; }; // Pressing Caps_Lock selects the first group, // pressing Shift+Caps_Lock selects the last group. partial modifier_keys xkb_symbols "shift_caps_switch" { key { [ ISO_First_Group, ISO_Last_Group ] }; }; // toggle using win + space as combo partial modifier_keys xkb_symbols "win_space_toggle" { key { type="PC_SUPER_LEVEL2", symbols[Group1]= [ space, ISO_Next_Group ], symbols[Group2]= [ space, ISO_Next_Group ] }; }; // Pressing the left Win key selects the first group, // pressing the right Win or the Menu key selects the last group. partial modifier_keys xkb_symbols "win_menu_switch" { virtual_modifiers AltGr; key { virtualMods= AltGr, symbols[Group1] = [ ISO_First_Group ] }; key { virtualMods= AltGr, symbols[Group1] = [ ISO_Last_Group ] }; key { virtualMods= AltGr, symbols[Group1] = [ ISO_Last_Group ] }; }; // Pressing the left Ctrl key selects the first group, // pressing the right Ctrl key selects the last group. partial modifier_keys xkb_symbols "lctrl_rctrl_switch" { virtual_modifiers AltGr; key { virtualMods= AltGr, symbols[Group1] = [ ISO_First_Group ] }; key { virtualMods= AltGr, symbols[Group1] = [ ISO_Last_Group ] }; }; // // CTRL-SHIFT toggle section // partial modifier_keys xkb_symbols "lctrl_lshift_toggle" { key { type[Group1]="PC_CONTROL_LEVEL2", symbols[Group1] = [ Shift_L, ISO_Next_Group ] }; key { [ Control_L, ISO_Next_Group ] }; }; partial modifier_keys xkb_symbols "lctrl_lshift_toggle_rev" { key { type[Group1]="PC_CONTROL_LEVEL2", symbols[Group1] = [ Shift_L, ISO_Prev_Group ] }; key { [ Control_L, ISO_Prev_Group ] }; }; partial modifier_keys xkb_symbols "rctrl_rshift_toggle" { key { type[Group1]="PC_CONTROL_LEVEL2", symbols[Group1] = [ Shift_R, ISO_Next_Group ] }; key { [ Control_R, ISO_Next_Group ] }; }; partial modifier_keys xkb_symbols "ctrl_shift_toggle" { include "group(lctrl_lshift_toggle)" include "group(rctrl_rshift_toggle)" }; partial modifier_keys xkb_symbols "ctrl_shift_toggle_bidir" { include "group(lctrl_lshift_toggle_rev)" include "group(rctrl_rshift_toggle)" }; // // CTRL-ALT toggle section // partial modifier_keys xkb_symbols "lctrl_lalt_toggle" { virtual_modifiers Alt; key { type[Group1]="PC_CONTROL_LEVEL2", symbols[Group1] = [ NoSymbol, ISO_Next_Group ], virtualMods= Alt }; key { type[Group1]="PC_ALT_LEVEL2", symbols[Group1] = [ Control_L, ISO_Next_Group ] }; }; partial modifier_keys xkb_symbols "lctrl_lalt_toggle_rev" { virtual_modifiers Alt; key { type[Group1]="PC_CONTROL_LEVEL2", symbols[Group1] = [ NoSymbol, ISO_Prev_Group ], virtualMods= Alt }; key { type[Group1]="PC_ALT_LEVEL2", symbols[Group1] = [ Control_L, ISO_Prev_Group ] }; }; partial modifier_keys xkb_symbols "rctrl_ralt_toggle" { virtual_modifiers Alt; key { type[Group1]="PC_CONTROL_LEVEL2", symbols[Group1] = [ NoSymbol, ISO_Next_Group ], virtualMods= Alt }; key { type[Group1]="PC_ALT_LEVEL2", symbols[Group1] = [ Control_R, ISO_Next_Group ] }; }; partial modifier_keys xkb_symbols "ctrl_alt_toggle" { include "group(lctrl_lalt_toggle)" include "group(rctrl_ralt_toggle)" }; partial modifier_keys xkb_symbols "ctrl_alt_toggle_bidir" { include "group(lctrl_lalt_toggle_rev)" include "group(rctrl_ralt_toggle)" }; // // ALT-SHIFT toggle section // partial modifier_keys xkb_symbols "lalt_lshift_toggle" { virtual_modifiers Alt; key { symbols[Group1] = [ NoSymbol, ISO_Next_Group ], virtualMods= Alt }; key { type[Group1]="PC_ALT_LEVEL2", symbols[Group1] = [ Shift_L, ISO_Next_Group ] }; }; partial modifier_keys xkb_symbols "lalt_lshift_toggle_rev" { virtual_modifiers Alt; key { symbols[Group1] = [ NoSymbol, ISO_Prev_Group ], virtualMods= Alt }; key { type[Group1]="PC_ALT_LEVEL2", symbols[Group1] = [ Shift_L, ISO_Prev_Group ] }; }; partial modifier_keys xkb_symbols "ralt_rshift_toggle" { virtual_modifiers Alt; key { symbols[Group1] = [ NoSymbol, ISO_Next_Group ], virtualMods= Alt }; key { type[Group1]="PC_ALT_LEVEL2", symbols[Group1] = [ Shift_R, ISO_Next_Group ] }; }; partial modifier_keys xkb_symbols "alt_shift_toggle" { include "group(lalt_lshift_toggle)" include "group(ralt_rshift_toggle)" }; partial modifier_keys xkb_symbols "alt_shift_toggle_bidir" { include "group(lalt_lshift_toggle_rev)" include "group(ralt_rshift_toggle)" }; // Pressing the Menu key switches to the next group, // while Shift+Menu acts as Menu. partial modifier_keys xkb_symbols "menu_toggle" { key { [ ISO_Next_Group, Menu ] }; }; // Pressing the left Win key switches to the next group. // (Using this map, you should declare your keyboard as // pc101 or pc102 instead of pc104 or pc105.) partial modifier_keys xkb_symbols "lwin_toggle" { virtual_modifiers AltGr; key { virtualMods= AltGr, symbols[Group1] = [ ISO_Next_Group ] }; }; // Pressing the right Win key switches to the next group. // (Using this map, you should declare your keyboard as // pc101 or pc102 instead of pc104 or pc105.) partial modifier_keys xkb_symbols "rwin_toggle" { virtual_modifiers AltGr; key { virtualMods= AltGr, symbols[Group1] = [ ISO_Next_Group ] }; }; // Pressing both Ctrl keys switches to the next or previous group // (depending on which Ctrl is pressed first). partial modifier_keys xkb_symbols "ctrls_toggle" { virtual_modifiers LControl, RControl; key { type[Group1]="PC_CONTROL_LEVEL2", symbols[Group1] = [ NoSymbol, ISO_Prev_Group ], virtualMods= LControl }; key { type[Group1]="PC_CONTROL_LEVEL2", symbols[Group1] = [ NoSymbol, ISO_Next_Group ], virtualMods= RControl }; }; // Pressing both Alt switches to the next or previous group // (depending on which Alt is pressed first). partial modifier_keys xkb_symbols "alts_toggle" { virtual_modifiers LAlt, RAlt; key { type[Group1]="PC_RALT_LEVEL2", symbols[Group1] = [ NoSymbol, ISO_Prev_Group ], virtualMods= LAlt }; key { type[Group1]="PC_LALT_LEVEL2", symbols[Group1] = [ NoSymbol, ISO_Next_Group ], virtualMods= RAlt }; }; // Pressing the left Shift key switches to the next group. partial modifier_keys xkb_symbols "lshift_toggle" { virtual_modifiers AltGr; key { symbols[Group1] = [ ISO_Next_Group ], virtualMods= AltGr }; }; // Pressing the right Shift key switches to the next group. partial modifier_keys xkb_symbols "rshift_toggle" { virtual_modifiers AltGr; key { symbols[Group1] = [ ISO_Next_Group ], virtualMods= AltGr }; }; // Pressing the left Alt key switches to the next group. partial modifier_keys xkb_symbols "lalt_toggle" { virtual_modifiers AltGr; key { symbols[Group1] = [ ISO_Next_Group ], virtualMods= AltGr }; }; // Pressing the left Ctrl key switches to the next group. partial modifier_keys xkb_symbols "lctrl_toggle" { virtual_modifiers AltGr; key { symbols[Group1] = [ ISO_Next_Group ], virtualMods= AltGr }; }; xkb_symbols "rctrl_toggle" { virtual_modifiers AltGr; key { symbols[Group1] = [ ISO_Next_Group ], virtualMods= AltGr }; }; // Pressing Alt+Caps_Lock switches to the next group, // pressing Caps_Lock toggles CapsLock. partial modifier_keys xkb_symbols "alt_caps_toggle" { key { type="PC_ALT_LEVEL2", symbols[Group1] = [ Caps_Lock, ISO_Next_Group ] }; }; hidden partial modifier_keys xkb_symbols "olpc" { key { [ ISO_Next_Group, ISO_Prev_Group ] }; }; partial modifier_keys xkb_symbols "alt_space_toggle" { key { type[Group1]="PC_ALT_LEVEL2", symbols[Group1] = [ space, ISO_Next_Group ] }; }; // Pressing the Scroll Lock key switches to the next group, partial modifier_keys xkb_symbols "sclk_toggle" { virtual_modifiers AltGr; key { virtualMods= AltGr, symbols[Group1] = [ ISO_Next_Group ] }; }; partial modifier_keys xkb_symbols "sclk_latch_no_lock" { virtual_modifiers AltGr; key { symbols[Group1] = [ ISO_Group_Latch ], actions[Group1] = [ LatchGroup(group=+1,!latchToLock,!clearLocks) ] }; }; // Control_L+Win_L selects the first group (presumably Lat), // Control_R+Menu selects the second group (presumably Rus). partial modifier_keys xkb_symbols "lctrl_lwin_rctrl_menu" { key { type[Group1] = "PC_CONTROL_LEVEL2", symbols[Group1] = [ Super_L, ISO_First_Group ] }; key { type[Group1] = "PC_CONTROL_LEVEL2", symbols[Group1] = [ Menu, ISO_Last_Group ] }; }; // Control_L+Win_L toggles groups. partial modifier_keys xkb_symbols "lctrl_lwin_toggle" { key { type[ Group1 ] = "PC_CONTROL_LEVEL2", symbols[ Group1 ] = [ Super_L, ISO_Next_Group ] }; }; partial modifier_keys xkb_symbols "menu_latch_group2" { key { symbols[1] = [ ISO_Group_Latch ], actions[1] = [ LatchGroup(group=2) ] }; }; partial modifier_keys xkb_symbols "menu_latch_group2_lock" { key { symbols[1] = [ ISO_Group_Latch ], actions[1] = [ LatchGroup(group=2, latchToLock=yes) ] }; }; partial modifier_keys xkb_symbols "menu_latch" { key { symbols[1] = [ ISO_Group_Latch ], actions[1] = [ LatchGroup(group=+1) ] }; }; partial modifier_keys xkb_symbols "menu_latch_lock" { key { symbols[1] = [ ISO_Group_Latch ], actions[1] = [ LatchGroup(group=+1, latchToLock=yes) ] }; }; partial modifier_keys xkb_symbols "menu_latch_negative" { key { symbols[1] = [ ISO_Group_Latch ], actions[1] = [ LatchGroup(group=-1) ] }; }; partial modifier_keys xkb_symbols "menu_latch_negative_lock" { key { symbols[1] = [ ISO_Group_Latch ], actions[1] = [ LatchGroup(group=-1, latchToLock=yes) ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/il000066400000000000000000000375731510033435100226110ustar00rootroot00000000000000// based on a keyboard map from an 'xkb/symbols/il' file // This is an implemetation of the Israeli standard SI-1452 (2013) // It does not implement changes to the English layout, as that part // of the standard is not normative nor really useful in the context // of xkb. // This implementation extends the standard with Yiddish digraphs // (a common extension) and Nun Hafukha (a fun character). default partial alphanumeric_keys xkb_symbols "basic" { // uses the kbd layout in use in Israel. name[Group1]= "Hebrew"; key.type[Group1] = "FOUR_LEVEL_SEMIALPHABETIC"; key { [ hebrew_zain, Z ] }; key { [ hebrew_samech, X, U05B6 ] }; // Segol key { [ hebrew_bet, C, U05B1 ] }; // Hataf Segol key { [ hebrew_he, V ] }; key { [ hebrew_nun, B, NoSymbol, U05C6 ]}; // Nun Hafukha key { [ hebrew_mem, N ] }; key { [ hebrew_zade, M, U05B5 ] }; // Tsere key { [ hebrew_taw, greater, rightsinglequotemark ]}; // greater Mirrored key { [ hebrew_finalzade, less, singlelowquotemark ]}; // less Mirrored key { [ hebrew_shin, A, U05B0 ] }; // Shva key { [ hebrew_dalet,S, U05BC ] }; // Dagesh key { [ hebrew_gimel,D ] }; key { [ hebrew_kaph, F ] }; key { [ hebrew_ayin, G, U05F1 ] }; // Yiddish Vav Yod key { [ hebrew_yod, H, U05F2 ] }; // Yiddish Double Yod key { [ hebrew_chet, J, U05B4 ] }; // Hiriq key { [ hebrew_lamed, K ] }; key { [ hebrew_finalkaph, L, rightdoublequotemark ]}; key { [ hebrew_finalpe, colon, doublelowquotemark ]}; key { [ slash, Q, U05C2 ] }; // Sin Dot key { [ apostrophe, W, U05C1 ] }; // Shin Dot key { [ hebrew_qoph, E, U05B8 ] }; // Qamats key { [ hebrew_resh, R, U05B3 ] }; // Hataf Qamats key { [ hebrew_aleph,T ] }; key { [ hebrew_tet, Y, U05F0 ] }; // Yiddish Double Vav key { [ hebrew_waw, U, U05B9 ] }; // Holam key { [ hebrew_finalnun, I ] }; key { [ hebrew_finalmem, O ] }; key { [ hebrew_pe, P, U05B7 ] }; // Patah key.type[Group1] = "FOUR_LEVEL"; // Non-alphanumeric keys key { [ period, question, division ]}; key { [ comma, quotedbl, U05F4] }; // Gershayim key { [ bracketright, braceright, U05B2 ]}; // Mirrored; Hataf Patah key { [ bracketleft, braceleft, U05BF ]}; // Mirrored; Rafe key { [ backslash, bar, U05BB ] }; // Qubuts // Top (digits) row key { [ semicolon, asciitilde, U05F3 ]}; // Geresh key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign, EuroSign ]}; key { [ 4, dollar, NewSheqelSign ]}; key { [ 5, percent, degree ]}; key { [ 6, asciicircum, U05AB ]}; // Hebrew Accent Ole key { [ 7, ampersand, U05BD ]}; // Meteg key { [ 8, asterisk, multiply]}; key { [ 9, parenright, U200E ]}; // LRM; Paren Mirrored key { [ 0, parenleft, U200F ]}; // RLM; Paren Mirrored key { [ minus, underscore, U05BE ]}; // Maqaf key { [ equal, plus, endash ]}; include "level3(ralt_switch)" }; // nikud patter based on Dekel Tsur's Hebrew mapping for LyX partial alphanumeric_keys xkb_symbols "lyx" { name[Group1]= "Hebrew (lyx)"; key { [ semicolon, asciitilde ] }; // On some key (e.g. AD01, right below) there is not yet mapping for the // second shift level. Since I could not figure a simple way to map this // to "emit nothing", it is currently mapped to the same letter of the // first shift level (avoiding mapping may risk it be used by a character // from a different group). key { [ slash, slash ] }; key { [ apostrophe, apostrophe ] }; key { [ hebrew_qoph, 0x10005b8 ] }; // Qamats key { [ hebrew_resh, 0x10005bc ] }; // Dagesh/Shuruq key { [ hebrew_aleph, 0x100200e ] }; // LRM key { [ hebrew_tet, 0x100200f ] }; // RLM key { [ hebrew_waw, 0x10005b9 ] }; // Holam key { [ hebrew_finalnun,hebrew_finalnun] }; key { [ hebrew_finalmem,hebrew_finalmem] }; key { [ hebrew_pe, 0x10005b7 ] }; // Patah key { [ hebrew_shin, 0x10005b0 ] }; // Sheva key { [ hebrew_dalet, 0x10005bc ] }; // Dagesh/Shuruq key { [ hebrew_gimel, hebrew_gimel ] }; key { [ hebrew_kaph, hebrew_kaph ] }; key { [ hebrew_ayin, 0x10005c2 ] }; // Sin dot key { [ hebrew_yod, 0x10005c1 ] }; // Shin dot key { [ hebrew_chet, 0x10005b4 ] }; // Hiriq key { [ hebrew_lamed, 0x10020aa ] }; // NIS key { [ hebrew_finalkaph,hebrew_finalkaph] }; key { [ hebrew_finalpe, colon ] }; key { [ comma, quotedbl ] }; key { [ hebrew_zain, hebrew_zain ] }; key { [ hebrew_samech,0x10005b6 ] }; // Segol key { [ hebrew_bet, 0x10005bb ] }; // Qubuts key { [ hebrew_he, 0x10005b1 ] }; // H. Segol key { [ hebrew_nun, 0x10005b2 ] }; // H. Patah key { [ hebrew_mem, 0x10005b3 ] }; // H. Qamats key { [ hebrew_zade, 0x10005b5 ] }; // Tsere key { [ hebrew_taw, greater ] }; key { [ hebrew_finalzade, less ] }; key { [ period, question ] }; // Note the parens mirroring below: key { [ bracketright, braceright ] }; key { [ bracketleft, braceleft ] }; key { [ 1, exclam ]}; key { [ 2, at ]}; key { [ 3, numbersign ]}; key { [ 4, dollar ]}; key { [ 5, percent ]}; key { [ 6, asciicircum ]}; key { [ 7, ampersand ]}; key { [ 8, asterisk ]}; key { [ 9, parenright ]}; key { [ 0, parenleft ]}; key { [ minus , 0x10005be ] }; // H. Hiphen key { [ equal , plus ] }; }; partial alphanumeric_keys xkb_symbols "phonetic" { // uses the phonetic layout from old Slackware 'il.map' file name[Group1]= "Hebrew (phonetic)"; key { [ equal, plus, hebrew_doublelowline, hebrew_doublelowline ]}; key { [ hebrew_qoph, hebrew_qoph ] }; key { [ hebrew_waw, hebrew_waw ] }; key { [ hebrew_aleph, hebrew_aleph ] }; key { [ hebrew_resh, hebrew_resh ] }; key { [ hebrew_taw, hebrew_tet ] }; key { [ hebrew_ayin, hebrew_ayin ] }; key { [ hebrew_waw, hebrew_waw ] }; key { [ hebrew_yod, hebrew_yod ] }; key { [ hebrew_samech, hebrew_samech ] }; key { [ hebrew_pe, hebrew_finalpe ] }; key { [ hebrew_aleph, hebrew_aleph ] }; key { [ hebrew_shin, hebrew_shin ] }; key { [ hebrew_dalet, hebrew_dalet ] }; key { [ hebrew_pe, hebrew_finalpe ] }; key { [ hebrew_gimel, hebrew_gimel ] }; key { [ hebrew_he, hebrew_he ] }; key { [ hebrew_yod, hebrew_yod ] }; key { [ hebrew_kaph, hebrew_finalkaph ] }; key { [ hebrew_lamed, hebrew_lamed ] }; key { [ hebrew_zain, hebrew_zain ] }; key { [ hebrew_chet, hebrew_chet ] }; key { [ hebrew_zade, hebrew_finalzade ] }; key { [ hebrew_waw, hebrew_waw ] }; key { [ hebrew_bet, hebrew_bet ] }; key { [ hebrew_nun, hebrew_finalnun ] }; key { [ hebrew_mem, hebrew_finalmem ] }; }; // The 'Biblical Hebrew' keyboard layout as defined by Tiro for use with the // 'SBL Hebrew' font was added 2006.11.13 by Sebastian J. Bronner // . Its primary features (as compared to the lyx layout) // are that the consonants are in the Israeli standard positions, that a great // multitude of glyphs can be input directly from the keyboard, and that it is // the closest thing to a standard layout a theologian can hope for. // Documentation (including printable keyboard tables), SBL Hebrew font, and // keyboard layout for Windows are available at // http://www.sbl-site.org/Resources/Resources_BiblicalFonts.aspx. // // It is of interest that the 'basic' layout defined first in this file (as // ships with x.org disagrees in the non-consonant characters that the Tiro- // layout claims to be the Israeli standard. Tiros apparent diligence in the // PDF-documentation accompanying the keyboard-layout-files lead me to put // greater stock in their claim than in this file. Therefore, the 'biblical' // layout below does not include 'il(basic)' but redoes the _whole_ thing from // scratch. partial alphanumeric_keys xkb_symbols "biblical" { name[Group1]= "Hebrew (Biblical, Tiro)"; key.type = "FOUR_LEVEL_SEMIALPHABETIC"; key { [ U05C3, U05AE, semicolon, asciitilde ] }; key { [ 1, U05A9, VoidSymbol, exclam ] }; key { [ 2, U0599, VoidSymbol, at ] }; key { [ 3, U0592, VoidSymbol, numbersign ] }; key { [ 4, U05AF, NewSheqelSign, dollar ] }; key { [ 5, U05BA, U200D, percent ] }; key { [ 6, U05B9, U200C, asciicircum ] }; key { [ 7, U05BF, U034F, ampersand ] }; key { [ 8, U05C2, U200E, asterisk ] }; key { [ 9, U05C1, U200F, parenright ] }; key { [ 0, U059D, U25CC, parenleft ] }; key { [ U05BE, U05A0, minus, underscore ] }; key { [ equal, U05BC, VoidSymbol, plus ] }; key { [ U0307, U05C4, U0308, slash ] }; key { [ U05F3, U05AC, U05F4, apostrophe ] }; key { [ hebrew_qoph, U05AB, U20AC ] }; key { [ hebrew_resh, U059F ] }; key { [ hebrew_aleph, U0593 ] }; key { [ hebrew_tet, U059E ] }; key { [ hebrew_waw, U059C, U05F0 ] }; key { [ hebrew_finalnun, U05A1 ] }; key { [ hebrew_finalmem, U0595 ] }; key { [ hebrew_pe, U0594 ] }; key { [ bracketright, U0597, VoidSymbol, braceright ] }; key { [ bracketleft, U0598, VoidSymbol, braceleft ] }; key { [ U05C0, U05A8, backslash, bar ] }; key { [ hebrew_shin, U05BD ] }; key { [ hebrew_dalet, U05B0 ] }; key { [ hebrew_gimel, U05BB ] }; key { [ hebrew_kaph, U05B4 ] }; key { [ hebrew_ayin, U05B1 ] }; key { [ hebrew_yod, U05B6, U05F2 ] }; key { [ hebrew_chet, U05B5, U05F1 ] }; key { [ hebrew_lamed, U05B3 ] }; key { [ hebrew_finalkaph, U05B8, U05C7 ] }; key { [ hebrew_finalpe, U05B2, VoidSymbol, colon ] }; key { [ U059a, U05B7, comma, quotedbl ] }; key { [ hebrew_zain, U05C5 ] }; key { [ hebrew_samech, U05A4 ] }; key { [ hebrew_bet, U05AA, U05A2 ] }; key { [ hebrew_he, U05A6 ] }; key { [ hebrew_nun, U05A5, U05C6 ] }; key { [ hebrew_mem, U05A7 ] }; key { [ hebrew_zade, U059B ] }; key { [ hebrew_taw, U0591, VoidSymbol, greater ] }; key { [ hebrew_finalzade, U0596, VoidSymbol, less ] }; key { [ U05AD, U05A3, period, question ] }; key { [ space, space, thinspace, nobreakspace ] }; }; // EXTRAS // Biblical hebrew (SIL) US Standard layout version 1.5 // This map is based closely on v 1.5 of the standard. The only deviation being the replacement of the composite characters sin and shin // by their more recent Unicodev6 counterparts // this map contains all the characters found in Biblical annotation, masoretic and Dead Sea Scroll related work. // The layout corresponds phonetically to a US standard layout or similar (Qwerty). // If you are using an actual Hebrew keyboard, you are probably better off using a Tiro compliant scholarly layout // This linux port created and maintained by Dennis Meulensteen, dennis@meulensteen.nl partial alphanumeric_keys xkb_symbols "biblicalSIL" { name[Group1]= "Hebrew (Biblical, SIL phonetic)"; key.type = "FOUR_LEVEL_SEMIALPHABETIC"; key { [ U20AC, U20AA, U0024 ] }; //Euro, Shekel, Dollar - key { [ 1, U0021, U05BD, U0597 ] }; //1, exclamation meteg revia key { [ 2, U0598, U05A2, U05AE ] }; //2, zarqa atn. hafukh zinor key { [ 3, U05A8, U0596, U0599 ] }; //3, qadma tipeha pashta key { [ 4, U059C, U05A5, U05A0 ] }; //4, geresh merkha tel. gedola key { [ 5, U059E, U05A6, U05A9 ] }; //5, gershayim mer. kefula tel qetana key { [ 6, VoidSymbol, U05AD, U059F ] }; //6, - dehi qar. para key { [ 7, U05AC, U05A3, U05A1 ] }; //7, iluy munah pazer key { [ 8, U059D, U059B, U0595 ] }; //8, g. muqdam tevir zaq. gadol key { [ 9, U0029, U05A7, U0593 ] }; //9, parenth.R darqa shalshelet key { [ 0, U0028, U05AA, U05AF ] }; //0, paren.L yer. ben yomo masora c. key { [ U05BE, U2013, U2014, U05BF ] }; //Maqaf, en dash em dash rafe key { [ U05BC, VoidSymbol, U0591, U25CC ] }; //Dagesh - etnahta mark base key { [ hebrew_qoph, U0597 ] }; //Qof revia - - key { [ hebrew_waw] }; //waw - - - key { [ U05B6, U05B5, VoidSymbol, U05B1 ] }; //segol tsere - hat. segol key { [ hebrew_resh ] }; //resh - - - key { [ hebrew_taw ] }; //taw - - - key { [ hebrew_yod, U059F ] }; //jod qar. para - - key { [ U05BB] }; //quibuts - - - key { [ U05B4 ] }; //hiriq, - - - key { [ U05B9, U05BA, U05C7, U05B3 ] }; //holam, holam(wav) qam. qatan hat. Qamats key { [ hebrew_pe, hebrew_finalpe, VoidSymbol, U034F ] }; //pe final pe - c. grapheme joiner key { [ bracketright, braceright, VoidSymbol, U0594 ] }; //Bracket R brace R - zaq. qatan key { [ bracketleft, braceleft, U059A, U0592 ] }; //Brachket L brace L yetiv segolta key { [ U05C0, U05C0, U05A4, U05AB ] };//Paseq Paseq mahapakh ole key { [ U05B7, U05B8, U05C7, U05B2 ] }; //patah Qamats Qam. Qatan hat. patah key { [ hebrew_samech, U05E9 ] }; //Samech, shin no dot - - key { [ hebrew_dalet ] }; //dalet - - - key { [ UFB2B, hebrew_shin, U05C2 ] }; //UCSv6 Sin shin (nodot) sindot - key { [ hebrew_gimel, VoidSymbol, U25E6, U2022 ] }; //gimel - bullet(DSS) bulletfill (DSS) key { [ hebrew_he, VoidSymbol, U0336, U030A ] };//he - strikeout(DSS) Ring Above(DSS) key { [ UFB2A, hebrew_shin, U05C1] }; //UCSv6 Shin shin (nodot) shindot - key { [ hebrew_kaph, hebrew_finalkaph ] }; //kaph Final kaph - key { [ hebrew_lamed, VoidSymbol ] }; //lamed - - key { [ U05B0, U05F4, semicolon, U05C3 ] }; //sva gers. p semicolon sof pasuq key { [ U2019, U201D, U0323, U05C4 ] };//QuoteRight double R Quote punctum punctum Above key { [ hebrew_zain ] }; //Zayin - - key { [ hebrew_chet ] }; //chet - - key { [ hebrew_zade, U05E5 ] }; // tzade, final tzade - key { [ hebrew_tet ] }; //tet - - key { [ hebrew_bet ] }; //bet - - key { [ hebrew_nun, hebrew_finalnun ] }; //nun, final nun key { [ hebrew_mem, hebrew_finalmem, U200C, U200D ] }; //mem, final mem 0.wid.non.join. 0.wid.joiner key { [ U002C, U05E2, U00AB, U0307 ] }; //comma, ayin guillemetsR masora dot key { [ U0002E, U05D0, U00BB, U0308 ] }; //period, alef guillemetsL thousands key { [ slash, question, U05F3 ] }; //slash question geresh P key { [ space, space, thinspace, nobreakspace ] };//space space thin space, nbsp }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/in000066400000000000000000003150441510033435100226030ustar00rootroot00000000000000// This layout includes all Indian layouts, including: // - Hindi // - Marathi // - Sanskrit // - Bangla // - Gujarati // - Kannada // - Malayalam // - Ol Chiki // - Oriya // - Tamil // - Telugu // - Urdu // Links: // - Indic INSCRIPT keyboard layout diagrams: // http://java.sun.com/products/jfc/tsc/articles/InputMethod/indiclayout.html // - Bangla Baishakhi (Bangla layouts): // - Bangla Baishakhi Inscript (Bangla layouts): // - Bangla Bornona (Bangla layouts): // - Uni Gitanjali (Bangla layouts): // http://nltr.org // - Ekusheyr Shadhinota (Bangla layouts): // http://ekushey.org/projects/shadhinota/index.html // - Microsoft Windows XP SP2: Indic Language Standards - an Introduction: // http://www.bhashaindia.com/MSProducts/XpSp2/Articles/IndicLanguageStandards.aspx // - Ol Chiki: // http://www.unicode.org/L2/L2005/05243r-n2984-ol-chiki.pdf (fig. 9) // based on a keyboard map from an 'xkb/symbols/dev' file // Devangari is the default. Kill me if I am wrong:) default partial alphanumeric_keys xkb_symbols "deva" { // March 2004 -- David Holl name[Group1]="Indian"; key.type="FOUR_LEVEL"; key { [ U094a, U0912, grave, asciitilde ] }; key { [ U0967, U090d, 1, exclam ] }; key { [ U0968, U0945, 2, at ] }; // Shift+AE0[3-8] really need to return a macro of keys defined by // INSCRIPT in place of the symbols that are here for now. But this // requires XKB to map 1 key into two to three other key presses. key { [ U0969, numbersign, 3, numbersign ] }; key { [ U096a, dollar, 4 ] }; key { [ U096b, percent, 5, percent ] }; key { [ U096c, asciicircum, 6, asciicircum ] }; key { [ U096d, ampersand, 7, ampersand ] }; key { [ U096e, asterisk, 8, asterisk ] }; key { [ U096f, parenleft, 9, parenleft ] }; key { [ U0966, parenright, 0, parenright ] }; key { [ minus, U0903, minus, underscore ] }; key { [ U0943, U090b, U0944, U0960 ] }; key { [ U094c, U0914 ] }; key { [ U0948, U0910 ] }; key { [ U093e, U0906 ] }; key { [ U0940, U0908, U0963, U0961 ] }; key { [ U0942, U090a ] }; key { [ U092c, U092d ] }; key { [ U0939, U0919 ] }; key { [ U0917, U0918, U095a ] }; key { [ U0926, U0927 ] }; key { [ U091c, U091d, U095b ] }; key { [ U0921, U0922, U095c, U095d ] }; key { [ U093c, U091e ] }; // I added \ / ? | for shell-convenience (file names and piping) key { [ U0949, U0911, U005C, U007C ] }; key { [ U094b, U0913 ] }; key { [ U0947, U090f ] }; key { [ U094d, U0905 ] }; key { [ U093f, U0907, U0962, U090c ] }; key { [ U0941, U0909 ] }; key { [ U092a, U092b, NoSymbol, U095e ] }; key { [ U0930, U0931 ] }; key { [ U0915, U0916, U0958, U0959 ] }; key { [ U0924, U0925 ] }; key { [ U091a, U091b, U0952 ] }; key { [ U091f, U0920, NoSymbol, U0951 ] }; key { [ U0946, U090e, U0953 ] }; key { [ U0902, U0901, NoSymbol, U0950 ] }; key { [ U092e, U0923, U0954 ] }; key { [ U0928, U0929 ] }; key { [ U0935, U0934 ] }; key { [ U0932, U0933 ] }; key { [ U0938, U0936 ] }; key { [ comma, U0937, U0970 ] }; key { [ period, U0964, U0965, U093d ] }; // I added \ / ? | for shell-convenience (file names and piping) key { [ U092f, U095f, slash, question ] }; // space, space, Zero-Width-Non-Joiner (ZWNJ), Zero-Width-Joiner (ZWJ): include "nbsp(zwnj3zwj4)" include "rupeesign(4)" include "level3(ralt_switch)" }; //Name : Bolnagri (Combined) //Description : A phonetic keyboard layout for Devnagari(Hindi) // http://www.indlinux.org/wiki/index.php/BolNagri //NOTE : This is a combined map of bolnagri_matras and bolnagri_vowels. //Inspired by "devrom" keymap by Steve Smith for the windows tool "keyman" //Original Author : Noah Levitt //Past Authors : Pramod.R and Ravikant //Current Main. : G Karunakar partial alphanumeric_keys xkb_symbols "bolnagri" { name[Group1] = "Hindi (Bolnagri)"; key.type="FOUR_LEVEL"; // Roman digits key { [ U0902, U0901, apostrophe, asciitilde ] }; // apostrophe: anusvara, candrabindu key { [ 1, exclam, U0967, exclam ] }; key { [ 2, at, U0968, at ] }; key { [ 3, numbersign, U0969, numbersign ] }; key { [ 4, dollar, U096A ] }; // Rupee symbol on AltGr+4 key { [ 5, percent, U096B, percent ] }; key { [ 6, asciicircum, U096C, asciicircum ] }; key { [ 7, ampersand, U096D, ampersand ] }; key { [ 8, asterisk, U096E, asterisk ] }; key { [ 9, parenleft, U096F, parenleft ] }; key { [ 0, parenright, U0966, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ U0964, U0965, U007C, U005C ] }; //pipe : danda, double danda //Q Row key { [ U200C, U200D ] }; // Q: ZWNJ, ZWJ key { [ U0935, U950 ] }; // W: wa, OM key { [ U0947, U0948, U090F, U0910 ] }; // E: e, ai matras key { [ U0930, U0943, U0931, U090B ] }; // R: ra, vocalic Ri key { [ U0924, U0925 ] }; // T: ta, tha key { [ U092f, U091E ] }; // Y: ya, nya key { [ U0941, U0942, U0909, U090A ] }; // U: u, uu matras key { [ U093F, U0940, U0907, U0908 ] }; // I: i, ii matras key { [ U094B, U094C, U0913, U0914 ] }; // O: o, au matras key { [ U092A, U092B ] }; // P: pa, pha key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; //A Row key { [ U093E, U0906, U0905, U0906 ] }; // A: aa, full A, AA key { [ U0938, U0937 ] }; // S: sa, ssa key { [ U0926, U0927 ] }; // D: da, dha key { [ U091F, U0920 ] }; // F: TA, THA key { [ U0917, U0918 ] }; // G: ga, gha key { [ U0939, U0903 ] }; // H: ha, visarg key { [ U091C, U091D ] }; // J: ja, jha key { [ U0915, U0916 ] }; // K: ka, kha key { [ U0932, U0933, U0962, U090C ] }; // L: la, vocalic L or lru matra key { [ semicolon, colon ] }; key { [apostrophe, quotedbl ] }; //Z Row key { [ U0936, U0945, U0936, U090D ] }; // Z: sha, akaar candra key { [ U094D, U0949, U094D, U0911 ] }; // X: halant, aakaar candra, chandra A key { [ U091A, U091B ] }; // C: ca, cha key { [ U0921, U0922 ] }; // V: da, dha key { [ U092C, U092D ] }; // B: ba, bha key { [ U0928, U0923 ] }; // N: na, nna key { [ U092E, U0919, U092E, U093D ] }; // M: ma, nga, avagraha key { [ comma, U0970 ] };// comma: comma, dev abbreviation sign key { [ period, U093C ] }; // period: period, nukta key { [ slash, question ] }; // modifier_map Shift { Shift_L }; // modifier_map Lock { Caps_Lock }; // modifier_map Control{ Control_L }; // modifier_map Mod3 { Mode_switch }; include "level3(ralt_switch)" include "rupeesign(4)" }; // based on a keyboard map from an 'xkb/symbols/ben' file partial alphanumeric_keys xkb_symbols "ben" { name[Group1]= "Bangla (India)"; // Mainly numbers. key { [ U09E7 ] }; key { [ U09E8 ] }; key { [ U09E9 ] }; key { [ U09EA ] }; key { [ U09EB ] }; key { [ U09EC ] }; key { [ U09ED ] }; key { [ U09EE ] }; key { [ U09EF, parenleft ] }; key { [ U09E6, parenright ] }; key { [ minus, U0983 ] }; key { [ U098B, U09C3 ] }; // Mainly long vowels key { [ U09CC, U0994 ] }; key { [ U09C8, U0990 ] }; key { [ U09BE, U0986 ] }; key { [ U09C0, U0988 ] }; key { [ U09C2, U098A ] }; // Mainly voiced consonants key { [ U09AC, U09AD ] }; key { [ U09B9, U0999 ] }; key { [ U0997, U0998 ] }; key { [ U09A6, U09A7 ] }; key { [ U099C, U099D ] }; key { [ U09A1, U09A2 ] }; key { [ U09BC, U099E ] }; // Mainly short vowels key { [ U09CB, U0993 ] }; key { [ U09C7, U098F ] }; key { [ U09CD, U0985 ] }; key { [ U09BF, U0987 ] }; key { [ U09C1, U0989 ] }; // Mainly unvoiced consonants key { [ U09AA, U09AB ] }; key { [ U09B0, U09DD ] }; key { [ U0995, U0996 ] }; key { [ U09A4, U09A5 ] }; key { [ U099A, U099B ] }; key { [ U099F, U09A0 ] }; key { [ U005C, U007C ] }; key { [ z, Z ] }; key { [ U0982, U0981 ] }; key { [ U09AE, U09A3 ] }; key { [ U09A8, U09A8 ] }; key { [ U09AC, U09AC ] }; key { [ U09B2, U09B2 ] }; key { [ U09B8, U09B6 ] }; key { [ comma, U09B7 ] }; key { [ period, U0964 ] }; key { [ U09DF, U09AF ] }; include "level3(ralt_switch)" include "rupeesign(4)" }; xkb_symbols "ben_probhat" { name[Group1]= "Bangla (India, Probhat)"; key.type="FOUR_LEVEL"; key { [ Escape ] }; // numbers key { [ U200D, asciitilde ] }; key { [ U09E7, exclam, U09F4 ] }; key { [ U09E8, at, U09F5 ] }; key { [ U09E9, numbersign, U09F6 ] }; key { [ U09EA, U09F3, U09F7, U09F2 ] }; key { [ U09EB, percent ] }; key { [ U09EC, asciicircum ] }; key { [ U09ED, U099E, U09FA ] }; key { [ U09EE, U09CE ] }; key { [ U09EF, parenleft ] }; key { [ U09E6, parenright, U09F8, U09F9 ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ BackSpace ] }; // tab, q to ] key { [ Tab, ISO_Left_Tab ] }; key { [ U09A6, U09A7 ] }; key { [ U09C2, U098A ] }; key { [ U09C0, U0988 ] }; key { [ U09B0, U09DC ] }; key { [ U099F, U09A0 ] }; key { [ U098F, U0990 ] }; key { [ U09C1, U0989 ] }; key { [ U09BF, U0987 ] }; key { [ U0993, U0994 ] }; key { [ U09AA, U09AB ] }; key { [ U09C7, U09C8 ] }; key { [ U09CB, U09CC, U09D7 ] }; key { [ Return ] }; // caps, a to ' // key { [ Caps_Lock ] }; key { [ U09BE, U0985, U098C, U09E0 ] }; key { [ U09B8, U09B7, U09E1, U09E3 ] }; key { [ U09A1, U09A2, U09C4, U09E2 ] }; key { [ U09A4, U09A5 ] }; key { [ U0997, U0998 ] }; key { [ U09B9, U0983, U09BD ] }; key { [ U099C, U099D ] }; key { [ U0995, U0996 ] }; key { [ U09B2, U0982 ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; // shift, z to / // key { [ Shift_L ] }; key { [ U09DF, U09AF ] }; key { [ U09B6, U09DD ] }; key { [ U099A, U099B ] }; key { [ U0986, U098B ] }; key { [ U09AC, U09AD ] }; key { [ U09A8, U09A3 ] }; key { [ U09AE, U0999 ] }; key { [ comma, U09C3 ] }; key { [ U0964, U0981, U09BC ] }; key { [ U09CD, question ] }; key { [ U200C, U0965 ] }; // key { [ Control_L ] }; // key { [ space ] }; // modifier_map Shift { Shift_L }; // modifier_map Lock { Caps_Lock }; // modifier_map Control{ Control_L }; include "level3(ralt_switch)" include "rupeesign(4)" }; // Bangla Baishakhi, Bangla Baishakhi Inscript, Bangla Bornona, Uni Gitanjali Layouts are added by Promathesh Mandal xkb_symbols "ben_baishakhi" { name[Group1]= "Bangla (India, Baishakhi)"; key { [ Escape ] }; // numbers key { [ 0x100200D, 0x100200C ] }; key { [ 0x10009E7, exclam ] }; key { [ 0x10009E8, at ] }; key { [ 0x10009E9, numbersign ] }; key { [ 0x10009EA, dollar, 0x10009F2 ] }; key { [ 0x10009EB, percent ] }; key { [ 0x10009EC, asciicircum, 0x10009D7 ] }; key { [ 0x10009ED, ampersand ] }; key { [ 0x10009EE, asterisk,0x10009FA ] }; key { [ 0x10009EF, parenleft ] }; key { [ 0x10009E6, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ BackSpace ] }; // tab, q to ] key { [ Tab, ISO_Left_Tab ] }; key { [ 0x10009A1, 0x10009A2 ] }; key { [ 0x10009C0 , 0x10009C2 ] }; key { [ 0x10009C7, 0x100098F, 0x1000990 ] }; key { [ 0x10009B0 , 0x10009C3, 0x100098B ] }; key { [ 0x100099F, 0x10009A0 ] }; key { [ 0x10009AF, 0x10009DF ] }; key { [ 0x10009C1, 0x1000989, 0x100098A ] }; key { [ 0x10009BF, 0x1000987, 0x1000988 ] }; key { [ 0x10009CB, 0x1000993, 0x1000994 ] }; key { [ 0x10009AA, 0x10009AB ] }; key { [ bracketleft, braceleft] }; key { [ bracketright, braceright ] }; key { [ Return ] }; // caps, a to ' // key { [ Caps_Lock ] }; key { [ 0x10009BE, 0x1000985, 0x1000986 ] }; key { [ 0x10009B8, 0x10009B6, 0x10009B7 ] }; key { [ 0x10009A6, 0x10009A7 ] }; key { [ 0x10009A4, 0x10009A5, 0x10009CE ] }; key { [ 0x1000997, 0x1000998 ] }; key { [ 0x10009CD, 0x10009B9, 0x1000983 ] }; key { [ 0x100099C, 0x100099D ] }; key { [ 0x1000995, 0x1000996 ] }; key { [ 0x10009B2, 0x1000964, 0x100098C ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; // shift, z to / // key { [ Shift_L ] }; key { [ 0x10009C8, 0x10009CC ] }; key { [ 0x10009DC, 0x10009DD ] }; key { [ 0x100099A, 0x100099B ] }; key { [ 0x10009F1, 0x10009F0 ] }; key { [ 0x10009AC, 0x10009AD ] }; key { [ 0x10009A8, 0x10009A3, 0x100099E ] }; key { [ 0x10009AE, 0x1000999, 0x1000981 ] }; key { [ comma, less ] }; key { [ period, greater,0x10009BC ] }; key { [ slash, question, 0x1000982 ] }; key { [ backslash, bar ] }; // third level with right-alt include "level3(ralt_switch)" // key { [ Control_L ] }; // key { [ space ] }; // modifier_map Shift { Shift_L }; // modifier_map Lock { Caps_Lock }; // modifier_map Control{ Control_L }; }; xkb_symbols "ben_inscript" { name[Group1]= "Bangla (India, Baishakhi Inscript)"; // Mainly numbers. key { [ 0x100200D, 0x100200C ] }; key { [ 0x10009E7 ] }; key { [ 0x10009E8 ] }; key { [ 0x10009E9 ] }; key { [ 0x10009EA ] }; key { [ 0x10009EB ] }; key { [ 0x10009EC ] }; key { [ 0x10009ED ] }; key { [ 0x10009EE ] }; key { [ 0x10009EF, parenleft ] }; key { [ 0x10009E6, parenright ] }; key { [ minus, 0x1000983 ] }; key { [ 0x10009C3, 0x100098B ] }; // Mainly long vowels key { [ 0x10009CC, 0x1000994 ] }; key { [ 0x10009C8, 0x1000990 ] }; key { [ 0x10009BE, 0x1000986 ] }; key { [ 0x10009C0, 0x1000988 ] }; key { [ 0x10009C2, 0x100098A ] }; // Mainly voiced consonants key { [ 0x10009AC, 0x10009AD ] }; key { [ 0x10009B9, 0x1000999 ] }; key { [ 0x1000997, 0x1000998 ] }; key { [ 0x10009A6, 0x10009A7 ] }; key { [ 0x100099C, 0x100099D ] }; key { [ 0x10009A1, 0x10009A2 ] }; key { [ 0x10009BC, 0x100099E ] }; // Mainly short vowels key { [ 0x10009CB, 0x1000993 ] }; key { [ 0x10009C7, 0x100098F ] }; key { [ 0x10009CD, 0x1000985 ] }; key { [ 0x10009BF, 0x1000987 ] }; key { [ 0x10009C1, 0x1000989 ] }; // Mainly unvoiced consonants key { [ 0x10009AA, 0x10009AB ] }; key { [ 0x10009B0, 0x10009DD ] }; key { [ 0x1000995, 0x1000996 ] }; key { [ 0x10009A4, 0x10009A5 ] }; key { [ 0x100099A, 0x100099B ] }; key { [ 0x100099F, 0x10009A0 ] }; key { [ backslash, bar ] }; key { [ 0x10009CE ] }; key { [ 0x1000982, 0x1000981 ] }; key { [ 0x10009AE, 0x10009A3 ] }; key { [ 0x10009A8, 0x10009A8 ] }; key { [ 0x10009AC, 0x10009AC ] }; key { [ 0x10009B2, 0x10009B2 ] }; key { [ 0x10009B8, 0x10009B6 ] }; key { [ comma, 0x10009B7 ] }; key { [ period, 0x1000964 ] }; key { [ 0x10009DF, 0x10009AF ] }; }; xkb_symbols "ben_gitanjali" { name[Group1]= "Bangla (India, Gitanjali)"; key { [ Escape ] }; // numbers key { [ colon, question ] }; key { [ 0x10009E7, 0x10009CE ] }; key { [ 0x10009E8, apostrophe ] }; key { [ 0x10009E9, numbersign ] }; key { [ 0x10009EA, 0x10009F3 ] }; key { [ 0x10009EB, slash ] }; key { [ 0x10009EC, period ] }; key { [ 0x10009ED, ampersand ] }; key { [ 0x10009EE, asterisk ] }; key { [ 0x10009EF, parenleft ] }; key { [ 0x10009E6, parenright ] }; key { [ minus, 0x1000983 ] }; key { [ 0x10009C3, 0x100098B ] }; key { [ BackSpace ] }; // tab, q to ] key { [ Tab, ISO_Left_Tab ] }; key { [ 0x10009D7, 0x1000994 ] }; key { [ 0x10009C8, 0x1000990 ] }; key { [ 0x10009BE, 0x1000985 ] }; key { [ 0x10009C0, 0x1000988 ] }; key { [ 0x10009C2, 0x100098A ] }; key { [ 0x10009AC, 0x10009AD ] }; key { [ 0x10009B9, 0x1000999 ] }; key { [ 0x1000997, 0x1000998 ] }; key { [ 0x10009A6, 0x10009A7 ] }; key { [ 0x100099C, 0x100099D ] }; key { [ 0x10009A1, 0x10009A2 ] }; key { [ 0x100200C, 0x100099E ] }; key { [ Return ] }; // caps, a to ' // key { [ Caps_Lock ] }; key { [ 0x100200D, 0x1000993 ] }; key { [ 0x10009C7, 0x100098F ] }; key { [ 0x10009CD ] }; key { [ 0x10009BF, 0x1000987 ] }; key { [ 0x10009C1, 0x1000989 ] }; key { [ 0x10009AA, 0x10009AB ] }; key { [ 0x10009B0, 0x10009F0 ] }; key { [ 0x1000995, 0x1000996 ] }; key { [ 0x10009A4, 0x10009A5 ] }; key { [ 0x100099A, 0x100099B ] }; key { [ 0x100099F, 0x10009A0 ] }; // shift, z to / // key { [ Shift_L ] }; key { [ 0x10009C7, 0x100098F ] }; key { [ 0x1000982, 0x1000981 ] }; key { [ 0x10009AE, 0x10009A3 ] }; key { [ 0x10009A8, 0x10009DC ] }; key { [ 0x10009F1, 0x10009DD ] }; key { [ 0x10009B2 ] }; key { [ 0x10009B8, 0x10009B6 ] }; key { [ comma, 0x10009B7 ] }; key { [ 0x1000964, 0x10009FA ] }; key { [ 0x10009AF, 0x10009DF ] }; key { [ backslash, bar ] }; // third level with right-win // include "level3(lwin_switch)" // key { [ Control_L ] }; // key { [ space ] }; // modifier_map Shift { Shift_L }; // modifier_map Lock { Caps_Lock }; // modifier_map Control{ Control_L }; }; xkb_symbols "ben_bornona" { name[Group1]= "Bangla (India, Bornona)"; key { [ Escape ] }; // numbers key { [ 0x100200D, 0x100200C ] }; key { [ 0x10009E7, exclam ] }; key { [ 0x10009E8, 0x1000981 ] }; key { [ 0x10009E9, numbersign ] }; key { [ 0x10009EA, 0x10009F3 ] }; key { [ 0x10009EB, percent ] }; key { [ 0x10009EC, 0x1000983 ] }; key { [ 0x10009ED, 0x10009CE ] }; key { [ 0x10009EE, asterisk ] }; key { [ 0x10009EF, parenleft ] }; key { [ 0x10009E6, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ BackSpace ] }; // tab, q to ] key { [ Tab, ISO_Left_Tab ] }; key { [ 0x1000982, 0x1000999, 0x10009D7 ] }; key { [ 0x10009A2, 0x10009A0, 0x100098A ] }; key { [ 0x10009C7, 0x10009C8, 0x1000988 ] }; key { [ 0x10009B0, 0x10009C3, 0x100098B ] }; key { [ 0x10009A4, 0x100099F ] }; key { [ 0x10009A7, 0x10009A5, 0x100098F ] }; key { [ 0x10009C1, 0x10009C2, 0x1000989 ] }; key { [ 0x10009BF, 0x10009C0, 0x1000987 ] }; key { [ 0x10009CB, 0x10009CC, 0x1000993 ] }; key { [ 0x10009AA, 0x1000990, 0x1000994 ] }; key { [ 0x100005B, 0x100007B, 0x10009DC ] }; key { [ 0x100005D, 0x100007D ] }; key { [ Return ] }; // caps, a to ' // key { [ Caps_Lock ] }; key { [ 0x10009BE, 0x1000985, 0x10009F4 ] }; key { [ 0x10009B8, 0x10009B6, 0x10009F5 ] }; key { [ 0x10009A6, 0x10009A1, 0x10009F8 ] }; key { [ 0x10009AB ] }; key { [ 0x1000997, 0x1000998 ] }; key { [ 0x10009CD, 0x10009B9 ] }; key { [ 0x100099C, 0x100099D ] }; key { [ 0x1000995, 0x1000996 ] }; key { [ 0x10009B2, 0x1000964 ] }; key { [ semicolon, 0x100003A ] }; key { [ apostrophe, quotedbl ] }; // shift, z to / // key { [ Shift_L ] }; key { [ 0x10009AF, 0x10009DC ] }; key { [ 0x10009B7, 0x10009DD, 0x10009FA ] }; key { [ 0x100099A, 0x100099B ] }; key { [ 0x10009AD ] }; key { [ 0x10009AC, 0x10009DF ] }; key { [ 0x10009A8, 0x10009A3 ] }; key { [ 0x10009AE, 0x100099E ] }; key { [ comma, 0x100003C ] }; key { [ 0x100002E, 0x100003E ] }; key { [ 0x100002F, question ] }; key { [ 0x10009F1, 0x10009F0 ] }; // key { [ Control_L ] }; // key { [ space ] }; // modifier_map Shift { Shift_L }; // modifier_map Lock { Caps_Lock }; // modifier_map Control{ Control_L }; // third level with right-alt include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "guj" { name[Group1]= "Gujarati"; // Mainly numbers. key { [ U0AE7, U0A8D ] }; key { [ U0AE8, U0AC5 ] }; key { [ U0AE9 ] }; key { [ U0AEA ] }; key { [ U0AEB ] }; key { [ U0AEC ] }; key { [ U0AED ] }; key { [ U0AEE ] }; key { [ U0AEF, parenleft ] }; key { [ U0AE6, parenright ] }; key { [ minus, U0A83 ] }; key { [ U0A8B, U0AC3 ] }; // Mainly long vowels key { [ U0ACC, U0A94 ] }; key { [ U0AC8, U0A90 ] }; key { [ U0ABE, U0A86 ] }; key { [ U0AC0, U0A88 ] }; key { [ U0AC2, U0A8A ] }; // Mainly voiced consonants key { [ U0AAC, U0AAD ] }; key { [ U0AB9, U0A99 ] }; key { [ U0A97, U0A98 ] }; key { [ U0AA6, U0AA7 ] }; key { [ U0A9C, U0A9D ] }; key { [ U0AA1, U0AA2 ] }; key { [ U0ABC, U0A9E ] }; // Mainly short vowels key { [ U0ACB, U0A93 ] }; key { [ U0AC7, U0A8F ] }; key { [ U0ACD, U0A85 ] }; key { [ U0ABF, U0A87 ] }; key { [ U0AC1, U0A89 ] }; // Mainly unvoiced consonants key { [ U0AAA, U0AAB ] }; key { [ U0AB0, U0AB0 ] }; key { [ U0A95, U0A96 ] }; key { [ U0AA4, U0AA5 ] }; key { [ U0A9A, U0A9B ] }; key { [ U0A9F, U0AA0 ] }; key { [ U0AC9, U0A91 ] }; key { [ z , Z ] }; key { [ U0A82, U0A81 ] }; key { [ U0AAE, U0AA3 ] }; key { [ U0AA8, U0AA8 ] }; key { [ U0AB5, U0AB5 ] }; key { [ U0AB2, U0AB3 ] }; key { [ U0AB8, U0AB6 ] }; key { [ comma, U0AB7 ] }; key { [ period, U0964 ] }; key { [ U0AAF, question ] }; include "rupeesign(4)" include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "kan" { // Inscript layout for Kannada // Author : G Karunakar // Date : Wed Nov 13 17:22:58 IST 2002 // Kannada digits mapped in basic only name[Group1]= "Kannada"; key { [ U0cca, U0c92 ] }; key { [ U0ce7 ] }; key { [ U0ce8 ] }; key { [ U0ce9 ] }; key { [ U0cea ] }; key { [ U0ceb ] }; key { [ U0cec ] }; key { [ U0ced ] }; key { [ U0cee ] }; key { [ U0cef ] }; key { [ U0ce6 ] }; key { [ U0c83 ] }; key { [ U0cc3, U0c8b ] }; key { [ U0ccc, U0c94 ] }; key { [ U0cc8, U0c90 ] }; key { [ U0cbe, U0c86 ] }; key { [ U0cc0, U0c88 ] }; key { [ U0cc2, U0c8a ] }; key { [ U0cac, U0cad ] }; key { [ U0cb9, U0c99 ] }; key { [ U0c97, U0c98 ] }; key { [ U0ca6, U0ca7 ] }; key { [ U0c9c, U0c9d ] }; key { [ U0ca1, U0ca2 ] }; key { [ U0cbc, U0c9e ] }; key { [ U0ccb, U0c93 ] }; key { [ U0cc7, U0c8f ] }; key { [ U0ccd, U0c85 ] }; key { [ U0cbf, U0c87 ] }; key { [ U0cc1, U0c89 ] }; key { [ U0caa, U0cab ] }; key { [ U0cb0, U0cb1 ] }; key { [ U0c95, U0c96 ] }; key { [ U0ca4, U0ca5 ] }; key { [ U0c9a, U0c9b ] }; key { [ U0c9f, U0ca0 ] }; key { [ U0cc6, U0c8e ] }; key { [ U0c82 ] }; key { [ U0cae, U0ca3 ] }; key { [ U0ca8 ] }; key { [ U0cb5, U0cb4 ] }; key { [ U0cb2, U0cb3 ] }; key { [ U0cb8, U0cb6 ] }; key { [ comma , U0cb7 ] }; key { [ period ] }; key { [ U0caf, U0040 ] }; key { symbols[Group1] = [ Mode_switch, Multi_key ], virtualMods = AltGr }; include "rupeesign(4)" include "level3(ralt_switch)" }; // Description : A keymap for Malayalam // Encoding : Unicode (http://www.unicode.org) // Author : Baiju M // Date : Sat Aug 17 21:10:48 IST 2002 // Mapping: partial alphanumeric_keys xkb_symbols "mal" { name[Group1] = "Malayalam"; //From grave to backslash (\) key { [ U0d4a , U0d12 ] }; // svu: // These lines were in former "mal" variant - // but the digits are replaced with the ones from 'mal_plusnum' - // for the integrity of all Indian layouts // // key { [1 , exclam ] }; // key { [2 , at ] }; // key { [3 , numbersign ] }; // key { [4 , dollar ] }; // key { [5 , percent ] }; // key { [6 ,asciicircum ] }; // key { [7 , ampersand ] }; // key { [8 , asterisk ] }; // key { [9 , parenleft ] }; // key { [0 , parenright ] }; key { [ U0d67 , exclam ] }; key { [ U0d68 , at ] }; key { [ U0d69 , numbersign ] }; key { [ U0d6a , dollar ] }; key { [ U0d6b , percent ] }; key { [ U0d6c , asciicircum ] }; key { [ U0d6d , ampersand ] }; key { [ U0d6e , asterisk ] }; key { [ U0d6f , parenleft ] }; key { [ U0d66 , parenright ] }; key { [ minus , U0d03 ] }; key { [ U0d43 , U0d0b ] }; key { [U0200c, U05C ]};//bksl: ZWNJ // From 'q' to right bracket (]) key { [ U0d4c , U0d14 ] }; key { [ U0d48 , U0d10 ] }; key { [ U0d3e , U0d06 ] }; key { [ U0d40 , U0d08 ] }; key { [ U0d42 , U0d0a ] }; key { [ U0d2c , U0d2d ] }; key { [ U0d39 , U0d19 ] }; key { [ U0d17 , U0d18 ] }; key { [ U0d26 , U0d27 ] }; key { [ U0d1c , U0d1d ] }; key { [ U0d21 , U0d22 ] }; key { [ U0200d , U0d1e ] }; // From 'a' to apostrophe (') key { [ U0d4b , U0d13 ] }; key { [ U0d47 , U0d0f ] }; key { [ U0d4d , U0d05 ] }; key { [ U0d3f , U0d07 ] }; key { [ U0d41 , U0d09 ] }; key { [ U0d2a , U0d2b ] }; key { [ U0d30 , U0d31 ] }; key { [ U0d15 , U0d16 ] }; key { [ U0d24 , U0d25 ] }; key { [ U0d1a , U0d1b ] }; key { [ U0d1f , U0d20 ] }; // From 'z' to slash (/) key { [ U0d46 , U0d0e ] }; key { [ U0d02 , U200b ] };//X:ZWSP key { [ U0d2e , U0d23 ] }; key { [ U0d28 ] }; key { [ U0d35 , U0d34 ] }; key { [ U0d32 , U0d33 ] }; key { [ U0d38 , U0d36 ] }; key { [ comma , U0d37 ] }; key { [ period , U0200d ] }; key { [ U0d2f , question ] }; include "rupeesign(4)" include "level3(ralt_switch)" }; //Name : Lalitha //Description : A transliteration keyboard layout for Malayalam //Original Author : Noah Levitt //Current Main : Jinesh K.J, Swathantra Malayalam Computing (SMC) partial alphanumeric_keys xkb_symbols "mal_lalitha" { name[Group1] = "Malayalam (Lalitha)"; key.type="FOUR_LEVEL"; // Roman digits key { [ U0D4D, U0D02, apostrophe, asciitilde ] }; // apostrophe: virama(chandrakala),anusvara key { [ 1, exclam, U0D67, exclam ] }; key { [ 2, at, U0D68, at ] }; key { [ 3, numbersign, U0D69, numbersign ] }; key { [ 4, dollar, U0D6A ] }; key { [ 5, percent, U0D6B, percent ] }; key { [ 6, asciicircum, U0D6C, asciicircum ] }; key { [ 7, ampersand, U0D6D, ampersand ] }; key { [ 8, asterisk, U0D6E, asterisk ] }; key { [ 9, parenleft, U0D6F, parenleft ] }; key { [ 0, parenright, U0D66, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ U005C, U007C, U200C ] };//backslash:pipe,backslash,ZWNJ //Q Row key { [ U0D48, U0D4C, U0D10, U0D14 ] }; // Q: ai and au matras key { [ U0D35 ] }; // W: wa, OM key { [ U0D46, U0D47, U0D0E, U0D0F ] }; // E: e,ee matras key { [ U0D30, U0D31, U0D43, U0D0B ] }; // R: ra,rra, vocalic Ri key { [ U0D24, U0D25, U0D1F, U0D20 ] }; // T: tha, ttha,ta,tta key { [ U0D2f ] }; // Y: ya key { [ U0D41, U0D42, U0D09, U0D0A ] }; // U: u, uu matras key { [ U0D3F, U0D40, U0D07, U0D08 ] }; // I: i, ii matras key { [ U0D4A, U0D4B, U0D12, U0D13 ] }; // O: o, oo matras key { [ U0D2A ] }; // P: pa key { [ bracketleft, braceleft ] };//braceleft: key { [ bracketright, braceright ] };//braceright: //A Row key { [ U0D3E, U0D05, U0D06, U0D05 ] }; // A: a,aa key { [ U0D38, U0D37 ] }; // S: sa, ssa key { [ U0D26, U0D27, U0D21, U0D22 ] }; // D: soft da,soft dda,hard da,hard dda, key { [ U0D2B ] }; // F: pha key { [ U0D17, U0D18 ] }; // G: ga, gha key { [ U0D39, U0D03 ] }; // H: ha, visarg key { [ U0D1C, U0D1D ] }; // J: ja, jha key { [ U0D15, U0D16 ] }; // K: ka, kha key { [ U0D32, U0D33 ] }; // L: la, vocalic L or lru matra` key { [ semicolon, colon ] }; key { [apostrophe, quotedbl ] }; //Z Row key { [ U0D34, U0D36 ] }; // Z: sha,zha key { [ U0D4D, U200B ] }; // X: chandrakala,ZWSP key { [ U0D1A, U0D1B ] }; // C: ca, cha key { [ U0D35, U200D ] }; // V: va,ZWJ key { [ U0D2C, U0D2D ] }; // B: ba, bha key { [ U0D28, U0D23, U0D19, U0D1E ] }; // N: na, hard na,nga,nha key { [ U0D2E, U0D02 ] }; // M: ma key { [ comma, U003C ] };// comma: comma key { [ period, U003E ] }; // period: period key { [ slash, question ] }; // modifier_map Shift { Shift_L }; // modifier_map Lock { Caps_Lock }; // modifier_map Control{ Control_L }; // modifier_map Mod3 { Mode_switch }; include "level3(ralt_switch)" include "rupeesign(4)" }; partial alphanumeric_keys xkb_symbols "olck" { // Layout for the Ol Chiki script. // http://www.unicode.org/L2/L2005/05243r-n2984-ol-chiki.pdf (figure 9) name[Group1]= "Ol Chiki"; key { [ grave, U1C7B ] }; key { [ U1C51, exclam ] }; key { [ U1C52, at ] }; key { [ U1C53, numbersign ] }; key { [ U1C54, dollar, U20B9 ] }; key { [ U1C55, percent ] }; key { [ U1C56, asciicircum ] }; key { [ U1C57, ampersand ] }; key { [ U1C58, asterisk ] }; key { [ U1C59, parenleft ] }; key { [ U1C50, parenright ] }; key { [ minus, U1C7C ] }; key { [ equal, plus ] }; key { [ U1C67 ] }; key { [ U1C63 ] }; key { [ U1C6E ] }; key { [ U1C68 ] }; key { [ U1C74, U1C5B ] }; key { [ U1C6D ] }; key { [ U1C69 ] }; key { [ U1C64 ] }; key { [ U1C5A, U1C73 ] }; key { [ U1C6F ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ U1C7F, U1C7E ] }; key { [ U1C5F ] }; key { [ U1C65 ] }; key { [ U1C70, U1C6B ] }; key { [ U1C5D ] }; key { [ U1C5C ] }; key { [ U1C66, U1C77 ] }; key { [ U1C61 ] }; key { [ U1C60 ] }; key { [ U1C5E ] }; key { [ semicolon, U1C7A ] }; key { [ apostrophe, quotedbl ] }; key { [ U1C72 ] }; key { [ U1C7D ] }; key { [ U1C6A ] }; key { [ U1C76 ] }; key { [ U1C75 ] }; key { [ U1C71, U1C78 ] }; key { [ U1C62, U1C6C ] }; key { [ comma, less ] }; key { [ U1C79, greater ] }; key { [ slash, question ] }; key { symbols[Group1] = [ Mode_switch, Multi_key ], virtualMods = AltGr }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "ori" { // Inscript layout for Oriya // Author: G Karunakar // Date: Wed Nov 13 18:16:19 IST 2002 name[Group1]= "Oriya"; key { [ U0b67 ] }; key { [ U0b68 ] }; key { [ U0b69 ] }; key { [ U0b6a ] }; key { [ U0b6b ] }; key { [ U0b6c ] }; key { [ U0b6d ] }; key { [ U0b6e ] }; key { [ U0b6f ] }; key { [ U0b66 ] }; key { [ U0b03 ] }; key { [ U0b43, U0b0b ] }; key { [ U0b4c, U0b14 ] }; key { [ U0b48, U0b10 ] }; key { [ U0b3e, U0b06 ] }; key { [ U0b40, U0b08 ] }; key { [ U0b42, U0b0a ] }; key { [ U0b2c, U0b2d ] }; key { [ U0b39, U0b19 ] }; key { [ U0b17, U0b18 ] }; key { [ U0b26, U0b27 ] }; key { [ U0b1c, U0b1d ] }; key { [ U0b21, U0b22 ] }; key { [ U0b3c, U0b1e ] }; key { [ U0b4b, U0b13 ] }; key { [ U0b47, U0b0f ] }; key { [ U0b4d, U0b05 ] }; key { [ U0b3f, U0b07 ] }; key { [ U0b41, U0b09 ] }; key { [ U0b2a, U0b2b ] }; key { [ U0b30 ] }; key { [ U0b15, U0b16 ] }; key { [ U0b24, U0b25 ] }; key { [ U0b1a, U0b1b ] }; key { [ U0b1f, U0b20 ] }; key { [ U0b02, U0b01 ] }; key { [ U0b2e, U0b23 ] }; key { [ U0b28 ] }; key { [ U0b35 ] }; key { [ U0b32, U0b33 ] }; key { [ U0b38, U0b36 ] }; key { [ comma , U0b37 ] }; key { [ period ] }; key { [ U0b2f, U0040 ] }; key { symbols[Group1] = [ Mode_switch, Multi_key ], virtualMods = AltGr }; include "rupeesign(4)" include "level3(ralt_switch)" }; // based on a keyboard map from an 'xkb/symbols/tml' file // INSCRIPT partial alphanumeric_keys xkb_symbols "tam" { name[Group1]= "Tamil (Inscript)"; key { [ U0BCA, U0B92 ] }; // Mainly numbers. key { [ U0BE7 ] }; key { [ U0BE8 ] }; key { [ U0BE9 ] }; key { [ U0BEA ] }; key { [ U0BEB ] }; key { [ U0BEC ] }; key { [ U0BED ] }; key { [ U0BEE ] }; key { [ U0BEF, parenleft ] }; key { [ U0BF0, parenright ] }; key { [ U0BF1, U0B83 ] }; key { [ U0BF2, plus ] }; // Mainly long vowels key { [ U0BCC, U0B94 ] }; key { [ U0BC8, U0B90 ] }; key { [ U0BBE, U0B86 ] }; key { [ U0BC0, U0B88 ] }; key { [ U0BC2, U0B8A ] }; // Mainly voiced consonants key { [ U0BB9, U0B99 ] }; key { [ U0B9c ] }; key { [ U0B9E ] }; // Mainly short vowels key { [ U0BCB, U0B93 ] }; key { [ U0BC7, U0B8F ] }; key { [ U0BCD, U0B85 ] }; key { [ U0BBF, U0B87 ] }; key { [ U0BC1, U0B89 ] }; // Mainly unvoiced consonants key { [ U0BAA ] }; key { [ U0BB0, U0BB1 ] }; key { [ U0B95 ] }; key { [ U0BA4 ] }; key { [ U0B9A ] }; key { [ U0B9F ] }; key { [ U005C, U007C ] };//backslash-bar - Changed to Unicode key { [ U0BC6, U0B8E ] }; key { [ U0B82 ] }; key { [ U0BAE, U0BA3 ] }; key { [ U0BA8, U0BA9 ] }; key { [ U0BB5, U0BB4 ] }; key { [ U0BB2, U0BB3 ] }; key { [ U0BB8, U0BB6 ] }; key { [ comma, U0BB7 ] }; key { [ period, U0964 ] }; key { [ U0BAF, question ] }; include "level3(ralt_switch)" include "rupeesign(4)" }; partial alphanumeric_keys xkb_symbols "tam_tamilnet" { // Description: A keymap based on the TamilNet'99 typewriter keyboard // Encoding: Unicode (http://www.unicode.org) // Author: Thuraiappah Vaseeharan // Modifed by: Malathi S // Secondary contact: Sri Ramadoss M // Date : Fri Sep 4 11:32:00 CST 2009 // Mapping: name[Group1]= "Tamil (TamilNet '99)"; // granthas key { [ apostrophe, asciitilde ] }; key { [ U0031, exclam ] } ; key { [ U0032, at ] } ; key { [ U0033, numbersign ] } ; key { [ U0034, U0BF9 ] } ; key { [ U0035, percent ] } ; key { [ U0036, asciicircum ] } ; key { [ U0037, ampersand ] } ; key { [ U0038, asterisk ] } ; key { [ U0039, parenleft ] } ; key { [ U0030, parenright ] } ; key { [ minus, underscore ] }; key { [ equal, plus ] }; // Qrow key { [ U0B9E, U0BB6 ] }; key { [ U0BB1, U0BB7 ] }; key { [ U0BA8, U0BB8 ] }; key { [ U0B9A, U0BB9 ] }; key { [ U0BB5, U0B9C ] }; key { [ U0BB2 ] }; key { [ U0BB0 ] }; key { [ U0BC8, U0B90 ] }; key { [ U0BCA, U0BCB ] }; key { [ U0BBF, U0BC0 ] }; key { [ U0BC1, U0BC2 ] }; // Arow key { [ U0BAF ] }; key { [ U0BB3 ] }; key { [ U0BA9 ] }; key { [ U0B95 ] }; key { [ U0BAA ] }; key { [ U0BBE, U0BB4 ] }; key { [ U0BA4 ] }; key { [ U0BAE ] }; key { [ U0B9F ] }; key { [ U0BCD, U0B83 ] }; key { [ U0B99 ] }; // Zrow key { [ U0BA3 ] }; key { [ U0B92, U0B93 ] }; key { [ U0B89, U0B8A ] }; key { [ U0B8E, U0B8F ] }; key { [ U0BC6, U0BC7 ] }; key { [ U0B94, U0BCC ] }; key { [ U0B85, U0B86 ] }; key { [ U0B87, U0B88 ] }; }; partial alphanumeric_keys xkb_symbols "tam_tamilnet_with_tam_nums" { // Description: A keymap based on the TamilNet'99 typewriter keyboard // Encoding: Unicode (http://www.unicode.org) // Author: Malathi S // Secondary contact: Sri Ramadoss M // Date : Fri Sep 4 11:33:00 CST 2009 // Mapping: name[Group1]= "Tamil (TamilNet '99 with Tamil numerals)"; // Mainly numbers. key { [ apostrophe, asciitilde ] }; key { [ U0BE7, exclam ] }; key { [ U0BE8, at ] }; key { [ U0BE9, numbersign ] }; key { [ U0BEA, U0BF9 ] }; key { [ U0BEB, percent ] }; key { [ U0BEC, asciicircum ] }; key { [ U0BED, ampersand ] }; key { [ U0BEE, asterisk ] }; key { [ U0BEF, parenleft ] }; key { [ U0BE6, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; // Qrow key { [ U0B9E, U0BB6 ] }; key { [ U0BB1, U0BB7 ] }; key { [ U0BA8, U0BB8 ] }; key { [ U0B9a, U0BB9 ] }; key { [ U0BB5, U0B9c ] }; key { [ U0BB2 ] }; key { [ U0BB0 ] }; key { [ U0BC8, U0B90 ] }; key { [ U0BCA, U0BCB ] }; key { [ U0BBF, U0BC0 ] }; key { [ U0BC1, U0BC2 ] }; // Arow key { [ U0BAF ] }; key { [ U0BB3 ] }; key { [ U0BA9 ] }; key { [ U0B95 ] }; key { [ U0BAA ] }; key { [ U0BBE, U0BB4 ] }; key { [ U0BA4 ] }; key { [ U0BAE ] }; key { [ U0B9F ] }; key { [ U0BCD, U0B83 ] }; key { [ U0B99 ] }; // Zrow key { [ U0BA3 ] }; key { [ U0B92, U0B93 ] }; key { [ U0B89, U0B8A ] }; key { [ U0B8E, U0B8F ] }; key { [ U0BC6, U0BC7 ] }; key { [ U0B94, U0BCC ] }; key { [ U0B85, U0B86 ] }; key { [ U0B87, U0B88 ] }; }; partial alphanumeric_keys xkb_symbols "tam_tamilnet_TSCII" { // Description : A Tamil typewrite-style keymap // loosely based on TamilNet'99 reommendations // Encoding : TSCII (http://www.tscii.org) // Author : Thuraiappah Vaseeharan // Last Modified: Sat Jan 5 17:11:26 CST 2002 name[Group1]= "Tamil (TamilNet '99, TSCII encoding)"; key { [ 0x10000b7, 0x10000a4 ] }; // aytham key { [ 0x1000082, 0x10000a5 ] }; // shri key { [ 0x1000083, 0x1000088 ] }; // ja key { [ 0x1000084, 0x1000089 ] }; // sha key { [ 0x1000085, 0x100008a ] }; // sa key { [ 0x1000086, 0x100008b ] }; // ha key { [ 0x1000087, 0x100008c ] }; // ksha // Qrow key { [ 0x10000bb, 0x100009a ] }; // nja key { [ 0x10000c8, 0x10000da ] }; // Ra key { [ 0x10000bf, 0x10000d1 ] }; // NNa key { [ 0x10000ba, 0x10000cd ] }; // ca key { [ 0x10000c5, 0x10000d7 ] }; // va key { [ 0x10000c4, 0x10000d6 ] }; // la key { [ 0x10000c3, 0x10000d5 ] }; // ra key { [ 0x10000a8, 0x10000b3 ] }; // sangili, ai key { [ 0x10000ca, 0x10000cb ] }; // di, dI key { [ 0x10000a2, 0x10000a3 ] }; // visiri key { [ dead_acute, 0x10000a3 ] }; // Ukaaram // Arow key { [ 0x10000c2, 0x10000d4 ] }; // ya key { [ 0x10000c7, 0x10000d9 ] }; // La key { [ 0x10000c9, 0x10000db ] }; // na key { [ 0x10000b8, 0x10000cc ] }; // ka key { [ 0x10000c0, 0x10000d2 ] }; // pa key { [ dead_grave,0x10000a1 ] }; // pulli,aravu key { [ 0x10000be, 0x10000d0 ] }; // tha key { [ 0x10000c1, 0x10000d3 ] }; // ma key { [ 0x10000bc, 0x10000ce ] }; // da key { [ 0x10000c6, 0x10000d8 ] }; // zha key { [ 0x10000b9, 0x1000099 ] }; // nga // Zrow key { [ 0x10000bd, 0x10000cf ] }; // Na key { [ 0x10000b4, 0x10000b5 ] }; // o, O key { [ 0x10000af, 0x10000b0 ] }; // u, U key { [ 0x10000b1, 0x10000b2 ] }; // e, E key { [ 0x10000a6, 0x10000a7 ] }; // kombus key { [ 0x10000b6, 0x10000aa ] }; // au key { [ 0x10000ab, 0x10000ac ] }; // a, A key { [ 0x10000fe, 0x10000ae ] }; // i, I }; partial alphanumeric_keys xkb_symbols "tam_tamilnet_TAB" { // Description: A keymap based on the TamilNet'99 typewriter keyboard // Encoding: TAB (http://www.tamilnet99.org) // Author: Thuraiappah Vaseeharan // Date : Sun Aug 12 02:23:00 CDT 2001 name[Group1]= "Tamil (TamilNet '99, TAB encoding)"; // numeral row key { [ 0x10000e7, 0x10000a7 ] } ; key { [ 0x10000fa, 0x10000a8 ] } ; key { [ 0x10000fb ] } ; key { [ 0x10000fc ] } ; key { [ 0x10000fd ] } ; key { [ 0x10000fe ] } ; key { [ 0x10000ff ] } ; // q-row key { [ 0x10000eb, 0x10000b3 ] }; key { [ 0x10000f8, 0x10000c1 ] }; key { [ 0x10000ef, 0x10000b8 ] }; key { [ 0x10000ea, 0x10000b2 ] }; key { [ 0x10000f5, 0x10000be ] }; key { [ 0x10000f4, 0x10000bd ] }; key { [ 0x10000f3, 0x10000bc ] }; key { [ 0x10000ac, 0x10000e4 ] }; key { [ 0x10000ae, 0x10000af ] }; key { [ 0x10000a4, 0x10000a6 ] }; key { [ dead_circumflex, 0x10000a6 ] }; // Ukaaram // a-row key { [ 0x10000f2, 0x10000bb ] }; key { [ 0x10000f7, 0x10000c0 ] }; key { [ 0x10000f9, 0x10000c2 ] }; key { [ 0x10000e8, 0x10000b0 ] }; key { [ 0x10000f0, 0x10000b9 ] }; key { [ 0x10000a2, 0x10000a3 ] }; key { [ 0x10000ee, 0x10000b6 ] }; key { [ 0x10000f1, 0x10000ba ] }; key { [ 0x10000ec, 0x10000b4 ] }; key { [ 0x10000f6, 0x10000bf ] }; key { [ 0x10000e9, 0x10000b1 ] }; // z-row key { [ 0x10000ed, 0x10000b5 ] }; key { [ 0x10000e5, 0x10000e6 ] }; key { [ 0x10000e0, 0x10000e1 ] }; key { [ 0x10000e2, 0x10000e3 ] }; key { [ 0x10000aa, 0x10000ab ] }; key { [ 0x10000ac, 0x10000a3 ] }; key { [ 0x10000dc, 0x10000dd ] }; key { [ 0x10000de, 0x10000df ] }; }; partial alphanumeric_keys xkb_symbols "tel" { // Inscript layout for Telugu using Unicode // Author: G Karunakar // Date: // See layout at http://www.indlinux.org/keymap/telugu.php name[Group1]= "Telugu"; key { [ U0c4a, U0c12 ] }; key { [ U0c67 ] }; key { [ U0c68 ] }; key { [ U0c69, numbersign ] }; key { [ U0c6a, dollar ] }; key { [ U0c6b, percent ] }; key { [ U0c6c, asciicircum ] }; key { [ U0c6d, ampersand ] }; key { [ U0c6e, asterisk ] }; key { [ U0c6f, parenleft ] }; key { [ U0c66, parenright ] }; key { [ U0c03, underscore ] }; key { [ U0c43, U0c0b ] }; key { [ BackSpace ] }; key { [ U0c4c, U0c14 ] }; key { [ U0c48, U0c10 ] }; key { [ U0c3e, U0c06 ] }; key { [ U0c40, U0c08 ] }; key { [ U0c42, U0c0a ] }; key { [ U0c2c, U0c2d ] }; key { [ U0c39, U0c19 ] }; key { [ U0c17, U0c18 ] }; key { [ U0c26, U0c27 ] }; key { [ U0c1c, U0c1d ] }; key { [ U0c21, U0c22 ] }; key { [ U0c1e ] }; key { [ U0c4b, U0c13 ] }; key { [ U0c47, U0c0f ] }; key { [ U0c4d, U0c05 ] }; key { [ U0c3f, U0c07 ] }; key { [ U0c41, U0c09 ] }; key { [ U0c2a, U0c2b ] }; key { [ U0c30, U0c31 ] }; key { [ U0c15, U0c16 ] }; key { [ U0c24, U0c25 ] }; key { [ U0c1a, U0c1b ] }; key { [ U0c1f, U0c20 ] }; key { [ U0c46, U0c0e ] }; key { [ U0c02, U0c01 ] }; key { [ U0c2e, U0c23 ] }; key { [ U0c28 ] }; key { [ U0c35 ] }; key { [ U0c32, U0c33 ] }; key { [ U0c38, U0c36 ] }; key { [ comma , U0c37 ] }; key { [ period ] }; key { [ U0c2f, U0040 ] }; key { symbols[Group1] = [ Mode_switch, Multi_key ], virtualMods = AltGr }; include "rupeesign(4)" include "level3(ralt_switch)" }; //Name : Sarala //Description : This is an adaptation of the Sarala keyboard (http://www.medhajananam.org/sarala/) developed // by Krishna Dhullipalla. Because of the way keyboard shortcuts are laid out in KDE, the keyboard // modifiers had to be changed. The layout does not take any part of the original Sarala keyboard // code however. It has been developed from scratch, so the experience may differ. // // There is a ibus-m17n version of Sarala layout developed by Satya Pothamsetti on // http://www.medhajananam.org/. //Standard : Supports Unicode 9.0. //Help : This layout differs slightly from the layout on Medhajenanam. The layout has been depicted in the // pdf file attached to this post on Sarala google group. // (https://groups.google.com/forum/#!topic/sarala-keyboard/-gsa90dUFcs). // //Layout Developed by : Krishna Dhullipalla (http://www.medhajananam.org/) //Author : Venkat R Akkineni //Date : Apr 28 2017 partial alphanumeric_keys xkb_symbols "tel-sarala" { name[Group1] = "Telugu (Sarala)"; key.type="FOUR_LEVEL"; // sequence base, shift, alt, alt + shift key { [ U0C4A, U0C12 ] }; // ొ ఒ key { [ U0C42, U0C0A ] }; // ూ ఊ key { [ U0C21, U0C22 ] }; // డ ఢ key { [ U0C35, U0C39 ] }; // వ హ key { [ U0C2C, U0C2D ] }; // బ భ key { [ U0C28, U0C23 ] }; // న ణ key { [ U0C2E, U0C01 ] }; // మ ఁ key { [ U002C, U0C1E, leftcaret ] }; // , ఞ < key { [ U002E, U0C19, rightcaret ] }; // . ఙ > key { [ U0C36, question, KP_Divide ] }; // శ ? / key { [ U0C2F, U0C3D ] }; // య ఽ key { [ U0C02, U0C03 ] }; // ం ః key { [ U0C26, U0C27 ] }; // ద ధ key { [ U0C4D, U0C05 ] }; // ్ అ key { [ U0C17, U0C18 ] }; // గ ఘ key { [ U0C1A, U0C1B, U0C58, U0C59 ] }; // చ ఛ ౘ ౙ key { [ U0C3E, U0C06 ] }; // ా ఆ key { [ U0C15, U0C16, U0C62, U0C63 ] }; // క ఖ ౢ ౣ key { [ U0C32, U0C33, U0C0C, U0C61 ] }; // ల ళ ఌ ౡ key { [ U0C1F, U0C20, semicolon, colon ] }; // ట ఠ ; : key { [ quoteright, quotedbl ] }; // ' " key { [ U0C46, U0C0E, U0C44, U0C34 ] }; // ె ఎ ౄ ఴ key { [ U0C38, U0C37, U0C44 ] }; // స ష ౄ key { [ U0C47, U0C0F, U0C44 ] }; // ే ఏ ౄ key { [ U0C30, U0C31, U0C44, U0C60 ] }; // ర ఱ ౄ ౠ key { [ U0C24, U0C25 ] }; // త థ key { [ U0C40, U0C08 ] }; // ీ ఈ key { [ U0C41, U0C09 ] }; // ు ఉ key { [ U0C3F, U0C07 ] }; // ి ఇ key { [ U0C4B, U0C13 ] }; // ో ఓ key { [ U0C2A, U0C2B ] }; // ప ఫ key { [ U0C1C, U0C1D, bracketleft, braceleft ] }; // జ ఝ [ { key { [ U0C48, U0C10, bracketright, braceright ] }; // ై ఐ ] } key { [ KP_1, exclam, U0C67, U0C78 ] }; // 1 ! ౦ ౸ key { [ KP_2, at, U0C68, U0C79 ] }; // 2 @ ౨ ౹ key { [ KP_3, numbersign, U0C69, U0C7A ] }; // 3 # ౩ ౺ key { [ KP_4, dollar, U0C6A, U0C7B ] }; // 4 $ ౪ ౻ key { [ KP_5, percent, U0C6B, U0C7C ] }; // 5 % ౫ ౼ key { [ KP_6, asciicircum, U0C6C, U0C7D ] }; // 6 ^ ౬ ౽ key { [ KP_7, ampersand, U0C6D, U0C7E ] }; // 7 & ౭ ౾ key { [ KP_8, KP_Multiply, U0C6E, U0C7F ] }; // 8 * ౮ ౿ key { [ KP_9, U0028, U0C6F, U20B9 ] }; // 9 ( ౯ ₹ key { [ KP_0, U0029, U0C66, U0C55 ] }; // 0 ) ౦ ౕ key { [ KP_Subtract, underbar, NoSymbol, U0C56 ] }; // - _ ౖ key { [ KP_Equal, KP_Add ] }; // = + key { [ U0C4C, U0C14, U0964, U0965 ] }; // ౌ ఔ । ॥ key { [ U0C43, U0C0B, quoteleft, asciitilde ] }; // ృ ఋ ` ~ include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "urd-phonetic" { include "pk(urd-phonetic)" name[Group1]= "Urdu (phonetic)"; }; partial alphanumeric_keys xkb_symbols "urd-phonetic3" { include "pk(urd-crulp)" name[Group1]= "Urdu (alt. phonetic)"; }; partial alphanumeric_keys xkb_symbols "urd-winkeys" { include "pk(urd-nla)" name[Group1]= "Urdu (Windows)"; }; // based on a keyboard map from an 'xkb/symbols/gur' file partial alphanumeric_keys xkb_symbols "guru" { name[Group1]= "Punjabi (Gurmukhi)"; // Mainly numbers. key { [ U0A67 ] }; key { [ U0A68 ] }; key { [ U0A69, U0A71 ] }; key { [ U0A6A, U0A74 ] }; key { [ U0A6B, U262C ] }; key { [ U0A6C ] }; key { [ U0A6D ] }; key { [ U0A6e ] }; key { [ U0A6F, parenleft ] }; key { [ U0A66, parenright ] }; key { [ U0A03 ] }; key { [ equal, plus ] }; // Mainly long vowels key { [ U0A4C, U0A14 ] }; key { [ U0A48, U0A10 ] }; key { [ U0A3E, U0A06 ] }; key { [ U0A40, U0A08 ] }; key { [ U0A42, U0A0A ] }; // Mainly voiced consonants key { [ U0A2C, U0A2D ] }; key { [ U0A39, U0A19 ] }; key { [ U0A17, U0A18 ] }; key { [ U0A26, U0A27 ] }; key { [ U0A1C, U0A1D ] }; key { [ U0A21, U0A22 ] }; key { [ U0A3C, U0A1E ] }; // Mainly short vowels key { [ U0A4B, U0A13 ] }; key { [ U0A47, U0A0F ] }; key { [ U0A4D, U0A05 ] }; key { [ U0A3F, U0A07 ] }; key { [ U0A41, U0A09 ] }; // Mainly unvoiced consonants key { [ U0A2A, U0A2B ] }; key { [ U0A30, U0A5C ] }; key { [ U0A15, U0A16 ] }; key { [ U0A24, U0A25 ] }; key { [ U0A1A, U0A1B ] }; key { [ U0A1F, U0A20 ] }; key { [ U005C, U007C ] }; key { [ z, U0A01 ] }; key { [ U0A02, U0A70, U0A71 ] }; key { [ U0A2E, U0A23 ] }; key { [ U0A28, U0A28 ] }; key { [ U0A35, U0A35 ] }; key { [ U0A32, U0A33 ] }; key { [ U0A38, U0A36 ] }; key { [ comma, less ] }; key { [ period, U0964 ] }; key { [ U0A2F, question ] }; include "rupeesign(4)" include "level3(ralt_switch)" }; //Name : Jhelum (Refind Inscript) //Description : A Jhelum keyboard layout for Gurmukhi (Punjabi) // http://www.satluj.org/Jhelum.html //Modified for Inscript to make //Original Author : Amanpreet Singh Alam { [ apostrophe, asciitilde, U0A02,U0A01 ] }; // apostrophe: anusvara, candrabindu key { [ 1,exclam, U0A67, exclam ] }; key { [ 2,at, U0A68, at ] }; key { [ 3,numbersign, U0A69, numbersign ] }; key { [ 4,dollar, U0A6A ] }; key { [ 5,percent,U0A6B, percent ] }; key { [ 6,U0A73, U0A6C,asciicircum ] }; key { [ 7,U0A72,U0A6D,ampersand ] }; key { [ 8,asterisk,U0A6E, asterisk ] }; key { [ 9,parenleft,U0A6F,parenleft ] }; key { [ 0,parenright,U0A66,parenright ] }; key { [ minus,underscore] }; key { [ equal,plus] }; key { [ U0964,U0965,U007C,U005C] }; //pipe : danda, double danda //Q Row key { [ U0A4C, U0A14 ] }; // Q: oo, ooh key { [ U0A48, U0A10 ] }; // W: ee, ae key { [ U0A3E, U0A06 ] }; // E: a, aa key { [ U0A40, U0A08, U20B9 ] }; // R: ee, ai, rupeesign key { [ U0A42, U0A0A ] }; // T: u, uu key { [ U0A30, U0A5C ] }; // Y: ra, raa key { [ U0A26, U0A27 ] }; // U: tha, thha key { [ U0A17, U0A18, U0A5A ] }; // I:ga, gha key { [ U0A24, U0A1F ] }; // O: ta, tha key { [ U0A2A, U0A5E, VoidSymbol,U0A5E ] }; // P: pa, pha key { [ U0A21, U0A22, bracketleft, braceleft ] }; key { [ U0A19, U0A1E, bracketright, braceright ] }; //A Row key { [ U0A4B, U0A13 ] }; // A: o, oo key { [ U0A47, U0A0F ] }; // S: e, ee key { [ U0A4D, U0A05 ] }; // D: halant, aa key { [ U0A3F, U0A07 ] }; // F: i, aa key { [ U0A41, U0A09 ] }; // G: u, uh key { [ U0A39, U0A20 ] }; // H: ha, thha key { [ U0A1C, U0A1D, U0A5B ] }; // J: ja, jha key { [ U0A15, U0A16,VoidSymbol ,U0A59 ] }; // K: ka, kha key { [ U0A32, U0A25, U0A33 ] }; // L: la, tha key { [ U0A38, colon, U0A36 ] }; //; sa key { [apostrophe, quotedbl ] }; //Z Row key { [ U0A71, U0A3C ] }; // Z: addak, par bindi key { [ U0A02, U0A70 ] }; // X: bindi, tippi key { [ U0A1A, U0A1B ] }; // C: ca, cha key { [ U0A35, U0A2F ] }; // V: va, ya key { [ U0A2C, U0A2D ] }; // B: ba, bha key { [ U0A28, U0A23 ] }; // N: na, nha key { [ U0A2E, U0A2E ] }; // M: ma key { [ comma, U262C ] };// comma: comma, dev abbreviation sign key { [ period, U0A74 ] }; // period: period, nukta key { [ slash, question ] }; // modifier_map Shift { Shift_L }; // modifier_map Lock { Caps_Lock }; // modifier_map Control{ Control_L }; // modifier_map Mod3 { Mode_switch }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "olpc" { // Contact: Walter Bender include "in(deva)" key { [ U094A, U0912 ] }; // DEVANAGARI VOWEL SIGN SHORT O; DEVANAGARI LETTER SHORT O key { [ U0967, U090D ] }; // DEVANAGARI DIGIT ONE; DEVANAGARI LETTER CANDRA E key { [ U0968, U0945 ] }; // DEVANAGARI DIGIT TWO; DEVANAGARI VOWEL SIGN CANDRA E key { [ U0969 ] }; // DEVANAGARI DIGIT THREE; key { [ U096A ] }; // DEVANAGARI DIGIT FOUR; key { [ U096B ] }; // DEVANAGARI DIGIT FIVE; key { [ U096C ] }; // DEVANAGARI DIGIT SIX; key { [ U096D ] }; // DEVANAGARI DIGIT SEVEN; key { [ U096E ] }; // DEVANAGARI DIGIT EIGHT; key { [ U096F, parenleft ] }; // DEVANAGARI DIGIT NINE; key { [ U0966, parenright ] }; // DEVANAGARI DIGIT ZERO; key { [ minus, U0903 ] }; // DEVANAGARI SIGN VISARGA; key { [ U0943, U090B ] }; // DEVANAGARI VOWEL SIGN VOCALIC R; DEVANAGARI LETTER VOCALIC R key { [ U094C, U0914 ] }; // DEVANAGARI VOWEL SIGN AU; DEVANAGARI LETTER AU key { [ U0948, U0910 ] }; // DEVANAGARI VOWEL SIGN AI; DEVANAGARI LETTER AI key { [ U093E, U0906 ] }; // DEVANAGARI VOWEL SIGN AA; DEVANAGARI LETTER AA key { [ U0940, U0908 ] }; // DEVANAGARI VOWEL SIGN II; DEVANAGARI LETTER II key { [ U0942, U090A ] }; // DEVANAGARI VOWEL SIGN UU; DEVANAGARI LETTER UU key { [ U092C, U092D ] }; // DEVANAGARI LETTER BA; DEVANAGARI LETTER BHA key { [ U0939, U0919 ] }; // DEVANAGARI LETTER HA; DEVANAGARI LETTER NGA key { [ U0917, U0918 ] }; // DEVANAGARI LETTER GA; DEVANAGARI LETTER GHA key { [ U0926, U0927 ] }; // DEVANAGARI LETTER DA; DEVANAGARI LETTER DHA key { [ U091C, U091D ] }; // DEVANAGARI LETTER JA; DEVANAGARI LETTER JHA key { [ U0921, U0922 ] }; // DEVANAGARI LETTER DDA; DEVANAGARI LETTER DDHA key { [ U093C, U091E ] }; // DEVANAGARI SIGN NUKTA; DEVANAGARI LETTER NYA key { [ U0949, U0911 ] }; // DEVANAGARI VOWEL SIGN CANDRA O; DEVANAGARI LETTER CANDRA O key { [ U094B, U0913 ] }; // DEVANAGARI VOWEL SIGN O; DEVANAGARI LETTER O key { [ U0947, U090F ] }; // DEVANAGARI VOWEL SIGN E; DEVANAGARI LETTER E key { [ U094D, U0905 ] }; // DEVANAGARI SIGN VIRAMA; DEVANAGARI LETTER A key { [ U093F, U0907 ] }; // DEVANAGARI VOWEL SIGN I; DEVANAGARI LETTER I key { [ U0941, U0909 ] }; // DEVANAGARI VOWEL SIGN U; DEVANAGARI LETTER U key { [ U092A, U092B ] }; // DEVANAGARI LETTER PA; DEVANAGARI LETTER PHA key { [ U0930, U0931 ] }; // DEVANAGARI LETTER RA; DEVANAGARI LETTER RRA key { [ U0915, U0916 ] }; // DEVANAGARI LETTER KA; DEVANAGARI LETTER KHA key { [ U0924, U0925 ] }; // DEVANAGARI LETTER TA; DEVANAGARI LETTER THA key { [ U091A, U091B ] }; // DEVANAGARI LETTER CA; DEVANAGARI LETTER CHA key { [ U091F, U0920 ] }; // DEVANAGARI LETTER TTA; DEVANAGARI LETTER TTHA key { [ U0946, U090E ] }; // DEVANAGARI VOWEL SIGN SHORT E; DEVANAGARI LETTER SHORT E key { [ U0902, U0901 ] }; // DEVANAGARI SIGN ANUSVARA; DEVANAGARI SIGN CANDRABINDU key { [ U092E, U0923 ] }; // DEVANAGARI LETTER MA; DEVANAGARI LETTER NNA key { [ U0928, U0929 ] }; // DEVANAGARI LETTER NA; DEVANAGARI LETTER NNNA key { [ U0935, U0934 ] }; // DEVANAGARI LETTER VA; DEVANAGARI LETTER LLLA key { [ U0932, U0933 ] }; // DEVANAGARI LETTER LA; DEVANAGARI LETTER LLA key { [ U0938, U0936 ] }; // DEVANAGARI LETTER SA; DEVANAGARI LETTER SHA key { [ comma, U0937 ] }; // DEVANAGARI LETTER SSA key { [ period, U0964 ] }; // DEVANAGARI DANDA key { [ U092F, U095F ] }; // DEVANAGARI LETTER YA; DEVANAGARI LETTER YYA // space, space, Zero-Width-Non-Joiner (ZWNJ), Zero-Width-Joiner (ZWJ): include "nbsp(zwnj3zwj4)" include "group(olpc)" include "rupeesign(4)" include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "hin-wx" { name[Group1]= "Hindi (Wx)"; key { [ grave, asciitilde, 2, 3 ] }; key { [ 0x1000967, exclam ] }; key { [ 0x1000968, at ] }; key { [ 0x1000969 , numbersign ] }; key { [ 0x100096A , dollar ] }; key { [ 0x100096B , percent ] }; key { [ 0x100096C , asciicircum ] }; key { [ 0x100096D , ampersand ] }; key { [ 0x100096e , asterisk ] }; key { [ 0x100096F, parenleft ] }; key { [ 0x1000966, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ 0x1000943, 0x1000944, 0x100090B, 0x1000960] }; key { [ 0x1000924, 0x1000925 ] }; key { [ 0x1000947, 0x1000948, 0x100090F, 0x1000910] }; key { [ 0x1000930, 0x1000937 ] }; key { [ 0x100091F, 0x1000920 ] }; key { [ 0x100092F ] }; key { [ 0x1000941, 0x1000942, 0x1000909, 0x100090A ] }; key { [ 0x100093F, 0x1000940, 0x1000907, 0x1000908 ] }; key { [ 0x100094B, 0x100094C, 0x1000913, 0x1000914] }; key { [ 0x100092A, 0x100092B ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ backslash, bar, 0x1000964, 0x1000965 ] }; key { [ 0x100094D, 0x100093E, 0x1000905,0x1000906 ] }; key { [ 0x1000938, 0x1000936 ] }; key { [ 0x1000921, 0x1000922 ] }; key { [ 0x1000919, 0x100091E ] }; key { [ 0x1000917, 0x1000918 ] }; key { [ 0x1000939, 0x1000903 ] }; key { [ 0x100091C, 0x100091D ] }; key { [ 0x1000915, 0x1000916 ] }; key { [ 0x1000932, 0x1000962, 0x1000933, 0x100090C] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ 0x1000901, 0x100093C, 0x100093D, 0x1000950] }; key { [ 0x1000926, 0x1000927 ] }; key { [ 0x100091A, 0x100091B ] }; key { [ 0x1000935 ] }; key { [ 0x100092C, 0x100092D ] }; key { [ 0x1000928, 0x1000923 ] }; key { [ 0x100092E, 0x1000902 ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ slash, question ] }; include "level3(ralt_switch)" include "rupeesign(4)" }; partial alphanumeric_keys xkb_symbols "eng" { include "us(basic)" name[Group1]= "English (India, with rupee)"; include "rupeesign(4)" include "level3(ralt_switch)" }; // Description : Enhanced INSCRIPT keymap for Malayalam // Encoding : Unicode (http://www.unicode.org) // Author : Mahesh T Pai // Date : March, 2011 // Source : http://www.nongnu.org/smc/docs/images/ml_inscript_layout.jpg // Comment : Based on the Inscript Keyboard created by M Baiju // Mapping: partial alphanumeric_keys xkb_symbols "mal_enhanced" { name[Group1] = "Malayalam (enhanced Inscript, with rupee)"; //From grave to backslash (\) key { [ U0d4a , U0d12 ] }; key { [ U0d67 , exclam ] }; key { [ U0d68 , at ] }; key { [ U0d69 , numbersign ] }; key { [ U0d6a , dollar ] }; key { [ U0d6b , percent ] }; key { [ U0d6c , asciicircum ] }; key { [ U0d6d , ampersand ] }; key { [ U0d6e , U0d7e ] }; key { [ U0d6f , parenleft ] }; key { [ U0d66 , parenright ] }; key { [ minus , U0d03 ] }; key { [ U0d43 , U0d0b ] }; key { [ U0d7c , U05C ] }; //bksl: chillu RR // From 'q' to right bracket (]) key { [ U0d57 , U0d14 ] }; key { [ U0d48 , U0d10 ] }; key { [ U0d3e , U0d06 ] }; key { [ U0d40 , U0d08 ] }; key { [ U0d42 , U0d0a ] }; key { [ U0d2c , U0d2d ] }; key { [ U0d39 , U0d19 ] }; key { [ U0d17 , U0d18 ] }; key { [ U0d26 , U0d27 ] }; key { [ U0d1c , U0d1d ] }; key { [ U0d21 , U0d22 ] }; key { [ U0200d , U0d1e ] }; // From 'a' to apostrophe (') key { [ U0d4b , U0d13 ] }; key { [ U0d47 , U0d0f ] }; key { [ U0d4d , U0d05 ] }; key { [ U0d3f , U0d07 ] }; key { [ U0d41 , U0d09 ] }; key { [ U0d2a , U0d2b ] }; key { [ U0d30 , U0d31 ] }; key { [ U0d15 , U0d16 ] }; key { [ U0d24 , U0d25 ] }; key { [ U0d1a , U0d1b ] }; key { [ U0d1f , U0d20 ] }; // From 'z' to slash (/) key { [ U0d46 , U0d0e ] }; key { [ U0d02 , U0d7a ] }; key { [ U0d2e , U0d23 ] }; key { [ U0d28 , U0d7b ] }; key { [ U0d35 , U0d34 ] }; key { [ U0d32 , U0d33 ] }; key { [ U0d38 , U0d36 ] }; key { [ comma , U0d37 ] }; key { [ period , U0d7d ] }; //chillu l key { [ U0d2f , question ] }; include "rupeesign(4)" include "level3(ralt_switch)" }; // ---- BEGIN Hindi KaGaPa phonetic ---- // Name: KaGaPa phonetic // Brief: Devanagari layout (Hindi, Sanskrit, Nepali, Marathi, etc.) // Diagram: (Original)[http://baraha.com/help/Keyboards/dev_brhkbd.htm] // (This layout)[http://bdsatish.in/lang/dev-kagapa.png] // // Description: Based on KaGaPa layout (also called Baraha layout or Nudi layout) // which is a modified layout of the specification by Dr. K. P. Rao. // This is a phonetic layout with the following features: // [1] All letters are mapped to phonetically-similar English keys // as much as possible. // [2] The independent vowel (svara) and its dependent vowel (maatra) // use the same key (depending upon SHIFT, ALTGR or ALTGR + SHIFT). // [3] Consonant conjuncts are produced by explicitly invoking the // 'viraama' (key f). The 'short a' maatra is implicit in all // consonants. // [4] Zero width non-joiner and joiner are on keys 6 and 7 // respectively. These are absolutely essential for alternative // glyph renderings of consonant half-forms. // [5] Rigvedic accent marks, visarga variants. // // Author: Satish BD // partial alphanumeric_keys xkb_symbols "hin-kagapa" { name[Group1] = "Hindi (KaGaPa, phonetic)"; key.type="FOUR_LEVEL"; // Roman digits key { [ apostrophe, asciitilde, U201C ] }; // U201C: left double quotation mark key { [ 1, exclam, U0967 ] }; key { [ 2, at, U0968, U20A8 ] }; // U20A8: generic rupee sign (Rs) key { [ 3, numbersign, U0969 ] }; key { [ 4, dollar, U096A, U20B9 ] }; // U20B9: new Indian rupee sign key { [ 5, percent, U096B ] }; key { [ 6, asciicircum, U096C, U200C ] }; // ZWNJ key { [ 7, ampersand, U096D, U200D ] }; // ZWJ key { [ 8, asterisk, U096E, U0901 ] }; // U0901: Devanagari candrabindu key { [ 9, parenleft, U096F ] }; key { [ 0, parenright, U0966, U0970 ] }; // U0970: Devanagari abbreviation sign key { [ minus, underscore, U0952 ] }; // U0952: Devanagari stress sign anudatta key { [ equal, plus ] }; key { [ U005C, U007C, U0964, U0965 ] }; // backslash, pipe, danda, double danda //Q Row key { [ U091F, U0920 ] }; // Q: retroflex Ta, Tha key { [ U0921, U0922, U095C, U095D ] }; // W: retroflex Da, Dha, Da-nukta, Dha-nukta key { [ U0946, U0947, U090E, U090F ] }; // E: matras, short E, long E key { [ U0930, U0943, U090B, U0931 ] }; // R: ra, vocalic R matra, vocalic R, ra-nukta key { [ U0924, U0925 ] }; // T: dental ta, tha key { [ U092F, U0948, U0910, U095F ] }; // Y: ya, ai matra, ai, ya-nukta key { [ U0941, U0942, U0909, U090A ] }; // U: matras, u, uu key { [ U093F, U0940, U0907, U0908 ] }; // I: matras, i, ii key { [ U094A, U094B, U0912, U0913 ] }; // O: matras, short o, long o key { [ U092A, U092B, U095E ] }; // P: pa, pha, pha-nukta key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; //A Row key { [ U093E, U0906, U0905, U0972 ] }; // A: aa matra, aa, short a, candra a key { [ U0938, U0936 ] }; // S: sa, sha key { [ U0926, U0927 ] }; // D: dental da, dha key { [ U094D, U0944, U0960 ] }; // F: virama, vocalic RR matra, vocalic RR key { [ U0917, U0918, U095A ] }; // G: ga, gha, ga-nukta key { [ U0939, U0903, U1CF5, U1CF6 ] }; // H: ha, visarga, jihvamuliya, upadhmaniya key { [ U091C, U091D, U095B ] }; // J: ja, jha, ja-nukta key { [ U0915, U0916, U0958, U0959 ] }; // K: ka, kha, ka-nukta, kha-nukta key { [ U0932, U0933, U0962, U090C ] }; // L: la, lla, vocalic L matra, vocalic L key { [ semicolon, colon, U1CF2, U1CF3 ] }; // U1CF2/3: ardhavisarga/rotated ardhavisarga key { [ apostrophe, quotedbl, U0951, U201D ] }; // U0951: Devanagari stress sign udatta // U201D: Right double quotation mark //Z Row key { [ U091E, U0919 ] }; // Z: nya, nga key { [ U0937, U093C, U0934 ] }; // X: ssa, nukta below, lla-nukta key { [ U091A, U091B ] }; // C: ca, cha key { [ U0935, U094C, U0914 ] }; // V: va, matra au, au key { [ U092C, U092D ] }; // B: ba, bha key { [ U0928, U0923, U0929 ] }; // N: na, nna, nnna key { [ U092E, U0902, U093D, U0950 ] }; // M: ma, anusvara, avagraha, Devanagari OM key { [ comma, U003C, U0945, U090D ] }; // comma: comma, less than, matra, candra e key { [ period, U003E, U0949, U0911 ] }; // period: period, greater than, matra, candra o key { [ slash, question ] }; include "level3(ralt_switch)" }; // ---- END Hindi KaGaPa ---- // Sanskrit uses Devanagari layout of Hindi partial alphanumeric_keys xkb_symbols "san-kagapa" { include "in(hin-kagapa)" name[Group1] = "Sanskrit (KaGaPa, phonetic)"; }; // Marathi uses Devanagari layout of Hindi partial alphanumeric_keys xkb_symbols "mar-kagapa" { include "in(hin-kagapa)" name[Group1] = "Marathi (KaGaPa, phonetic)"; }; // ---- BEGIN Kannada KaGaPa phonetic ---- // Name: Kannada KaGaPa phonetic // Diagram: (Original)[http://www.baraha.com/help/Keyboards/kan_brhkbd.htm] // (This layout)[http://bdsatish.in/lang/kan-kagapa.png] // // Description: Based on KaGaPa layout (also called Baraha layout or Nudi layout). // See the description to "hin-kagapa" above. // Certain punctuation characters from Devanagari block are // retained for compatibility. // // Author: Satish BD // partial alphanumeric_keys xkb_symbols "kan-kagapa" { name[Group1] = "Kannada (KaGaPa, phonetic)"; key.type="FOUR_LEVEL"; // Roman digits key { [ apostrophe, asciitilde, U201C ] }; // U201C: left double quotation mark key { [ 1, exclam, U0CE7 ] }; key { [ 2, at, U0CE8, U20A8 ] }; // U20A8: generic rupee sign (Rs) key { [ 3, numbersign, U0CE9 ] }; key { [ 4, dollar, U0CEA, U20B9 ] }; // U20B9: new Indian rupee sign key { [ 5, percent, U0CEB ] }; key { [ 6, asciicircum, U0CEC, U200C ] }; // ZWNJ key { [ 7, ampersand, U0CED, U200D ] }; // ZWJ key { [ 8, asterisk, U0CEE, U0901 ] }; // U0901: Devanagari candrabindu key { [ 9, parenleft, U0CEF ] }; key { [ 0, parenright, U0CE6 ] }; key { [ minus, underscore, U0952 ] }; // U0952: Devanagari stress sign anudatta key { [ equal, plus ] }; key { [ U005C, U007C, U0964, U0965 ] }; // backslash, pipe, danda, double danda //Q Row key { [ U0C9F, U0CA0 ] }; // Q: retroflex Ta, Tha key { [ U0CA1, U0CA2 ] }; // W: retroflex Da, Dha key { [ U0CC6, U0CC7, U0C8E, U0C8F ] }; // E: matras, short E, long E key { [ U0CB0, U0CC3, U0C8B, U0CB1 ] }; // R: ra, vocalic R matra, vocalic R, RRA key { [ U0CA4, U0CA5 ] }; // T: dental ta, tha key { [ U0CAF, U0CC8, U0C90 ] }; // Y: ya, ai matra, ai key { [ U0CC1, U0CC2, U0C89, U0C8A ] }; // U: matras, u, uu key { [ U0CBF, U0CC0, U0C87, U0C88 ] }; // I: matras, i, ii key { [ U0CCA, U0CCB, U0C92, U0C93 ] }; // O: matras, short o, long o key { [ U0CAA, U0CAB ] }; // P: pa, pha key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; //A Row key { [ U0CBE, U0C86, U0C85 ] }; // A: aa matra, aa, short a key { [ U0CB8, U0CB6 ] }; // S: sa, sha key { [ U0CA6, U0CA7 ] }; // D: dental da, dha key { [ U0CCD, U0CC4, U0CE0 ] }; // F: virama, vocalic RR matra, vocalic RR key { [ U0C97, U0C98 ] }; // G: ga, gha key { [ U0CB9, U0C83, U0CF1, U0CF2 ] }; // H: ha, visarga, jihvanuliya, upadhmaniya key { [ U0C9C, U0C9D ] }; // J: ja, jha key { [ U0C95, U0C96 ] }; // K: ka, kha key { [ U0CB2, U0CB3, U0CE2, U0C8C ] }; // L: la, lla, vocalic L matra, vocalic L key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl, U0951, U201D ] }; // U0951: Devanagari stress sign udatta // U201D: Right double quotation mark //Z Row key { [ U0C9E, U0C99 ] }; // Z: nya, nga key { [ U0CB7, U0CBC, U0CDE ] }; // X: ssa, nukta below, LLLA key { [ U0C9A, U0C9B ] }; // C: ca, cha key { [ U0CB5, U0CCC, U0C94 ] }; // V: va, matra au, au key { [ U0CAC, U0CAD ] }; // B: ba, bha key { [ U0CA8, U0CA3 ] }; // N: na, nna key { [ U0CAE, U0C82, U0CBD, U0950 ] }; // M: ma, anusvara, avagraha, Devanagari OM key { [ comma, U003C, U0CB1 ] }; // comma: comma, less than, RRA key { [ period, U003E, U0CDE ] }; // period: period, greater than, LLLA key { [ slash, question ] }; include "level3(ralt_switch)" }; // ---- END Kannada KaGaPa ---- // ---- BEGIN Telugu KaGaPa phonetic ---- // Name: Telugu KaGaPa phonetic // Diagram: (Original)[http://www.baraha.com/help/Keyboards/tel_brhkbd.htm] // (This layout)[http://bdsatish.in/lang/tel-kagapa.png] // // Description: Based on KaGaPa layout (also called Baraha layout or Nudi layout). // See the description to "hin-kagapa" above. // Certain punctuation characters from Devanagari block are // retained for compatibility. // // Author: Satish BD // partial alphanumeric_keys xkb_symbols "tel-kagapa" { name[Group1] = "Telugu (KaGaPa, phonetic)"; key.type="FOUR_LEVEL"; // Roman digits key { [ apostrophe, asciitilde, U201C ] }; // U201C: left double quotation mark key { [ 1, exclam, U0C67 ] }; key { [ 2, at, U0C68, U20A8 ] }; // U20A8: generic rupee sign (Rs) key { [ 3, numbersign, U0C69 ] }; key { [ 4, dollar, U0C6A, U20B9 ] }; // U20B9: new Indian rupee sign key { [ 5, percent, U0C6B ] }; key { [ 6, asciicircum, U0C6C, U200C ] }; // ZWNJ key { [ 7, ampersand, U0C6D, U200D ] }; // ZWJ key { [ 8, asterisk, U0C6E, U0C01 ] }; // U0C01: Telugu arasunna key { [ 9, parenleft, U0C6F ] }; key { [ 0, parenright, U0C66 ] }; key { [ minus, underscore, U0952 ] }; // U0952: Devanagari stress sign anudatta key { [ equal, plus ] }; key { [ U005C, U007C, U0964, U0965 ] }; // backslash, pipe, danda, double danda //Q Row key { [ U0C1F, U0C20 ] }; // Q: retroflex Ta, Tha key { [ U0C21, U0C22 ] }; // W: retroflex Da, Dha key { [ U0C46, U0C47, U0C0E, U0C0F ] }; // E: matras, short E, long E key { [ U0C30, U0C43, U0C0B, U0C31 ] }; // R: ra, vocalic R matra, vocalic R, RRA key { [ U0C24, U0C25 ] }; // T: dental ta, tha key { [ U0C2F, U0C48, U0C10 ] }; // Y: ya, ai matra, ai key { [ U0C41, U0C42, U0C09, U0C0A ] }; // U: matras, u, uu key { [ U0C3F, U0C40, U0C07, U0C08 ] }; // I: matras, i, ii key { [ U0C4A, U0C4B, U0C12, U0C13 ] }; // O: matras, short o, long o key { [ U0C2A, U0C2B ] }; // P: pa, pha key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; //A Row key { [ U0C3E, U0C06, U0C05 ] }; // A: aa matra, aa, short a key { [ U0C38, U0C36 ] }; // S: sa, sha key { [ U0C26, U0C27 ] }; // D: dental da, dha key { [ U0C4D, U0C44, U0C60 ] }; // F: virama, vocalic RR matra, vocalic RR key { [ U0C17, U0C18 ] }; // G: ga, gha key { [ U0C39, U0C03 ] }; // H: ha, visarga key { [ U0C1C, U0C1D ] }; // J: ja, jha key { [ U0C15, U0C16 ] }; // K: ka, kha key { [ U0C32, U0C33, U0C62, U0C0C ] }; // L: la, lla, vocalic L matra, vocalic L key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl, U0951, U201D ] }; // U0951: Devanagari stress sign udatta // U201D: Right double quotation mark //Z Row key { [ U0C1E, U0C19 ] }; // Z: nya, nga key { [ U0C37 ] }; // X: ssa key { [ U0C1A, U0C1B ] }; // C: ca, cha key { [ U0C35, U0C4C, U0C14 ] }; // V: va, matra au, au key { [ U0C2C, U0C2D ] }; // B: ba, bha key { [ U0C28, U0C23 ] }; // N: na, nna key { [ U0C2E, U0C02, U0C3D, U0950 ] }; // M: ma, anusvara, avagraha, Devanagari OM key { [ comma, U003C, U0C58 ] }; // comma: comma, less than, TSA key { [ period, U003E, U0C59 ] }; // period: period, greater than, DZA key { [ slash, question ] }; include "level3(ralt_switch)" }; // Description : Keymap for Manipuri language (Meetei mayek script) // Encoding : Unicode (http://www.unicode.org) // Author : Santosh Heigrujam // Date : December, 2013 // Source : // Comment : partial alphanumeric_keys modifier_keys xkb_symbols "eeyek" { name[Group1]= "Manipuri (Eeyek)"; key { [ grave, asciitilde ] }; key { [ Uabf1, exclam ] }; key { [ Uabf2, at ] }; key { [ Uabf3, numbersign ] }; key { [ Uabf4, dollar ] }; key { [ Uabf5, percent ] }; key { [ Uabf6, asciicircum ] }; key { [ Uabf7, ampersand ] }; key { [ Uabf8, asterisk ] }; key { [ Uabf9, parenleft ] }; key { [ Uabf0, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ Uabc8, Uabd8 ] }; key { [ Uabcb, Uabcb ] }; key { [ Uabcf, Uabe2 ] }; key { [ Uabd4, Uabd4 ] }; key { [ Uabc7, Uabe0 ] }; key { [ Uabcc, Uabe6 ] }; key { [ Uabce, Uabe8 ] }; key { [ Uabe4, Uabe9 ] }; key { [ Uabe3, Uabe7 ] }; key { [ Uabc4, Uabde ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ Uabd1, Uabe5 ] }; key { [ Uabc1, Uabd3 ] }; key { [ Uabd7, Uabd9 ] }; key { [ Uabd0, Uabda ] }; key { [ Uabd2, Uabd8 ] }; key { [ Uabcd, Uabea ] }; key { [ Uabd6, Uabd3 ] }; key { [ Uabc0, Uabdb ] }; key { [ Uabc2, Uabdc ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ Uabc9, Uabe1 ] }; key { [ Uabca, Uabd9 ] }; key { [ Uabc6, Uabeb ] }; key { [ Uabda, Uabed ] }; key { [ Uabd5, Uabec ] }; key { [ Uabc5, Uabdf ] }; key { [ Uabc3, Uabdd ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ slash, question ] }; key { [ backslash, bar ] }; include "level3(ralt_switch)" }; // This layout is developed by Niranjan Tambe in July 2019 // for typing Indic languages in International Phonetic Alphabet (IPA). partial alphanumeric_keys modifier_keys xkb_symbols "iipa" { name[Group1]= "Indic IPA (IIPA)"; key { [ 1, exclam] }; key { [ 2, at] }; key { [ 3, numbersign] }; key { [ 4, U20B9] }; key { [ 5, percent] }; key { [ 6, asciicircum] }; key { [ 7, ampersand] }; key { [ 8, asterisk] }; key { [ 9, parenleft] }; key { [ 0, parenright] }; key { [ minus, underscore] }; key { [ equal, plus] }; key { [ U02B0, U02B1] }; // [ʰ], [ʱ] key { [ U00E6, q] }; // [æ], [q] found in Urdu key { [ a, U028B] }; // [a], [ʋ] key { [ i, U026A] }; // [i] [ɪ] key { [ u, U026F] }; // [u] [ɯ] found in Tamil key { [ b, Y] }; // [b] key { [ h, U014B] }; // [h], [ŋ] key { [ g, U0263] }; // [g], [ɣ] found in Urdu key { [ d, U00F0] }; // [d], [ð] found in Malayalam key { [ U02A4, U02A3] }; // [ʤ], [ʣ] found in Marathi key { [ U0256, U027D] }; // [ɖ], [ɽ] key { [ bracketleft, bracketright] }; // "[", "]" needed for denoting phonetic symbols key { [ o, U0254] }; // [o], [ɔ] found in Bangla key { [ e, U025B] }; // [e], [ɛ] key { [ U0259, U0361] }; // [ə], [ ͡ ] key { [ i, U026A] }; // [i], [ɪ] key { [ u, U026F] }; // [u], [ɯ] key { [ p, f] }; // [p], [f] key { [ U027E, r] }; // [ɾ], [r] key { [ k, x] }; // [k], [x] found in Urdu key { [ t, U03B8] }; // [t], [θ] key { [ U02A7, U02A6] }; // [ʧ], [ʦ] found in Marathi key { [ U0288, quotedbl] }; // [ʈ] key { [ grave, asciitilde] }; key { [ backslash, bar] }; key { [ U032A, U0303] }; // [ ̪], [ ̃] Dental mark, nasalisation mark key { [ U0306, X] }; // [ ̆] Short sound key { [ m, U0273] }; // [m], [ɳ] key { [ n, v] }; // [n], [v] key { [ w, z] }; // [w], [z] key { [ l, U026D] }; // [l], [ɭ] key { [ s, U0283] }; // [s], [ʃ] key { [ comma, U0282] }; // [ʂ] key { [ period, U02D0] }; // [ː] Long sound key { [ j, slash] }; // [j] }; // This layout is developed by Niranjan Tambe in July 2019 // for typing Marathi language with some necessary symbols. xkb_symbols "marathi" { name[Group1]="मराठी इन्स्क्रिप्ट"; key { [ U0962, U090C, grave, asciitilde ] }; // Added ॢ & ऌ key { [ U0967, exclam, 1, exclam ] }; // Added exclamation mark key { [ U0968, U0945, 2, at ] }; // Added ॅ key { [ U0969, U093D, 3, numbersign ] }; // Added ऽ key { [ U096a, U20B9, 4 ] }; // Added ₹ key { [ U096b, percent, 5, percent ] }; key { [ U096c, asciicircum, 6, asciicircum ] }; key { [ U096d, U0970, 7, ampersand ] }; // Added ॰ key { [ U096e, U0950, 8, asterisk ] }; key { [ U096f, parenleft, 9, parenleft ] }; key { [ U0966, parenright, 0, parenright ] }; key { [ minus, U0903, minus, underscore ] }; key { [ U0943, U090b, U0944, U0960 ] }; key { [ U094c, U0914 ] }; key { [ U0948, U0910 ] }; key { [ U093e, U0906 ] }; key { [ U0940, U0908, U0963, U0961 ] }; key { [ U0942, U090a ] }; key { [ U092c, U092d ] }; key { [ U0939, U0919 ] }; key { [ U0917, U0918, U095a ] }; key { [ U0926, U0927 ] }; key { [ U091c, U091d, U095b ] }; key { [ U0921, U0922, U095c, U095d ] }; key { [ U093c, U091e ] }; key { [ U0949, U0911, U005C, U007C ] }; key { [ U094b, U0913 ] }; key { [ U0947, U090f ] }; key { [ U094d, U0905 ] }; key { [ U093f, U0907, U0962, U090c ] }; key { [ U0941, U0909 ] }; key { [ U092a, U092b, NoSymbol, U095e ] }; key { [ U0930, U0931 ] }; key { [ U0915, U0916, U0958, U0959 ] }; key { [ U0924, U0925 ] }; key { [ U091a, U091b, U0952 ] }; key { [ U091f, U0920, NoSymbol, U0951 ] }; key { [ apostrophe, U0972, U0953 ] }; // Added apostrophe & ॲ key { [ U0902, U0901, NoSymbol, U0950 ] }; key { [ U092e, U0923, U0954 ] }; key { [ U0928, quotedbl ] }; // Added " key { [ U0935, UA8FB ] }; // Added headstroke key { [ U0932, U0933 ] }; key { [ U0938, U0936 ] }; key { [ comma, U0937, U0970 ] }; key { [ period, U0964, U0965, U093d ] }; key { [ U092f, question, slash, question ] }; }; // EXTRAS: // Modi is an ancient Indian script that is used to write texts in Marathi, Hindi and Sanskrit. // This keyboard layout is Based on Marathi KaGaPa phonetic layout. Just the characters which are not applicable in modi, are ommited. // // Author : D.Abhi // // partial alphanumeric_keys xkb_symbols "modi-kagapa" { name[Group1] = "Modi (KaGaPa phonetic)"; key.type="FOUR_LEVEL"; // Roman digits key { [ apostrophe, asciitilde, U201C ] }; // U201C: left double quotation mark key { [ 1, exclam, U11651 ] }; key { [ 2, at, U11652, U20A8 ] }; // U20A8: generic rupee sign (Rs) key { [ 3, numbersign, U11653 ] }; key { [ 4, dollar, U11654, U20B9 ] }; // U20B9: new Indian rupee sign key { [ 5, percent, U11655 ] }; key { [ 6, asciicircum, U11656, U200C ] }; // ZWNJ key { [ 7, ampersand, U11657, U200D ] }; // ZWJ key { [ 8, asterisk, U11658 ] }; key { [ 9, parenleft, U11659 ] }; key { [ 0, parenright, U11650, U11643 ] }; // U11643: Modi abbreviation sign key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ U005C, U007C, U11641, U11642 ] }; // backslash, pipe, Modi danda, Modi double danda //Q Row key { [ U11618, U11619 ] }; // Q: retroflex Modi letter Ta, Tha key { [ U1161A, U1161B ] }; // W: retroflex Modi letter Da, Dha key { [ U11639, U1160A, U1160B ] }; // E: Modi vovel sign E, Modi letter E, letter ai key { [ U11628, U11635, U11606 ] }; // R: Modi ra, Modi vowel sign vocalic R, vocalic letter R key { [ U1161D, U1161E ] }; // T: dental Modi letter ta, tha key { [ U11627, U1163A ] }; // Y: Modi letter ya, Modi vowel sign ai key { [ U11633, U11634, U11604, U11605 ] }; // U: Modi vowel sign u, uu, Modi letter u, uu key { [ U11631, U11632, U11602, U11603 ] }; // I: Modi vowel sign i, ii, Modi letter i, ii key { [ U1163B, U1160C ] }; // O: Modi vowel sign o, Modi letter o key { [ U11622, U11623 ] }; // P: Modi letter pa, pha key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; //A Row key { [ U11630, U11601, U11600 ] }; // A: Modi vowel sign aa, Modi letter aa, Modi letter a key { [ U1162D, U1162B ] }; // S: Modi letter sa, sha key { [ U1161F, U11620 ] }; // D: dental Modi letter da, dha key { [ U1163F, U11636, U11607 ] }; // F: Modi sign virama, Modi vowel sign vocalic RR, letter vocalic RR key { [ U11610, U11611 ] }; // G: Modi letter ga, gha key { [ U1162E, U1163E ] }; // H: Modi letter ha, Modi visarga key { [ U11615, U11616 ] }; // J: Modi letter ja, jha key { [ U1160E, U1160F ] }; // K: Modi letter ka, kha key { [ U11629, U1162F, U11637, U11608 ] }; // L: Modi letter la, lla, Modi vowel sign vocalic L, letter vocalic L key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; //Z Row key { [ U11617, U11612 ] }; // Z: Modi letter nya, nga key { [ U1162C, U11609, U11638 ] }; // X: Modi letter ssa, Modi letter vocalic ll, Modi vowel sign vocalic ll key { [ U11613, U11614 ] }; // C: Modi letter ca, cha key { [ U1162A, U1163C, U1160D ] }; // V: Modi letter va, Modi vowel sign au, Modi letter au key { [ U11624, U11625 ] }; // B: Modi letter ba, bha key { [ U11621, U1161C ] }; // N: Modi letter na, nna key { [ U11626, U1163D, U093D, U0950 ] }; // M: Modi ma, Modi anusvara, avagraha, Devanagari OM key { [ comma, U003C, U11640, U11644 ] }; // comma: comma, less than, Modi chandrabindu, Modi sign huva key { [ period, U003E ] }; // period: period, greater than, matra, candra o key { [ slash, question ] }; include "level3(ralt_switch)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/inet000066400000000000000000001746571510033435100231510ustar00rootroot00000000000000// EAK (Easy Access keyboards: Internet, Multimedia, PDA) // Copyright (C) 2002 Stanislav Brabec // // Based on the LinEAK project. // LinEAK - Linux support for Easy Access and Internets // Copyright (C) 2001, 2002 Mark Smulders // Usage in XF86Config: // Option "XkbLayout" "my_kb_layout" // Option "XkbVariant" "my_kb_variant" // Option "XkbModel" "my_eak_type" // Option "XkbRules" "xfree86" // Simple command line usage: // setxkbmap 'my_kb_layout' -variant 'my_kb_variant' -model 'my_eak_type' // Very common set of media keys. hidden partial alphanumeric_keys xkb_symbols "media_common" { key { [ XF86AudioMedia ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86Eject ] }; key { [ XF86Eject ] }; }; // Popular web navigation keys. hidden partial alphanumeric_keys xkb_symbols "nav_common" { key { [ XF86Calculator ] }; key { [ XF86WWW ] }; key { [ XF86Search ] }; key { [ XF86Favorites ] }; key { [ XF86Reload ] }; key { [ XF86Stop ] }; key { [ XF86Forward ] }; key { [ XF86Back ] }; key { [ XF86MyComputer ] }; key { [ XF86Mail ] }; key { [ XF86AudioMedia ] }; }; // ACPI Standard hidden partial alphanumeric_keys xkb_symbols "acpi_common" { key { [ XF86PowerOff ] }; key { [ XF86Standby ] }; key { [ XF86WakeUp ] }; key { [ XF86Battery ] }; key { [ XF86WLAN ] }; key { [ XF86Sleep ] }; }; // Combined sections, for simplicity. hidden partial alphanumeric_keys xkb_symbols "media_nav_common" { include "inet(media_common)" include "inet(nav_common)" }; hidden partial alphanumeric_keys xkb_symbols "media_nav_acpi_common" { include "inet(media_common)" include "inet(nav_common)" include "inet(acpi_common)" }; hidden partial alphanumeric_keys xkb_symbols "nav_acpi_common" { include "inet(nav_common)" include "inet(acpi_common)" }; hidden partial alphanumeric_keys xkb_symbols "media_acpi_common" { include "inet(media_common)" include "inet(acpi_common)" }; // Evdev Standardized Keycodes partial alphanumeric_keys xkb_symbols "evdev" { key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ XF86Open ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ Linefeed ] }; // Commented out because HZTG has same keycode as TLDE // key { [ Zenkaku_Hankaku ] }; key { [ Hiragana_Katakana ] }; key { [ Henkan ] }; key { [ Muhenkan ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Romaji ] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ XF86AudioMicMute ] }; // key { [ ] }; // KEY_MACRO key { [ plusminus ] }; key { [ XF86LaunchA ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; // key { [ ] }; // KEY_SETUP key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; // key { [ ] }; // KEY_DELETEFILE key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86TaskPane ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; // key { [ ] }; // KEY_CLOSECD (opposite of eject) key { [ XF86Eject ] }; key { [ XF86Eject, XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; // key { [ ] }; // KEY_ISO key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; // key { [ ] }; // KEY_MOVE // key { [ ] }; // KEY_EDIT key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86LaunchA ] }; key { [ XF86LaunchC ] }; key { [ XF86LaunchD ] }; key { [ XF86LaunchE ] }; key { [ XF86LaunchF ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; // key { [ ] }; // KEY_BASSBOOST key { [ Print ] }; // key { [ ] }; // KEY_HP key { [ XF86WebCam ] }; key { [ XF86AudioPreset ] }; // key { [ ] }; // KEY_QUESTION key { [ XF86Mail ] }; key { [ XF86Messenger ] }; // KEY_CHAT key { [ XF86Search ] }; key { [ XF86Go ] }; // KEY_CONNECT key { [ XF86Finance ] }; key { [ XF86Game ] }; // KEY_SPORT key { [ XF86Shop ] }; // key { [ ] }; // KEY_ALTERASE key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; // KEY_KBDILLUMTOGGLE key { [ XF86KbdBrightnessDown ] }; // KEY_KBDILLUMDOWN key { [ XF86KbdBrightnessUp ] }; // KEY_KBDILLUMUP key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; // key { [ ] }; // KEY_VIDEO_NEXT -- drive next video source // key { [ ] }; // KEY_VIDEO_PREV -- drive previous video source key { [ XF86MonBrightnessCycle ] }; // KEY_BRIGHTNESS_CYCLE -- bright up, max++ == min // key { [ ] }; // KEY_BRIGHTNESS_ZERO -- brightness off // key { [ ] }; // KEY_DISPLAY_OFF -- turn off display key { [ XF86WWAN ] }; // KEY_WWAN key { [ XF86RFKill ] }; // KEY_RFKILL key { [ XF86Favorites ] }; key { [ XF86Keyboard ] }; key { [ XF86RotationLockToggle ] }; key { [ XF86FullScreen ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; }; // Acer // Acer AirKey V partial alphanumeric_keys xkb_symbols "airkey" { include "inet(acpi_common)" key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86Mail ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioMute ] }; key { [ XF86WWW ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86Terminal ] }; key { [ XF86AudioStop, XF86Eject ] }; }; // Acer C300 laptop partial alphanumeric_keys xkb_symbols "acer_c300" { include "inet(nav_common)" key { [ F14 ] }; key { [ F13 ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86Launch2 ] }; key { [ Help ] }; key { [ XF86Launch1 ] }; }; // Acer Ferrari 4000 Keyboard // From Alex Dubov partial alphanumeric_keys xkb_symbols "acer_ferrari4k" { include "inet(media_nav_common)" key { [ dollar ] }; key { [ EuroSign ] }; key { [ XF86Display ] }; // Missing keycodes - set-up with setkeycodes key { [ Help ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; }; // Acer laptop (Generic layout for Acer laptops from 2004 onwards) // From Carlos Corbacho // Keys marked (HAL) require HAL 0.5.10 (or newer) to be set up correctly // (Your laptop must also be added to hal-info) // (Not all these keys will be available on every Acer laptop) partial alphanumeric_keys xkb_symbols "acer_laptop" { include "inet(media_nav_acpi_common)" key { [ XF86Launch2 ] }; // "P" or "P2" (HAL) key { [ XF86Launch1 ] }; // "e" or "P1" (HAL) // Hotkeys (Function) // Launch Keys // Device keys key { [ XF86Display ] }; // Fn+F5 (HAL) key { [ XF86Launch4 ] }; // Fn+F3 (HAL) key { [ XF86LaunchB ] }; // Bluetooth (HAL) key { [ XF86LaunchA ] }; // Wireless (HAL) key { [ Help ] }; // Fn+F1 (HAL) key { [ XF86Launch5 ] }; // Fn+F7 (HAL) key { [ XF86Launch3 ] }; // Fn+F2 (HAL) // Special Characters // To avoid setting a precedent/standard that will be broken in later // versions of HAL, these keys are commented out for now. When they are no // longer marked 'FIXME' and have saner keycodes, these two entries can be // fixed and permanently uncommented. In the meantime, just uncomment these // to make the keys work. // key { [ EuroSign ] }; // Euro (HAL) // key { [ dollar ] }; // Dollar (HAL) }; // Azona // Azona RF2300 wireless Internet partial alphanumeric_keys xkb_symbols "azonaRF2300" { // From Radics Laszlo include "inet(nav_acpi_common)" key { [ XF86HomePage ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Copy ] }; key { [ XF86Cut ] }; // key { [ XF86Paste ] }; }; // Brother // Brother Internet partial alphanumeric_keys xkb_symbols "brother" { include "inet(acpi_common)" key { [ XF86ScrollUp ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86ScrollDown ] }; key { [ XF86ZoomOut ] }; key { [ XF86AudioMute ] }; key { [ XF86WWW ] }; key { [ Menu ] }; key { [ XF86AudioStop ] }; key { [ XF86Calculator ] }; key { [ XF86Xfer ] }; key { [ XF86Mail ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86ZoomIn ] }; key { [ XF86AudioLowerVolume ] }; }; // BTC // BTC 5113RF Multimedia partial alphanumeric_keys xkb_symbols "btc5113rf" { include "inet(acpi_common)" key { [ XF86AudioStop ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86Favorites ] }; key { [ XF86Eject ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86Back ] }; key { [ XF86WWW ] }; key { [ XF86Search ] }; }; // BTC 9000 partial alphanumeric_keys xkb_symbols "btc9000" { include "inet(acpi_common)" key { [ XF86AudioStop ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86Favorites ] }; key { [ XF86AudioMedia ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86Reload ] }; key { [ XF86Mail ] }; key { [ XF86HomePage ] }; key { [ XF86Search ] }; }; // BTC 9000A partial alphanumeric_keys xkb_symbols "btc9000a" { include "inet(acpi_common)" key { [ XF86AudioStop ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86Favorites ] }; key { [ XF86Eject ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86HomePage ] }; key { [ Help ] }; key { [ XF86WWW ] }; key { [ XF86Search ] }; }; // BTC 9001AH xkb_symbols "btc9001ah" { include "inet(acpi_common)" key { [ XF86HomePage ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Mail ] }; key { [ XF86Eject ] }; }; // BTC 5090 partial alphanumeric_keys xkb_symbols "btc5090" { include "inet(media_nav_acpi_common)" key { [ XF86Start ] }; key { [ XF86Eject ] }; }; // BTC 9019U partial alphanumeric_keys xkb_symbols "btc9019u" { include "inet(media_nav_acpi_common)" key { [ XF86Search ] }; key { [ XF86HomePage ] }; }; // Cherry // Cherry Blue Line CyBo@rd partial alphanumeric_keys xkb_symbols "cherryblue" { include "inet(nav_common)" key { [ XF86Reload ] }; key { [ XF86HomePage ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Standby ] }; key { [ XF86Terminal ] }; key { [ XF86Go ] }; }; // Cherry CyMotion Master XPress partial alphanumeric_keys xkb_symbols "cherryblueb" { include "inet(media_nav_common)" key { [ XF86Reload ] }; key { [ XF86HomePage ] }; key { [ XF86Forward ] }; key { [ XF86Back ] }; key { [ XF86Copy ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ XF86Cut ] }; key { [ XF86Paste ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Book ] }; key { [ XF86Finance ] }; key { [ XF86Standby ] }; key { [ XF86AudioRewind ] }; key { [ XF86Eject ] }; key { [ XF86Book ] }; key { [ XF86Book ] }; key { [ XF86Terminal ] }; key { [ XF86Go ] }; }; // Cherry Blue Line CyBo@rd (alt.) partial alphanumeric_keys xkb_symbols "cherrybluea" { include "inet(media_nav_acpi_common)" key { [ XF86Go ] }; }; // Cherry CyBo@rd USB-Hub partial alphanumeric_keys xkb_symbols "cherrycyboard" { include "inet(media_nav_acpi_common)" key { [ XF86Search ] }; key { [ XF86HomePage ] }; key { [ XF86Terminal ] }; key { [ XF86AudioMedia ] }; }; // Cherry CyMotion Expert partial alphanumeric_keys xkb_symbols "cherrycmexpert" { include "inet(cherryblueb)" include "inet(acpi_common)" key { [ XF86Mail ] }; }; // Chicony // Chicony Internet partial alphanumeric_keys xkb_symbols "chicony" { include "inet(acpi_common)" key { [ XF86AudioMute ] }; key { [ XF86Mail ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86Forward ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioStop ] }; key { [ XF86Back ] }; key { [ XF86LaunchB ] }; key { [ XF86LaunchC ] }; key { [ XF86LaunchA ] }; key { [ XF86WWW ] }; key { [ XF86ContrastAdjust ] }; key { [ XF86BrightnessAdjust ] }; }; // Chicony KU-0108 partial alphanumeric_keys xkb_symbols "chicony0108" { include "inet(cherrycyboard)" }; // Chicony KU-0420 AKA Targus Slim Internet Media USB Keyboard partial alphanumeric_keys xkb_symbols "chicony0420" { include "inet(media_nav_acpi_common)" key { [ XF86AudioMedia ] }; key { [ XF86MyComputer ] }; }; // Chicony KB-9885 partial alphanumeric_keys xkb_symbols "chicony9885" { include "inet(acpi_common)" key { [ XF86AudioMute ] }; key { [ XF86Mail ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86Forward ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioStop ] }; key { [ XF86Back ] }; key { [ XF86LaunchB ] }; key { [ XF86LaunchC ] }; key { [ XF86LaunchA ] }; key { [ XF86WWW ] }; }; // Compaq // Compaq Easy Access partial alphanumeric_keys xkb_symbols "compaqeak8" { key { [ XF86Community ] }; key { [ XF86Market ] }; key { [ XF86Meeting ] }; key { [ XF86Search ] }; key { [ XF86News ] }; key { [ XF86Mail ] }; key { [ XF86HomePage ] }; key { [ XF86WWW ] }; }; // Compaq Internet (7 keys) partial alphanumeric_keys xkb_symbols "compaqik7" { key { [ XF86LightBulb ] }; key { [ XF86Mail ] }; key { [ XF86Search ] }; key { [ Help ] }; key { [ XF86VendorHome ] }; key { [ XF86HomePage ] }; key { [ XF86Shop ] }; }; // Compaq Internet (13 keys) partial alphanumeric_keys xkb_symbols "compaqik13" { include "inet(media_acpi_common)" key { [ XF86Mail ] }; key { [ XF86Go ] }; key { [ XF86Search ] }; key { [ XF86WWW ] }; key { [ XF86Shop ] }; }; // Compaq Internet (18 keys) partial alphanumeric_keys xkb_symbols "compaqik18" { include "inet(media_acpi_common)" key { [ XF86LightBulb ] }; key { [ XF86Eject ] }; key { [ XF86Mail ] }; key { [ XF86Go ] }; key { [ XF86Search ] }; key { [ XF86WWW ] }; key { [ XF86VendorHome ] }; key { [ XF86Community ] }; key { [ XF86Shop ] }; key { [ Print ] }; }; // laptop/notebook Compaq (eg. Armada, Evo) laptop Keyboard partial alphanumeric_keys xkb_symbols "armada" { include "inet(media_acpi_common)" key { [ XF86Search ] }; key { [ XF86Mail ] }; key { [ XF86HomePage ] }; key { [ XF86WWW ] }; key { [ XF86Launch2 ] }; // Battery Monitor key { [ XF86AudioMedia ] }; key { [ XF86Launch0 ] }; // Info Center }; // Compaq Presario laptop partial alphanumeric_keys xkb_symbols "presario" { include "inet(media_acpi_common)" key { [ XF86Q ] }; key { [ XF86Launch2 ] }; key { [ XF86Mail ] }; key { [ XF86Launch1 ] }; key { [ XF86WWW ] }; key { [ XF86Shop ] }; key { [ XF86AudioMedia ] }; }; // Compaq iPaq partial alphanumeric_keys xkb_symbols "ipaq" { key { [ XF86Shop ] }; key { [ XF86Standby ] }; key { [ XF86Search ] }; key { [ XF86Travel ] }; key { [ XF86BackForward ] }; key { [ XF86Q ] }; key { [ XF86Mail ] }; }; // Dell partial alphanumeric_keys xkb_symbols "dell" { include "inet(acpi_common)" key { [ XF86Mail ] }; key { [ XF86Search ] }; key { [ XF86HomePage ] }; }; // Dell Precision M65 laptop partial alphanumeric_keys xkb_symbols "dellm65" { include "inet(media_common)" key { [ XF86PowerOff ] }; key { [ Super_L ] }; }; // laptop/notebook Dell Inspiron 8xxx partial alphanumeric_keys xkb_symbols "inspiron" { include "inet(media_common)" key { [ XF86AudioStop ] }; key { [ XF86AudioNext ] }; key { [ XF86Eject ] }; key { [ XF86Display ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; }; // DELL USB Multimedia (former 8135, generalized, superset of 8125) partial alphanumeric_keys xkb_symbols "dellusbmm" { // Describes the extra keys on a SK-8135 Multimedia keyboard // From Olivier Lahaye include "inet(media_nav_acpi_common)" key { [ XF86HomePage ] }; key { [ XF86MyComputer ] }; key { [ XF86AudioMedia ] }; }; // Diamond // Diamond 9801/9802 partial alphanumeric_keys xkb_symbols "diamond" { include "inet(media_nav_acpi_common)" key { [ XF86Go ] }; }; // Ennyah // Ennyah DKB-1008 partial alphanumeric_keys xkb_symbols "ennyah_dkb1008" { include "inet(media_nav_acpi_common)" key { [ XF86AudioMedia ] }; }; // Genius // Genius Comfy KB-16M/Multimedia KWD-910 partial alphanumeric_keys xkb_symbols "genius" { include "inet(media_acpi_common)" key { [ XF86AudioRaiseVolume ] }; key { [ XF86Calculator ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86Forward ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86Back ] }; key { [ XF86ScreenSaver ] }; key { [ XF86Mail ] }; key { [ XF86Eject ] }; key { [ XF86WWW ] }; }; // Genius Comfy 21e partial alphanumeric_keys xkb_symbols "geniuscomfy2" { // Describes the extra keys on a Genius Comfy KB-21e-Scroll // From Radics Laszlo include "inet(media_nav_acpi_common)" key { [ Return ] }; }; // Gyration partial alphanumeric_keys xkb_symbols "gyration" { include "inet(nav_common)" key { [ XF86Reload ] }; key { [ XF86HomePage ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; }; // Hewlett-Packard // Hewlett-Packard Internet partial alphanumeric_keys xkb_symbols "hpi6" { include "inet(media_nav_acpi_common)" key { [ XF86HomePage ] }; key { [ XF86Search ] }; key { [ XF86VendorHome ] }; key { [ XF86Community ] }; key { [ XF86AudioMedia ] }; key { [ XF86Eject ] }; key { [ XF86Shop ] }; key { [ XF86Launch1 ] }; key { [ Help ] }; key { [ XF86Finance ] }; key { [ Print ] }; key { [ Help ] }; }; // Hewlett-Packard SK-2501, SK-2505 Multimedia partial alphanumeric_keys xkb_symbols "hp250x" { key { [ XF86Tools ] }; key { [ XF86Search ] }; key { [ XF86Eject ] }; key { [ XF86Mail ] }; key { [ XF86AudioMute ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch4 ] }; key { [ XF86Standby ] }; key { [ Help ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86WWW ] }; }; // Hewlett-Packard Omnibook XE3 GC, GD, GE and Pavilion N5xxx partial alphanumeric_keys xkb_symbols "hpxe3gc" { // Describes the OneTouch buttons on HP Omnibook XE3 GC and // HP Pavilion N52XX models. // See http://sourceforge.net/projects/omke for details on enabling // these keys include "inet(media_common)" key { [ Help ] }; key { [ XF86Launch1 ] }; key { [ XF86WWW ] }; key { [ XF86Mail ] }; }; // Hewlett-Packard Omnibook XE3 GF partial alphanumeric_keys xkb_symbols "hpxe3gf" { // Describes the OneTouch buttons on HP Omnibook XE3 GF models. // See http://sourceforge.net/projects/omke for details on enabling // these keys include "inet(media_nav_common)" key { [ Help ] }; key { [ XF86Launch1 ] }; }; // Hewlett-Packard Omnibook XT1000 partial alphanumeric_keys xkb_symbols "hpxt1000" { // Describes the OneTouch buttons on HP Omnibook XT1000 models. // See http://sourceforge.net/projects/omke for details on enabling // these keys include "inet(media_nav_common)" key { [ XF86Launch3 ] }; key { [ Help ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch1 ] }; }; // Hewlett-Packard Pavilion ZT1100 partial alphanumeric_keys xkb_symbols "hpzt11xx" { // Describes the OneTouch buttons on HP Pavilion ZT11xx models. // See http://sourceforge.net/projects/omke for details on enabling // these keys include "inet(media_nav_common)" key { [ XF86Launch3 ] }; key { [ Help ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch1 ] }; }; // Hewlett-Packard Pavilion dv5 partial alphanumeric_keys xkb_symbols "hpdv5" { // Describes the OneTouch buttons on HP Pavilion dv5 models. // See http://sourceforge.net/projects/omke for details on enabling // these keys include "inet(media_common)" key { [ XF86ScreenSaver ] }; key { [ XF86WWW ] }; key { [ Help ] }; key { [ XF86Launch1 ] }; }; // Hewlett-Packard Omnibook XE4xxx and ZE4xxx partial alphanumeric_keys xkb_symbols "hpxe4xxx" { // Describes the OneTouch buttons on HP Omnibook XE4xxx and ZE4xxx // models. // See http://sourceforge.net/projects/omke for details on enabling // these keys include "inet(media_nav_common)" key { [ Help ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch1 ] }; }; // Hewlett-Packard Omnibook 500 FA partial alphanumeric_keys xkb_symbols "hp500fa" { // Describes the OneTouch buttons on HP Omnibook 500 FA models. // See http://sourceforge.net/projects/omke for details on enabling // these keys key { [ Help ] }; key { [ XF86Launch1 ] }; }; // Hewlett-Packard Omnibook 500 partial alphanumeric_keys xkb_symbols "hp5xx" { // Describes the OneTouch buttons on HP Omnibook 5xx models. // See http://sourceforge.net/projects/omke for details on enabling // these keys include "inet(media_common)" key { [ Help ] }; key { [ XF86Launch1 ] }; }; // Honeywell // Honeywell Euroboard partial alphanumeric_keys xkb_symbols "honeywell_euroboard" { // January 2002 // Scott Penrose // http://linux.dd.com.au/quest/linux/keyboard/honeywell/ key { [ XF86Game ] }; key { [ XF86AudioPrev ] }; key { [ XF86Eject ] }; key { [ XF86Launch2 ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86Launch1 ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioStop ] }; key { [ XF86Mail ] }; key { [ XF86ScreenSaver ] }; key { [ XF86Calculator ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86WWW ] }; }; // IBM // IBM Rapid Access partial alphanumeric_keys xkb_symbols "rapidaccess" { key { [ XF86AudioMute ] }; key { [ XF86Launch2 ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPause ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop ] }; key { [ XF86Standby ] }; key { [ Help ] }; key { [ XF86Launch4 ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch1 ] }; }; // IBM Rapid Access II partial alphanumeric_keys xkb_symbols "rapidaccess2" { include "inet(acpi_common)" key { [ XF86AudioNext ] }; key { [ XF86Favorites ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPrev ] }; key { [ XF86HomePage ] }; key { [ XF86Shop ] }; key { [ XF86Search ] }; key { [ XF86MyComputer ] }; key { [ XF86VendorHome ] }; }; // IBM ThinkPad 60 series partial alphanumeric_keys xkb_symbols "thinkpad60" { include "inet(media_nav_common)" key { [ XF86VendorHome ] }; }; // IBM Space Saver partial alphanumeric_keys xkb_symbols "ibm_spacesaver" { key { type="ONE_LEVEL", symbols[Group1]= [ Num_Lock ] }; }; // Logitech // Logitech common definitions hidden partial alphanumeric_keys xkb_symbols "logitech_base" { include "inet(media_nav_acpi_common)" key { [ XF86HomePage ] }; key { [ XF86Community ] }; key { [ XF86ScrollClick ] }; key { [ XF86VendorHome ] }; key { [ XF86New ] }; key { [ XF86Reply ] }; key { [ XF86MyComputer ] }; key { [ XF86Documents ] }; key { [ XF86Pictures ] }; key { [ XF86Music ] }; }; // Logitech second set of common keys hidden partial alphanumeric_keys xkb_symbols "logitech_set3" { key { [ XF86AudioStop ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86New ] }; // F1 key { [ XF86Reply ] }; // F2 key { [ XF86Send ] }; // F4 key { [ Print ] }; // F7 key { [ XF86Save ] }; // F8 key { [ XF86Documents ] }; // F10 key { [ XF86Go ] }; key { [ XF86AudioMedia ] }; }; // Logitech Access partial alphanumeric_keys xkb_symbols "logiaccess" { include "inet(logitech_base)" key { [ XF86MailForward ] }; key { [ XF86Send ] }; key { [ XF86Messenger ] }; key { [ XF86WebCam ] }; }; // Logitech Cordless Desktop (alt.) partial alphanumeric_keys xkb_symbols "logicda" { include "inet(logitech_base)" include "inet(logitech_set3)" }; // Logitech Internet Navigator partial alphanumeric_keys xkb_symbols "logicink" { include "inet(logitech_base)" key { [ XF86Shop ] }; key { [ XF86VendorHome ] }; key { [ XF86Finance ] }; key { [ XF86Start ] }; }; // Logitech Cordless Desktop EX110 partial alphanumeric_keys xkb_symbols "logiex110" { include "inet(logitech_base)" key { [ XF86Close ] }; // Close // Extended function keys // In the Console before starting X // Using setkeycodes e03b 212 e03c 213 e03d 214 e03e 215 e03f 216 e040 217 // setkeycodes e041 218 e042 219 e043 220 e044 221 e057 222 e058 223 6d 206 // *=keys that are there but need different symbol names. key { [ Help ] }; // F1 key { [ XF86Word ] }; // F2 key { [ XF86Excel ] }; // F3 key { [ XF86Pictures ] }; // F4 key { [ Undo ] }; // F5 key { [ Redo ] }; // F6 * key { [ Print ] }; // F7 key { [ XF86Save ] }; // F8 key { [ XF86Launch1 ] }; // F9 * key { [ XF86Launch2 ] }; // F10 key { [ XF86Launch3 ] }; // F11 key { [ XF86Launch4 ] }; // F12 }; // Logitech iTouch Internet Navigator SE partial alphanumeric_keys xkb_symbols "logiinkse" { include "inet(logitech_base)" key { [ XF86MailForward ] }; // F3 key { [ XF86Send ] }; // F4 key { [ Undo ] }; // F5 key { [ Redo ] }; // F6 key { [ Print ] }; // F7 key { [ XF86Messenger ] }; key { [ XF86WebCam ] }; key { [ XF86VendorHome ] }; key { [ XF86Shop ] }; key { [ XF86Save ] }; // F8 }; // Logitech iTouch Internet Navigator SE USB partial alphanumeric_keys xkb_symbols "logiinkseusb" { include "inet(logitech_base)" include "inet(logitech_set3)" }; // Logitech iTouch Cordless Y-RB6 partial alphanumeric_keys xkb_symbols "logiitc" { include "inet(logitech_base)" key { [ XF86AudioRaiseVolume ] }; // Just to override RaiseVolume from logitech_base, // since no keysym can have two keycodes, see // https://bugs.freedesktop.org/show_bug.cgi?id=7095 key { [ XF86Launch1 ] }; }; // Logitech Internet partial alphanumeric_keys xkb_symbols "logiik" { include "inet(logitech_base)" key { [ Find ] }; key { [ Print ] }; key { [ XF86Favorites ] }; key { [ XF86Reload ] }; key { [ XF86Search ] }; key { [ XF86HotLinks ] }; key { [ XF86Forward ] }; key { [ XF86HomePage ] }; key { [ XF86Stop ] }; key { [ XF86OpenURL ] }; key { [ XF86AddFavorite ] }; key { [ XF86History ] }; key { [ XF86WWW ] }; }; // Logitech iTouch partial alphanumeric_keys xkb_symbols "itouch" { include "inet(logitech_base)" key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; }; // Logitech UltraX Cordless Media Desktop partial alphanumeric_keys xkb_symbols "logiultraxc" { key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioRaiseVolume ] }; }; partial alphanumeric_keys xkb_symbols "logidinovo" { include "inet(media_nav_common)" key { [ XF86HomePage ] }; key { [ XF86Standby ] }; key { [ XF86Search ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioMedia ] }; }; partial alphanumeric_keys xkb_symbols "logidinovoedge" { include "inet(media_acpi_common)" key { [ XF86HomePage ] }; key { [ XF86Mail ] }; key { [ XF86Search ] }; key { [ XF86AudioMedia ] }; }; partial alphanumeric_keys xkb_symbols "logitech_g15" { include "inet(media_nav_acpi_common)" key { [ XF86Messenger ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch9 ] }; key { [ XF86Phone ] }; key { [ XF86LaunchD ] }; key { [ XF86Support ] }; key { [ XF86LaunchF ] }; key { [ XF86LogOff ] }; key { [ XF86Launch5 ] }; key { [ XF86Travel ] }; key { [ XF86Spell ] }; key { [ XF86Launch4 ] }; key { [ XF86Music ] }; key { [ XF86Forward ] }; key { [ XF86Send ] }; key { [ XF86Save ] }; key { [ XF86Pictures ] }; key { [ XF86LaunchA ] }; key { [ XF86iTouch ] }; key { [ XF86Launch3 ] }; key { [ XF86ToDoList ] }; key { [ XF86Calculator ] }; key { [ XF86VendorHome ] }; key { [ XF86Away ] }; key { [ XF86WebCam ] }; key { [ XF86Launch0 ] }; key { [ XF86Launch6 ] }; key { [ XF86Calendar ] }; key { [ XF86LaunchB ] }; key { [ XF86LaunchC ] }; key { [ XF86WWW ] }; key { [ XF86LaunchE ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch8 ] }; }; // Memorex // Memorex MX1998 partial alphanumeric_keys xkb_symbols "mx1998" { include "inet(media_acpi_common)" key { [ XF86ScrollDown ] }; key { [ XF86AudioRewind ] }; key { [ XF86Close ] }; key { [ XF86Xfer ] }; key { [ XF86AudioRecord ] }; key { [ XF86Documents ] }; key { [ XF86Game ] }; key { [ XF86Calculator ] }; key { [ Menu ] }; key { [ XF86WWW ] }; key { [ XF86WakeUp ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86ScrollUp ] }; }; // Memorex MX2500 EZ-Access partial alphanumeric_keys xkb_symbols "mx2500" { include "inet(media_nav_acpi_common)" key { [ XF86Clear ] }; key { [ XF86Phone ] }; key { [ XF86DOS ] }; key { [ XF86Close ] }; key { [ XF86Xfer ] }; key { [ XF86Eject ] }; key { [ XF86Documents ] }; key { [ XF86News ] }; key { [ XF86WakeUp ] }; key { [ XF86RotateWindows ] }; }; // Memorex MX2750 partial alphanumeric_keys xkb_symbols "mx2750" { include "inet(media_nav_acpi_common)" key { [ XF86Launch0 ] }; }; // Microsoft // Microsoft Natural Ergonomic 4000 partial alphanumeric_keys xkb_symbols "microsoft4000" { include "inet(media_nav_common)" key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86Launch5 ] }; // Missing because of lack of support from kbd driver: Zoom in and // slider. }; // Microsoft Natural Wireless Ergonomic 7000 partial alphanumeric_keys xkb_symbols "microsoft7000" { include "inet(media_nav_common)" key { [ Undo ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86MailForward ] }; key { [ XF86Close ] }; key { [ Print ] }; key { [ XF86Save ] }; key { [ XF86Send ] }; key { [ Help ] }; key { [ XF86Reply ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ KP_Equal ] }; key { [ XF86Open ] }; // Missing because of lack of support from kbd driver: Spell, Launch, // and Zoom in and out buttons. }; // Microsoft Internet partial alphanumeric_keys xkb_symbols "microsoftinet" { include "inet(nav_acpi_common)" key { [ XF86AudioStop ] }; }; // Microsoft Natural Pro USB partial alphanumeric_keys xkb_symbols "microsoftprousb" { include "inet(nav_common)" key { [ XF86Reload ] }; key { [ XF86AudioMedia ] }; key { [ XF86HomePage ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Standby ] }; // Internet Section -- Left Side // Multimedia Section -- Right Side // My Computer Section -- Far Right // My computer maps to printscreen, so leaving commented out for now // key { [ XF86MyComputer ] }; }; // Microsoft Natural Pro OEM partial alphanumeric_keys xkb_symbols "microsoftprooem" { include "inet(media_nav_common)" key { [ XF86Search ] }; key { [ XF86HomePage ] }; key { [ XF86Standby ] }; key { [ XF86MyComputer ] }; // Internet Section -- Left Side // Multimedia Section -- Right Side // My Computer Section -- Far Right }; // Microsoft Internet Pro (Swedish) partial alphanumeric_keys xkb_symbols "microsoftprose" { include "inet(nav_common)" key { [ XF86Reload ] }; key { [ XF86HomePage ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Standby ] }; key { [ XF86AudioStop ] }; key { [ XF86MyComputer ] }; key { [ XF86AudioMedia ] }; }; // Microsoft Office Keyboard partial alphanumeric_keys xkb_symbols "microsoftoffice" { include "inet(nav_acpi_common)" key { [ XF86Calendar ] }; key { [ Undo ] }; key { [ XF86HomePage ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Cut ] }; key { [ XF86LogOff ] }; key { [ XF86ApplicationLeft ] }; key { [ XF86TaskPane ] }; key { [ XF86Spell ] }; key { [ XF86WWW ] }; key { [ XF86New ] }; key { [ XF86Open ] }; key { [ XF86Close ] }; key { [ Help ] }; key { [ XF86Save ] }; key { [ Print ] }; key { [ XF86OfficeHome ] }; key { [ Redo ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Send ] }; key { [ XF86Copy ] }; key { [ XF86ApplicationRight ] }; key { [ XF86Paste ] }; }; // Microsoft Wireless Multimedia 1.0A partial alphanumeric_keys xkb_symbols "microsoftmult" { include "inet(media_nav_acpi_common)" key { [ XF86Messenger ] }; key { [ XF86New ] }; key { [ XF86Open ] }; key { [ XF86Close ] }; key { [ XF86Reply ] }; key { [ Redo ] }; key { [ Undo ] }; key { [ XF86LogOff ] }; key { [ XF86Spell ] }; key { [ Help ] }; key { [ XF86Music ] }; key { [ XF86Forward ] }; key { [ XF86Send ] }; key { [ XF86Save ] }; key { [ Print ] }; key { [ XF86Pictures ] }; key { [ XF86Documents ] }; }; // Microsoft Surface partial alphanumeric_keys xkb_symbols "microsoftsurface" { include "inet(evdev)" key { [ XF86Search ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; }; // Oretec // Oretec MCK-800 MM/Internet keyboard partial alphanumeric_keys xkb_symbols "oretec" { include "inet(acpi_common)" key { [ XF86ScrollUp ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86ScrollDown ] }; key { [ XF86ZoomOut ] }; key { [ XF86AudioMute ] }; key { [ XF86WWW ] }; key { [ Menu ] }; key { [ XF86AudioStop ] }; key { [ XF86Calculator ] }; key { [ XF86Xfer ] }; key { [ XF86Mail ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86ZoomIn ] }; key { [ XF86AudioLowerVolume ] }; }; // Propeller // Propeller Voyager KTEZ-1000 partial alphanumeric_keys xkb_symbols "propeller" { include "inet(media_common)" key { [ XF86AudioRewind ] }; key { [ XF86Close ] }; key { [ XF86Xfer ] }; key { [ XF86AudioRecord ] }; key { [ XF86Documents ] }; key { [ XF86Game ] }; key { [ XF86Calculator ] }; key { [ Menu ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86Standby ] }; }; // QTronix // QTronix Scorpius 98N+ partial alphanumeric_keys xkb_symbols "qtronix" { key { [ XF86ScrollDown ] }; key { [ XF86Forward ] }; key { [ XF86WakeUp ] }; key { [ XF86Search ] }; key { [ XF86Standby ] }; key { [ XF86ScrollUp ] }; key { [ XF86Back ] }; key { [ XF86Reload ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioStop ] }; key { [ XF86HomePage ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRecord ] }; key { [ XF86PowerOff ] }; key { [ XF86Stop ] }; key { [ XF86Calculator ] }; }; // Samsung // Samsung SDM 4500P partial alphanumeric_keys xkb_symbols "samsung4500" { include "inet(media_nav_acpi_common)" key { [ XF86Launch4 ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch5 ] }; key { [ XF86Close ] }; key { [ XF86Book ] }; key { [ XF86Eject ] }; key { [ Help ] }; key { [ XF86Explorer ] }; key { [ XF86Launch2 ] }; }; // Samsung SDM 4510P partial alphanumeric_keys xkb_symbols "samsung4510" { include "inet(media_acpi_common)" key { [ XF86Launch1 ] }; key { [ XF86Launch3 ] }; key { [ XF86Eject ] }; key { [ XF86Launch2 ] }; }; // SK // NEC SK-1300 partial alphanumeric_keys xkb_symbols "sk1300" { include "inet(media_common)" key { [ XF86Eject ] }; key { [ XF86Forward ] }; key { [ XF86WWW ] }; key { [ XF86Standby ] }; key { [ XF86Back ] }; key { [ XF86Stop ] }; }; // NEC SK-2500 partial alphanumeric_keys xkb_symbols "sk2500" { include "inet(media_nav_common)" key { [ XF86AudioRewind ] }; key { [ XF86Close ] }; key { [ XF86Eject ] }; key { [ XF86Eject ] }; key { [ XF86Forward ] }; key { [ XF86AudioRecord ] }; key { [ XF86Xfer ] }; key { [ XF86PowerOff ] }; key { [ Menu ] }; key { [ XF86ScreenSaver ] }; }; // NEC SK-6200 partial alphanumeric_keys xkb_symbols "sk6200" { include "inet(acpi_common)" key { [ XF86Favorites ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86WWW ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop ] }; key { [ XF86Mail ] }; }; // NEC SK-7100 partial alphanumeric_keys xkb_symbols "sk7100" { include "inet(media_common)" key { [ XF86AudioPause ] }; key { [ XF86Close ] }; key { [ XF86Video ] }; key { [ XF86Eject ] }; key { [ XF86CD ] }; key { [ XF86Display ] }; key { [ XF86WWW ] }; }; // Sven // SVEN Ergonomic 2500 partial alphanumeric_keys xkb_symbols "sven" { include "inet(acpi_common)" key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86Forward ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86ZoomOut ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop ] }; key { [ XF86HomePage ] }; key { [ XF86Mail ] }; key { [ XF86ZoomIn ] }; key { [ XF86MyComputer ] }; key { [ XF86Stop ] }; key { [ XF86ScreenSaver ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Calculator ] }; key { [ XF86Reload ] }; key { [ XF86Search ] }; key { [ XF86Favorites ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ XF86AudioNext ] }; key { [ XF86Back ] }; }; // SVEN Slim 303 partial alphanumeric_keys xkb_symbols "sven303" { key { [ XF86PowerOff ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; }; // Symplon // Symplon PaceBook tablet partial alphanumeric_keys xkb_symbols "symplon" { include "inet(nav_acpi_common)" key { [ XF86RotationPB ] }; key { [ XF86SplitScreen ] }; key { [ XF86Support ] }; key { [ XF86New ] }; key { [ XF86User2KB ] }; key { [ XF86RotationKB ] }; key { [ XF86MenuKB ] }; key { [ XF86User1KB ] }; key { [ XF86UserPB ] }; key { [ XF86MenuPB ] }; }; // Toshiba // Toshiba Satellite S3000 partial alphanumeric_keys xkb_symbols "toshiba_s3000" { include "inet(media_common)" // Describes the Special buttons on Toshiba Satellite 3000 models. // See http://sourceforge.net/projects/omke for details on enabling // these keys key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86Mail ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioLowerVolume ] }; }; // Trust // Trust Wireless Classic partial alphanumeric_keys xkb_symbols "trust" { include "inet(media_nav_acpi_common)" key { [ XF86ScreenSaver ] }; key { [ XF86Eject ] }; }; // Trust Direct Access partial alphanumeric_keys xkb_symbols "trustda" { include "inet(media_common)" key { [ XF86AudioRewind ] }; key { [ XF86Close ] }; key { [ XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86Xfer ] }; key { [ XF86Standby ] }; key { [ Help ] }; key { [ XF86WWW ] }; key { [ XF86Away ] }; }; // YaHoo! // Yahoo! Internet partial alphanumeric_keys xkb_symbols "yahoo" { include "inet(acpi_common)" key { [ XF86AudioPrev ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioStop ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86AudioMute ] }; key { [ XF86Close ] }; key { [ XF86Calculator ] }; key { [ Help ] }; key { [ XF86Mail ] }; key { [ XF86WWW ] }; }; // Apple keyboards (macbooks, powerbooks, powermac G5, etc) partial alphanumeric_keys xkb_symbols "apple" { // Really brightness up/down key { [ XF86BrightnessAdjust ] }; key { [ XF86BrightnessAdjust ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86RotateWindows ] }; // Really keyboard backlight off/up/down key { [ XF86Launch0 ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86PowerOff ] }; key { [ F13 ] }; key { [ F14 ] }; key { [ F15 ] }; key { [ XF86Eject ] }; key { [ F16 ] }; key { [ KP_Equal ] }; }; partial alphanumeric_keys xkb_symbols "cymotionlinux" { include "inet(media_nav_acpi_common)" key { [ Undo ] }; key { [ Redo ] }; key { [ XF86ScrollDown ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch1 ] }; key { [ XF86MenuKB ] }; key { [ XF86Launch3 ] }; key { [ XF86Cut ] }; key { [ XF86Copy ] }; key { [ XF86Paste ] }; key { [ XF86ScrollUp ] }; key { [ XF86AudioMedia ] }; }; partial alphanumeric_keys xkb_symbols "silvercrest" { include "inet(media_nav_acpi_common)" key { [ XF86HomePage ] }; key { [ XF86Launch2 ] }; key { [ XF86Launch1 ] }; }; // eMachines partial alphanumeric_keys xkb_symbols "emachines" { include "inet(media_nav_acpi_common)" key { [ XF86iTouch ] }; key { [ KP_0 ] }; key { [ KP_1 ] }; key { [ KP_2 ] }; key { [ KP_3 ] }; key { [ KP_4 ] }; key { [ KP_5 ] }; key { [ KP_6 ] }; key { [ KP_7 ] }; key { [ KP_8 ] }; key { [ KP_9 ] }; key { [ KP_Add ] }; key { [ KP_Decimal ] }; key { [ KP_Divide ] }; key { [ KP_Multiply ] }; key { [ KP_Subtract ] }; }; // BenQ // BenQ X* (X730, X500, X800) // // To make the FN_LOCK and CONFIG key work on the BenQ X500 , use: // setkeycodes e074 130 # KEY_PROPS from /usr/include/linux/input.h // setkeycodes e075 171 # KEY_CONFIG from /usr/include/linux/input.h partial alphanumeric_keys xkb_symbols "benqx" { include "inet(media_nav_acpi_common)" key { [ XF86ModeLock ] }; key { [ XF86WWW ] }; key { [ XF86Go ] }; key { [ XF86Calendar ] }; }; // Intel // Intel Classmate partial alphanumeric_keys xkb_symbols "classmate" { key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; }; // Unitek partial alphanumeric_keys xkb_symbols "unitekkb1925" { include "inet(media_nav_common)" key { [ XF86AudioMute ] }; key { [ XF86PowerOff ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Search ] }; key { [ XF86Reload ] }; }; // Creative // Creative Desktop Wireless 7000 partial alphanumeric_keys xkb_symbols "creativedw7000" { include "inet(media_nav_acpi_common)" key { [ XF86Pictures ] }; }; // Compal // Compal FL90 partial alphanumeric_keys xkb_symbols "compalfl90" { include "inet(media_nav_acpi_common)" key { [ XF86MonBrightnessUp ] }; key { [ XF86MonBrightnessDown ] }; }; partial alphanumeric_keys xkb_symbols "pc105" { include "inet(media_nav_acpi_common)" }; partial alphanumeric_keys xkb_symbols "chromebook" { include "level3(ralt_switch)" key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Reload ] }; key { [ F11 ] }; // key { [ F5, F5, F5, F5 ] }; // Overview key key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ BackSpace, BackSpace, Delete ] }; key { [ Up, Up, Prior, Up ] }; key { [ Down, Down, Next, Down ] }; key { [ Left, Left, Home, Left ] }; key { [ Right, Right, End, Right ] }; key { [ Super_L, Super_L, Caps_Lock, Super_L ] }; }; partial alphanumeric_keys xkb_symbols "teck227" { include "inet(media_nav_common)" key { [ Hiragana ] }; }; partial alphanumeric_keys xkb_symbols "teck229" { include "inet(teck227)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/keypad000066400000000000000000000563161510033435100234560ustar00rootroot00000000000000default hidden partial keypad_keys xkb_symbols "x11" { include "keypad(operators)" key { [ KP_Home, KP_7 ] }; key { [ KP_Up, KP_8 ] }; key { [ KP_Prior, KP_9 ] }; key { [ KP_Left, KP_4 ] }; key { [ KP_Begin, KP_5 ] }; key { [ KP_Right, KP_6 ] }; key { [ KP_End, KP_1 ] }; key { [ KP_Down, KP_2 ] }; key { [ KP_Next, KP_3 ] }; key { [ KP_Enter ] }; key { [ KP_Equal ] }; key { [ KP_Insert, KP_0 ] }; key { [ KP_Delete, KP_Decimal ] }; key { [ KP_Decimal, KP_Decimal ] }; }; hidden partial keypad_keys xkb_symbols "overlay" { include "keypad(overlay1)" }; hidden partial keypad_keys xkb_symbols "overlay1" { key { [ KP_Home ], overlay1= }; key { [ KP_Up ], overlay1= }; key { [ KP_Prior ], overlay1= }; key { [ KP_Left ], overlay1= }; key { [ KP_Begin ], overlay1= }; key { [ KP_Right ], overlay1= }; key { [ KP_End ], overlay1= }; key { [ KP_Down ], overlay1= }; key { [ KP_Next ], overlay1= }; key { [ KP_Insert ], overlay1= }; key { [ KP_Delete ], overlay1= }; key { [ KP_7 ] }; key { [ KP_8 ] }; key { [ KP_9 ] }; key { [ KP_4 ] }; key { [ KP_5 ] }; key { [ KP_6 ] }; key { [ KP_1 ] }; key { [ KP_2 ] }; key { [ KP_3 ] }; key { [ KP_0 ] }; key { [ KP_Decimal ] }; }; hidden partial keypad_keys xkb_symbols "overlay2" { key { [ KP_Home ], overlay2= }; key { [ KP_Up ], overlay2= }; key { [ KP_Prior ], overlay2= }; key { [ KP_Left ], overlay2= }; key { [ KP_Begin ], overlay2= }; key { [ KP_Right ], overlay2= }; key { [ KP_End ], overlay2= }; key { [ KP_Down ], overlay2= }; key { [ KP_Next ], overlay2= }; key { [ KP_Insert ], overlay2= }; key { [ KP_Delete ], overlay2= }; key { [ KP_7 ] }; key { [ KP_8 ] }; key { [ KP_9 ] }; key { [ KP_4 ] }; key { [ KP_5 ] }; key { [ KP_6 ] }; key { [ KP_1 ] }; key { [ KP_2 ] }; key { [ KP_3 ] }; key { [ KP_0 ] }; key { [ KP_Decimal ] }; }; hidden partial keypad_keys xkb_symbols "operators" { // Puts some commands to control the X server on // the fifth level of the keypad's operator keys. key { type="CTRL+ALT", // Ungrab cancels server/keyboard/pointer grabs symbols[Group1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86_Ungrab ] }; key { type="CTRL+ALT", // ClsGrb kills whichever client has a grab in effect symbols[Group1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86_ClearGrab ] }; key { type="CTRL+ALT", // -VMode switches to the previous video mode symbols[Group1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86_Prev_VMode ] }; key { type="CTRL+ALT", // +VMode switches to the next video mode symbols[Group1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86_Next_VMode ] }; }; // Legacy PC keypad definition // Copyright © 2006-2007 Nicolas Mailhot keypad_keys xkb_symbols "legacy" { include "keypad(core)" include "keypad(legacymath)" include "keypad(legacynumber)" include "kpdl(dot)" }; // Legacy Wang 725-3771-ae and 725-3771-uk keypad definition // Copyright © 2006-2007 Nicolas Mailhot keypad_keys xkb_symbols "legacy_wang" { include "keypad(core)" include "keypad(legacymath)" include "keypad(legacynumber_wang)" include "kpdl(dot)" }; // Complete new keypad definition // Copyright © 2006-2007 Nicolas Mailhot keypad_keys xkb_symbols "oss" { include "keypad(core)" include "keypad(ossmath)" include "keypad(ossnumber)" include "kpdl(dotoss)" }; // Latin9 restriction of new keypad definition // Copyright © 2006-2007 Nicolas Mailhot keypad_keys xkb_symbols "oss_latin9" { include "keypad(core)" include "keypad(ossmath_latin9)" include "keypad(legacynumber)" include "kpdl(dotoss_latin9)" }; // Wang 725-3771-ae and 725-3771-uk keypad variant of oss keypad // Copyright © 2006-2007 Nicolas Mailhot keypad_keys xkb_symbols "oss_wang" { include "keypad(core)" include "keypad(ossmath)" include "keypad(ossnumber_wang)" include "kpdl(dotoss)" }; // Forward-looking keypad definition // Won't work with applications that make ASCII assumptions // Copyright © 2007 Nicolas Mailhot keypad_keys xkb_symbols "future" { include "keypad(core)" include "keypad(futuremath)" include "keypad(ossnumber)" include "kpdl(commaoss)" }; // Forward-looking keypad definition // Won't work with applications that make ASCII assumptions // Copyright © 2007 Nicolas Mailhot keypad_keys xkb_symbols "future_wang" { include "keypad(core)" include "keypad(futuremath)" include "keypad(ossnumber_wang)" include "kpdl(commaoss)" }; // Keypad keys nobody changes // Copyright © 2006 Nicolas Mailhot partial keypad_keys xkb_symbols "core" { modifier_map Mod2 { Num_Lock }; key { [ Num_Lock ] }; key { [ KP_Enter ] }; key { [ KP_Equal ] }; }; // Legacy keypad math area // Copyright © 2006 Nicolas Mailhot // // ┏━━━━━┱─────┬─────┬─────┐ // ┃Num ┃ ₁ │ ₂ │ ₃ │ ₁ // ┃Lock⇭┃ / │ * │ - │ ₂ // ┡━━━━━╃─────┼─────┼─────┤ ₃ // │ ₄ │ ₄ // │ │ // ┤ │ 1 None // │ │ 2 Ctrl+Alt // │ + │ // ╆━━━━━┪ partial keypad_keys xkb_symbols "legacymath" { key.type[Group1]="CTRL+ALT" ; key { [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86_Ungrab ] }; // / key { [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86_ClearGrab ] }; // * key { [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86_Prev_VMode ] }; // - key { [ KP_Add, KP_Add, KP_Add, KP_Add, XF86_Next_VMode ] }; // + }; // Keypad math area with non-CS operators // Copyright © 2006 Nicolas Mailhot // // ┏━━━━━┱─────┬─────┬─────┐ // ┃Num ┃ ∕ ₁ │ . ₂ │ − ₃ │ ₁ // ┃Lock⇭┃ / ÷ │ * × │ - − │ ₂ // ┡━━━━━╃─────┼─────┼─────┤ ₃ // │ + ₄ │ ₄ // │ │ // ┤ │ 1 None // │ │ 2 Level3 ⇮ // │ + + │ 3 Shift+Level3 ⇧⇮ // ╆━━━━━┪ 4 Ctrl+Alt partial keypad_keys xkb_symbols "ossmath" { key.type[Group1]="CTRL+ALT" ; key { [ KP_Divide, 0x1002215, 0x10000F7, VoidSymbol, XF86_Ungrab ] }; // / ∕ ÷ key { [ KP_Multiply, 0x10022C5, 0x10000D7, VoidSymbol, XF86_ClearGrab ] }; // * ⋅ × key { [ KP_Subtract, 0x1002212, 0x1002212, VoidSymbol, XF86_Prev_VMode ] }; // - − − key { [ KP_Add, 0x100002B, 0x100002B, VoidSymbol, XF86_Next_VMode ] }; // + + + }; // Keypad math area with non-CS operators in first levels // As demanded by users not interested in legacy pre-unicode junk // Copyright © 2007 Nicolas Mailhot // // ┏━━━━━┱─────┬─────┬─────┐ // ┃Num ┃ / ₁ │ * ₂ │ - ₃ │ ₁ // ┃Lock⇭┃ ∕ ÷ │ . × │ − − │ ₂ // ┡━━━━━╃─────┼─────┼─────┤ ₃ // │ + ₄ │ ₄ // │ │ // ┤ │ 1 None // │ │ 2 Level3 ⇮ // │ + + │ 3 Shift+Level3 ⇧⇮ // ╆━━━━━┪ 4 Ctrl+Alt partial keypad_keys xkb_symbols "futuremath" { key.type[Group1]="FOUR_LEVEL_X" ; key { [ 0x1002215, KP_Divide, 0x10000F7, XF86_Ungrab ] }; // ∕ / ÷ key { [ 0x10022C5, KP_Multiply, 0x10000D7, XF86_ClearGrab ] }; // ⋅ * × key { [ 0x1002212, KP_Subtract, 0x1002212, XF86_Prev_VMode ] }; // − - − key { [ 0x100002B, KP_Add, 0x100002B, XF86_Next_VMode ] }; // + + + }; // Keypad math area with non-CS operators, restricted to latin9 // Copyright © 2006 Nicolas Mailhot // // ┏━━━━━┱─────┬─────┬─────┐ // ┃Num ┃ / ₁ │ · ₂ │ - ₃ │ ₁ // ┃Lock⇭┃ / ÷ │ * × │ - - │ ₂ // ┡━━━━━╃─────┼─────┼─────┤ ₃ // │ + ₄ │ ₄ // │ │ // ┤ │ 1 None // │ │ 2 Level3 ⇮ // │ + + │ 3 Shift+Level3 ⇧⇮ // ╆━━━━━┪ 4 Ctrl+Alt partial keypad_keys xkb_symbols "ossmath_latin9" { key.type[Group1]="FOUR_LEVEL_X"; key { [ KP_Divide, slash, division, XF86_Ungrab ] }; // / / ÷ key { [ KP_Multiply, periodcentered, multiply, XF86_ClearGrab ] }; // * · × key { [ KP_Subtract, minus, minus, XF86_Prev_VMode ] }; // - - - key { [ KP_Add, plus, plus, XF86_Next_VMode ] }; // + + + }; // Legacy keypad number area // Copyright © 2006 Nicolas Mailhot // // ┏━━━━━┱ // ┃Num ┃ ⇱ Home // ┃Lock⇭┃ ⇲ End // ┡━━━━━╃─────┼─────┼ ⇞ Page up // │ 7 │ 8 │ 9 │ ⇟ Page down // │ ⇱ │ ⇧ │ ⇞ │ ⎀ Insert // ├─────┼─────┼─────┤ ␥ Delete // │ 4 │ 5 │ 6 │ ⇦⇧⇨⇩ Directions // │ ⇦ │ │ ⇨ │ // ├─────┼─────┼─────╆ // │ 1 │ 2 │ 3 ┃ // │ ⇲ │ ⇩ │ ⇟ ┃ 1 None // ├─────┴─────┼─────┨ 2 Num Lock ⇭ // │ 0 │ // │ ⎀ │ // └───────────┴ partial keypad_keys xkb_symbols "legacynumber" { key.type[Group1]="KEYPAD" ; key { [ KP_Home, KP_7 ] }; // 7 key { [ KP_Up, KP_8 ] }; // 8 key { [ KP_Prior, KP_9 ] }; // 9 key { [ KP_Left, KP_4 ] }; // 4 key { [ KP_Begin, KP_5 ] }; // 5 key { [ KP_Right, KP_6 ] }; // 6 key { [ KP_End, KP_1 ] }; // 1 key { [ KP_Down, KP_2 ] }; // 2 key { [ KP_Next, KP_3 ] }; // 3 key { [ KP_Insert, KP_0 ] }; // 0 }; // Legacy Wang 725-3771-ae and 725-3771-uk keypad number area // Copyright © 2007 Nicolas Mailhot // This is actually a three-level keypad, declared as four-level // to avoid defining a new type // // ┏━━━━━┱ // ┃Num ┃ ⇱ Home // ┃Lock⇭┃ ⇲ End // ┡━━━━━╃─────┼─────┼ ⇞ Page up // │ 7 │ 8 │ 9 │ ⇟ Page down // │ ⇱ < │ ⇧ > │ ⇞ ^ │ ⎀ Insert // ├─────┼─────┼─────┤ ␥ Delete // │ 4 │ 5 │ 6 │ ⇦⇧⇨⇩ Directions // │ ⇦ [ │ ] │ ⇨ $ │ // ├─────┼─────┼─────╆ // │ 1 │ 2 │ 3 ┃ // │ ⇲ & │ ⇩ @ │ ⇟ # ┃ 1 None // ├─────┴─────┼─────┨ 2 Num Lock ⇭ // │ 0 │ 3 Level3 ⇮ // │ ⎀ │ // └───────────┴ partial keypad_keys xkb_symbols "legacynumber_wang" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ KP_Home, KP_7, less ] }; // 7 < key { [ KP_Up, KP_8, greater ] }; // 8 > key { [ KP_Prior, KP_9, asciicircum ] }; // 9 ^ key { [ KP_Left, KP_4, bracketleft ] }; // 4 [ key { [ KP_Begin, KP_5, bracketright ] }; // 5 ] key { [ KP_Right, KP_6, dollar ] }; // 6 $ key { [ KP_End, KP_1, ampersand ] }; // 1 & key { [ KP_Down, KP_2, at ] }; // 2 @ key { [ KP_Next, KP_3, numbersign ] }; // 3 # key { [ KP_Insert, KP_0, apostrophe ] }; // 0 ' }; // Keypad number area with arrow symbols // Copyright © 2006 Nicolas Mailhot // // ┏━━━━━┱ // ┃Num ┃ ⇱ Home // ┃Lock⇭┃ ⇲ End // ┡━━━━━╃─────┼─────┼ ⇞ Page up // │ 7 ⇖ │ 8 ⇑ │ 9 ⇗ │ ⇟ Page down // │ ⇱ ↖ │ ⇧ ↑ │ ⇞ ↗ │ ⎀ Insert // ├─────┼─────┼─────┤ ␥ Delete // │ 4 ⇐ │ 5 ⇔ │ 6 ⇒ │ ⇦⇧⇨⇩ Directions // │ ⇦ ← │ ↔ │ ⇨ → │ ⍽ narrow no-break space // ├─────┼─────┼─────╆ // │ 1 ⇙ │ 2 ⇓ │ 3 ⇘ ┃ // │ ⇲ ↙ │ ⇩ ↓ │ ⇟ ↘ ┃ 1 None // ├─────┴─────┼─────┨ 2 Num Lock ⇭ // │ 0 ⇕ │ 3 Level3 ⇮ // │ ⎀ ↕ │ 4 Shift+Level3 ⇧⇮ // └───────────┴ partial keypad_keys xkb_symbols "ossnumber" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ KP_Home, KP_7, 0x1002196, 0x10021D6 ] }; // 7 ↖ ⇖ key { [ KP_Up, KP_8, 0x1002191, 0x10021D1 ] }; // 8 ↑ ⇑ key { [ KP_Prior, KP_9, 0x1002197, 0x10021D7 ] }; // 9 ↗ ⇗ key { [ KP_Left, KP_4, 0x1002190, 0x10021D0 ] }; // 4 ← ⇐ key { [ KP_Begin, KP_5, 0x1002194, 0x10021D4 ] }; // 5 ↔ ⇔ key { [ KP_Right, KP_6, 0x1002192, 0x10021D2 ] }; // 6 → ⇒ key { [ KP_End, KP_1, 0x1002199, 0x10021D9 ] }; // 1 ↙ ⇙ key { [ KP_Down, KP_2, 0x1002193, 0x10021D3 ] }; // 2 ↓ ⇓ key { [ KP_Next, KP_3, 0x1002198, 0x10021D8 ] }; // 3 ↘ ⇘ key { [ KP_Insert, KP_0, 0x1002195, 0x10021D5 ] }; // 0 ↕ ⇕ }; // Wang 725-3771-ae and 725-3771-uk keypad number area with additional arrow symbols // Copyright © 2007 Nicolas Mailhot // // ┏━━━━━┱ // ┃Num ┃ ⇱ Home // ┃Lock⇭┃ ⇲ End // ┡━━━━━╃─────┼─────┼ ⇞ Page up // │ 7 ↖ │ 8 ↑ │ 9 ↗ │ ⇟ Page down // │ ⇱ < │ ⇧ > │ ⇞ ^ │ ⎀ Insert // ├─────┼─────┼─────┤ ␥ Delete // │ 4 ← │ 5 ↔ │ 6 → │ ⇦⇧⇨⇩ Directions // │ ⇦ [ │ ] │ ⇨ $ │ ⍽ narrow no-break space // ├─────┼─────┼─────╆ // │ 1 ↙ │ 2 ↓ │ 3 ↘ ┃ // │ ⇲ & │ ⇩ @ │ ⇟ # ┃ 1 None // ├─────┴─────┼─────┨ 2 Num Lock ⇭ // │ 0 ↕ │ 3 Level3 ⇮ // │ ⎀ ' │ 4 Shift+Level3 ⇧⇮ // └───────────┴ partial keypad_keys xkb_symbols "ossnumber_wang" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ KP_Home, KP_7, less, 0x1002196 ] }; // 7 < ↖ key { [ KP_Up, KP_8, greater, 0x1002191 ] }; // 8 > ↑ key { [ KP_Prior, KP_9, asciicircum, 0x1002197 ] }; // 9 ^ ↗ key { [ KP_Left, KP_4, bracketleft, 0x1002190 ] }; // 4 [ ← key { [ KP_Begin, KP_5, bracketright, 0x1002194 ] }; // 5 ] ↔ key { [ KP_Right, KP_6, dollar, 0x1002192 ] }; // 6 $ → key { [ KP_End, KP_1, ampersand, 0x1002199 ] }; // 1 & ↙ key { [ KP_Down, KP_2, at, 0x1002193 ] }; // 2 @ ↓ key { [ KP_Next, KP_3, numbersign, 0x1002198 ] }; // 3 # ↘ key { [ KP_Insert, KP_0, apostrophe, 0x1002195 ] }; // 0 ' ↕ }; // Standard base "pc" layout only contains cursor keys, and then gets // augmented with the digits later. If you define your own layout for // the numpad you can inherit the cursors, but you'll have to define // the digits yourself. This module can be included in the rules to // define math operators; these are the variants used in computer // languages that are based on ASCII. NoSymbol does not mean that // nothing is bound to the key but that no assignment is done here. // srvr_ctrl(stdkeypad) and keypad(x11) declare the operator keys to // be of type CTRL+ALT in order to assign server control events to // them, but it uses the second level which is overwritten if we have // more than one definition (shift state) for the key. Instead, here // the commands are put at the 4th lever. partial keypad_keys xkb_symbols "ops" { key { [ NoSymbol, slash, NoSymbol, XF86_Ungrab ] }; key { [ NoSymbol, asterisk, NoSymbol, XF86_ClearGrab ] }; key { [ NoSymbol, minus, NoSymbol, XF86_Prev_VMode ] }; key { [ NoSymbol, plus, NoSymbol, XF86_Next_VMode ] }; key { [ NoSymbol, equal ] }; }; // Hexadecimal Numpad, by Roland Kaufmann // License: BSD (also covers variant with ATM digit order) // Third-level gives the letters used in hexadecimal numbers, or // columns in small spreadsheets. As a bonus, having 'e' available at // the center of the keyboard makes it easy to enter floating point // numbers in scientific notation. // Equal is added to start formulas (most numpads on PCs don't have // their own equal key), comma as a list separator (as most // programming languages wants period as a decimal separator) and // colon to enter times and ranges. Someone also may want to represent // multiplication and division in prose using x and colon. // Two first levels are specified as NoSymbol to not override any // previous specification. Combine this with another keypad specifier, // e.g. "legacy". partial keypad_keys xkb_symbols "hex" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; // None NumLock AltGr // symbol row key { [ NoSymbol, NoSymbol, parenleft ] }; key { [ NoSymbol, NoSymbol, parenright ] }; key { [ NoSymbol, NoSymbol, dollar ] }; // upper row key { [ NoSymbol, NoSymbol, a ] }; key { [ NoSymbol, NoSymbol, b ] }; key { [ NoSymbol, NoSymbol, c ] }; // home row key { [ NoSymbol, NoSymbol, d ] }; key { [ NoSymbol, NoSymbol, e ] }; key { [ NoSymbol, NoSymbol, f ] }; key { [ NoSymbol, NoSymbol, comma ] }; // lower row key { [ NoSymbol, NoSymbol, equal ] }; key { [ NoSymbol, NoSymbol, x ] }; key { [ NoSymbol, NoSymbol, colon ] }; // decimal row key { [ NoSymbol, NoSymbol, backslash ] }; }; // Main numbers follows the traditions from ATMs and phones with // numbers increasing downwards to the right. (It is easier to // change the keyboard layout than to reprogram your local ATM; // also cell-phones are becoming more common while calculators are // becoming more rare). // First level is left unspecified, so it may be combined with another // layout, e.g. "legacy". partial keypad_keys xkb_symbols "atm" { // upper row key { [ NoSymbol, KP_1 ] }; key { [ NoSymbol, KP_2 ] }; key { [ NoSymbol, KP_3 ] }; // lower row key { [ NoSymbol, KP_7 ] }; key { [ NoSymbol, KP_8 ] }; key { [ NoSymbol, KP_9 ] }; }; partial modifier_keys xkb_symbols "pointerkeys" { key { [ Num_Lock, Pointer_EnableKeys ] }; }; // Only numbers, operators and decimal separator, // as seen on keypad overlay on Japanese keyboard. // ┌─┬─┬─┬─┐ // │7│8│9│*│ // ├─┼─┼─┼─┤ // │4│5│6│-│ // ├─┼─┼─┼─┤ // │1│2│3│+│ // ├─┼─┼─┼─┤ // │0│ │·│/│ // └─┴─┴─┴─┘ partial keypad_keys xkb_symbols "numoperdecsep" { key { [ KP_7 ] }; key { [ KP_8 ] }; key { [ KP_9 ] }; // ClsGrb kills whichever client has a grab in effect key { type="CTRL+ALT", symbols[Group1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86_ClearGrab ] }; key { [ KP_4 ] }; key { [ KP_5 ] }; key { [ KP_6 ] }; // -VMode switches to the previous video mode key { type="CTRL+ALT", symbols[Group1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86_Prev_VMode ] }; key { [ KP_1 ] }; key { [ KP_2 ] }; key { [ KP_3 ] }; // +VMode switches to the next video mode key { type="CTRL+ALT", symbols[Group1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86_Next_VMode ] }; key { [ KP_0 ] }; key { [ KP_Decimal ] }; // Ungrab cancels server/keyboard/pointer grabs key { type="CTRL+ALT", symbols[Group1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86_Ungrab ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/kpdl000066400000000000000000000065061510033435100231270ustar00rootroot00000000000000// The key is a mess. // It was probably originally meant to be a decimal separator. // Except since it was declared by USA people it didn't use the original // SI separator "," but a "." (since then the USA managed to f-up the SI // by making "." an accepted alternative, but standards still use "," as // default) // As a result users of SI-abiding countries expect either a "." or a "," // or a "decimal_separator" which may or may not be translated in one of the // above depending on applications. // It's not possible to define a default per-country since user expectations // depend on the conflicting choices of their most-used applications, // operating system, etc. Therefore it needs to be a configuration setting // Copyright © 2007 Nicolas Mailhot // Legacy #1 // This assumes KP_Decimal will be translated in a dot partial keypad_keys xkb_symbols "dot" { key.type[Group1]="KEYPAD" ; key { [ KP_Delete, KP_Decimal ] }; // }; // Legacy #2 // This assumes KP_Separator will be translated in a comma partial keypad_keys xkb_symbols "comma" { key.type[Group1]="KEYPAD" ; key { [ KP_Delete, KP_Separator ] }; // }; // Period , usual keyboard serigraphy in most countries partial keypad_keys xkb_symbols "dotoss" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ KP_Delete, period, comma, 0x100202F ] }; // . , ⍽ (narrow no-break space) }; // Period , usual keyboard serigraphy in most countries, latin-9 restriction partial keypad_keys xkb_symbols "dotoss_latin9" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ KP_Delete, period, comma, nobreakspace ] }; // . , ⍽ (no-break space) }; // Comma , what most non anglo-saxon people consider the real separator partial keypad_keys xkb_symbols "commaoss" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ KP_Delete, comma, period, 0x100202F ] }; // , . ⍽ (narrow no-break space) }; // Momayyez : Bahrain, Iran, Iraq, Kuwait, Oman, Qatar, Saudi Arabia, Syria, UAE partial keypad_keys xkb_symbols "momayyezoss" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ KP_Delete, 0x100066B, comma, 0x100202F ] }; // ? , ⍽ (narrow no-break space) }; // Abstracted , pray everything will work out (it usually does not) partial keypad_keys xkb_symbols "kposs" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ KP_Delete, KP_Decimal, KP_Separator, 0x100202F ] }; // ? ? ⍽ (narrow no-break space) }; // Spreadsheets may be configured to use the dot as decimal // punctuation, comma as a thousands separator and then semi-colon as // the list separator. Of these, dot and semi-colon is most important // when entering data by the keyboard; the comma can then be inferred // and added to the presentation afterwards. Using semi-colon as a // general separator may in fact be preferred to avoid ambiguities // in data files. Most times a decimal separator is hard-coded, it // seems to be period, probably since this is the syntax used in // (most) programming languages. partial keypad_keys xkb_symbols "semi" { key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; key { [ NoSymbol, NoSymbol, semicolon ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/latch000066400000000000000000000025621510033435100232660ustar00rootroot00000000000000default partial alphanumeric_keys xkb_symbols "modifiers" { name[Group1] = "Test latching behavior"; virtual_modifiers Alt=Mod1, LevelThree; key { [ 1, exclam, onesuperior, exclamdown, plus ], type[Group1]="CTRL+ALT"}; key { [ q, Q ], type[Group1] = "ALPHABETIC" }; key { symbols[Group1] = [ Shift_L ], actions[Group1] = [ LatchMods(modifiers=Shift,latchToLock=true,clearLocks=true) ] }; key { symbols[Group1] = [ Shift_R ], actions[Group1] = [ LatchMods(modifiers=Shift,latchToLock=false,clearLocks=false) ] }; key { symbols[Group1] = [ Control_L ], actions[Group1] = [ LatchMods(modifiers=Control) ] }; key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ Alt_L ], actions[Group1] = [ LatchMods(modifiers=Alt) ] }; key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Latch ], actions[Group1] = [ LatchMods(modifiers=LevelThree,latchToLock=true,clearLocks=true) ] }; key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Latch ], actions[Group1] = [ LatchMods(modifiers=LevelThree,latchToLock=false,clearLocks=false) ] }; key { [XF86_Switch_VT_1], type[Group1] = "ONE_LEVEL" }; key { [ISO_Group_Shift], type[Group1] = "ONE_LEVEL" }; key { [ ISO_Level3_Lock ], type[Group1] = "ONE_LEVEL" }; key { [ ISO_Group_Latch ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/latin000066400000000000000000000344541510033435100233070ustar00rootroot00000000000000// Common Latin alphabet layout default partial xkb_symbols "basic" { key { [ 1, exclam, onesuperior, exclamdown ] }; key { [ 2, at, twosuperior, oneeighth ] }; key { [ 3, numbersign, threesuperior, sterling ] }; key { [ 4, dollar, onequarter, dollar ] }; key { [ 5, percent, onehalf, threeeighths ] }; key { [ 6, asciicircum, threequarters, fiveeighths ] }; key { [ 7, ampersand, braceleft, seveneighths ] }; key { [ 8, asterisk, bracketleft, trademark ] }; key { [ 9, parenleft, bracketright, plusminus ] }; key { [ 0, parenright, braceright, degree ] }; key { [ minus, underscore, backslash, questiondown ] }; key { [ equal, plus, dead_cedilla, dead_ogonek ] }; key { [ q, Q, at, Greek_OMEGA ] }; key { [ w, W, lstroke, Lstroke ] }; key { [ e, E, e, E ] }; key { [ r, R, paragraph, registered ] }; key { [ t, T, tslash, Tslash ] }; key { [ y, Y, leftarrow, yen ] }; key { [ u, U, downarrow, uparrow ] }; key { [ i, I, rightarrow, idotless ] }; key { [ o, O, oslash, Ooblique ] }; key { [ p, P, thorn, THORN ] }; key { [bracketleft, braceleft, dead_diaeresis, dead_abovering ] }; key { [bracketright, braceright, dead_tilde, dead_macron ] }; key { [ a, A, ae, AE ] }; key { [ s, S, ssharp, section ] }; key { [ d, D, eth, ETH ] }; key { [ f, F, dstroke, ordfeminine ] }; key { [ g, G, eng, ENG ] }; key { [ h, H, hstroke, Hstroke ] }; key { [ j, J, dead_hook, dead_horn ] }; key { [ k, K, kra, ampersand ] }; key { [ l, L, lstroke, Lstroke ] }; key { [ semicolon, colon, dead_acute, dead_doubleacute ] }; key { [apostrophe, quotedbl, dead_circumflex, dead_caron ] }; key { [ grave, asciitilde, notsign, notsign ] }; key { [ backslash, bar, dead_grave, dead_breve ] }; key { [ z, Z, guillemotleft, less ] }; key { [ x, X, guillemotright, greater ] }; key { [ c, C, cent, copyright ] }; key { [ v, V, leftdoublequotemark, leftsinglequotemark ] }; key { [ b, B, rightdoublequotemark, rightsinglequotemark ] }; key { [ n, N, n, N ] }; key { [ m, M, mu, masculine ] }; key { [ comma, less, horizconnector, multiply ] }; key { [ period, greater, periodcentered, division ] }; key { [ slash, question, dead_belowdot, dead_abovedot ] }; }; // Northern Europe ( Danish, Finnish, Norwegian, Swedish) common layout partial xkb_symbols "type2" { include "latin" key { [ 1, exclam, exclamdown, onesuperior ] }; key { [ 2, quotedbl, at, twosuperior ] }; key { [ 3, numbersign, sterling, threesuperior] }; key { [ 4, currency, dollar, onequarter ] }; key { [ 5, percent, onehalf, cent ] }; key { [ 6, ampersand, yen, fiveeighths ] }; key { [ 7, slash, braceleft, division ] }; key { [ 8, parenleft, bracketleft, guillemotleft] }; key { [ 9, parenright, bracketright, guillemotright] }; key { [ 0, equal, braceright, degree ] }; key { [ e, E, EuroSign, cent ] }; key { [ r, R, registered, registered ] }; key { [ t, T, thorn, THORN ] }; key { [ o, O, oe, OE ] }; key { [ aring, Aring, dead_diaeresis, dead_abovering ] }; key { [dead_diaeresis, dead_circumflex, dead_tilde, dead_caron ] }; key { [ a, A, ordfeminine, masculine ] }; key { [ c, C, copyright, copyright ] }; key { [ comma, semicolon, dead_cedilla, dead_ogonek ] }; key { [ period, colon, periodcentered, dead_abovedot ] }; key { [ minus, underscore, dead_belowdot, dead_abovedot ] }; }; // Slavic Latin ( Albanian, Croatian, Polish, Slovene, Yugoslav) // common layout partial xkb_symbols "type3" { include "latin" key { [ q, Q, backslash, Greek_OMEGA ] }; key { [ w, W, bar, Lstroke ] }; key { [ z, Z, leftarrow, yen ] }; key { [ f, F, bracketleft, ordfeminine ] }; key { [ g, G, bracketright, ENG ] }; key { [ k, K, lstroke, ampersand ] }; key { [ y, Y, guillemotleft, less ] }; key { [ v, V, at, grave ] }; key { [ b, B, braceleft, apostrophe ] }; key { [ n, N, braceright, braceright ] }; key { [ m, M, section, masculine ] }; key { [ comma, semicolon, less, multiply ] }; key { [ period, colon, greater, division ] }; }; // Another common Latin layout // (German, Estonian, Spanish, Icelandic, Italian, Latin American, Portuguese) partial xkb_symbols "type4" { include "latin" key { [ 2, quotedbl, at, oneeighth ] }; key { [ 6, ampersand, notsign, fiveeighths ] }; key { [ 7, slash, braceleft, seveneighths ] }; key { [ 8, parenleft, bracketleft, trademark ] }; key { [ 9, parenright, bracketright, plusminus ] }; key { [ 0, equal, braceright, degree ] }; key { [ e, E, EuroSign, cent ] }; key { [ comma, semicolon, horizconnector, multiply ] }; key { [ period, colon, periodcentered, division ] }; key { [ minus, underscore, dead_belowdot, dead_abovedot ] }; }; partial xkb_symbols "nodeadkeys" { key { [ equal, plus, cedilla, ogonek ] }; key { [bracketleft, braceleft, diaeresis, degree ] }; key { [bracketright, braceright, asciitilde, macron ] }; key { [ semicolon, colon, acute, doubleacute ] }; key { [apostrophe, quotedbl, asciicircum, caron ] }; key { [ backslash, bar, grave, breve ] }; key { [ slash, question, dead_belowdot, abovedot ] }; }; partial xkb_symbols "type2_nodeadkeys" { include "latin(nodeadkeys)" key { [ aring, Aring, diaeresis, degree ] }; key { [ diaeresis, asciicircum, asciitilde, caron ] }; key { [ comma, semicolon, cedilla, ogonek ] }; key { [ period, colon, periodcentered, abovedot ] }; key { [ minus, underscore, dead_belowdot, abovedot ] }; }; partial xkb_symbols "type3_nodeadkeys" { include "latin(nodeadkeys)" }; partial xkb_symbols "type4_nodeadkeys" { include "latin(nodeadkeys)" key { [ minus, underscore, dead_belowdot, abovedot ] }; }; // Added 2008.03.05 by Marcin Woliński // See http://marcinwolinski.pl/keyboard/ for a description. // Used by pl(intl) // // ┌─────┐ // │ 2 4 │ 2 = Shift, 4 = Level3 + Shift // │ 1 3 │ 1 = Normal, 3 = Level3 // └─────┘ // ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━┓ // │ ~ ~ │ ! ' │ @ " │ # ˝ │ $ ¸ │ % ˇ │ ^ ^ │ & ˘ │ * ̇ │ ( ̣ │ ) ° │ _ ¯ │ + ˛ ┃ ⌫ Back- ┃ // │ ` ` │ 1 ¡ │ 2 © │ 3 • │ 4 § │ 5 € │ 6 ¢ │ 7 − │ 8 × │ 9 ÷ │ 0 ° │ - – │ = — ┃ space ┃ // ┢━━━━━┷━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┺━┳━━━━━━━┫ // ┃ ┃ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { « │ } » ┃ Enter ┃ // ┃Tab ↹ ┃ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ [ ‹ │ ] › ┃ ⏎ ┃ // ┣━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┺┓ ┃ // ┃ ┃ A │ S │ D │ F │ G │ H │ J │ K │ L │ : “ │ " ” │ | ¶ ┃ ┃ // ┃Caps ⇬ ┃ a │ s │ d │ f │ g │ h │ j │ k │ l │ ; ‘ │ ' ’ │ \ ┃ ┃ // ┣━━━━━━━━┹────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┬┴────┲┷━━━━━┻━━━━━━┫ // ┃ │ Z │ X │ C │ V │ B │ N │ M │ < „ │ > · │ ? ¿ ┃ ┃ // ┃Shift ⇧ │ z │ x │ c │ v │ b │ n │ m │ , ‚ │ . … │ / ⁄ ┃Shift ⇧ ┃ // ┣━━━━━━━┳━━━━━┷━┳━━━┷━━━┱─┴─────┴─────┴─────┴─────┴─────┴───┲━┷━━━━━╈━━━━━┻━┳━━━━━━━┳━━━┛ // ┃ ┃ ┃ ┃ ␣ ⍽ ┃ ┃ ┃ ┃ // ┃Ctrl ┃Meta ┃Alt ┃ ␣ Space ⍽ ┃AltGr ⇮┃Menu ┃Ctrl ┃ // ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹───────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┛ partial xkb_symbols "intl" { key { [ grave, asciitilde, dead_grave, dead_tilde ] }; key { [ 1, exclam, exclamdown, dead_acute ] }; key { [ 2, at, copyright, dead_diaeresis ] }; key { [ 3, numbersign, U2022, dead_doubleacute ] }; // U+2022 is bullet (the name bullet does not work) key { [ 4, dollar, section, dead_cedilla ] }; key { [ 5, percent, EuroSign, dead_caron ] }; key { [ 6, asciicircum, cent, dead_circumflex ] }; key { [ 7, ampersand, U2212, dead_breve ] }; // U+2212 is MINUS SIGN key { [ 8, asterisk, multiply, dead_abovedot ] }; key { [ 9, parenleft, division, dead_belowdot ] }; key { [ 0, parenright, degree, dead_abovering ] }; key { [ minus, underscore, endash, dead_macron ] }; key { [ equal, plus, emdash, dead_ogonek ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E ] }; key { [ r, R ] }; key { [ t, T ] }; key { [ y, Y ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ o, O ] }; key { [ p, P ] }; key { [bracketleft, braceleft, U2039, guillemotleft ] }; key { [bracketright, braceright, U203A, guillemotright ] }; key { [ a, A ] }; key { [ s, S ] }; key { [ d, D ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ h, H ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ l, L ] }; key { [ semicolon, colon, leftsinglequotemark, leftdoublequotemark ] }; key { [apostrophe, quotedbl, rightsinglequotemark, rightdoublequotemark ] }; key { [ backslash, bar, NoSymbol, paragraph ] }; key { [ z, Z ] }; key { [ x, X ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ b, B ] }; key { [ n, N ] }; key { [ m, M ] }; key { [ comma, less, singlelowquotemark, doublelowquotemark ] }; key { [ period, greater, ellipsis, periodcentered ] }; key { [ slash, question, U2044, questiondown ] }; // U+2044 is FRACTION SLASH }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/level3000066400000000000000000000157631510033435100233740ustar00rootroot00000000000000// These partial variants assign ISO_Level3_Shift to various XKB keycodes // so that the third shift level can be reached. // The default behaviour: // the right Alt key (AltGr) chooses the third symbol engraved on a key. default partial modifier_keys xkb_symbols "ralt_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; partial modifier_keys xkb_symbols "ralt_latch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Latch ] }; include "level3(modifier_mapping)" }; // Ensure a mapping to a real modifier for LevelThree. partial modifier_keys xkb_symbols "modifier_mapping" { replace key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; modifier_map Mod5 { }; }; // The right Alt key never chooses the third level. // This option attempts to undo the effect of a layout's inclusion of // 'ralt_switch'. You may want to also select another level3 option // to map the level3 shift to some other key. partial modifier_keys xkb_symbols "ralt_alt" { key { type[Group1]="TWO_LEVEL", type[Group2]="TWO_LEVEL", type[Group3]="TWO_LEVEL", type[Group4]="TWO_LEVEL", symbols[Group1] = [ Alt_R, Meta_R ], symbols[Group2] = [ Alt_R, Meta_R ], symbols[Group3] = [ Alt_R, Meta_R ], symbols[Group4] = [ Alt_R, Meta_R ] }; modifier_map Mod1 { }; }; // The right Alt key (while pressed) chooses the third shift level, // and Compose is mapped to its second level. partial modifier_keys xkb_symbols "ralt_switch_multikey" { key { type[Group1]="TWO_LEVEL", symbols[Group1] = [ ISO_Level3_Shift, Multi_key ] }; include "level3(modifier_mapping)" }; // A special case of the right-Alt switch -- for use with grp:alts_toggle. hidden partial modifier_keys xkb_symbols "ralt_switch_for_alts_toggle" { virtual_modifiers LAlt, AltGr; key { type[Group1]="PC_RALT_LEVEL2", symbols[Group1] = [ Alt_L, ISO_Prev_Group, ISO_Prev_Group ], virtualMods= LAlt }; key { type[Group1]="PC_ALT_LEVEL2", symbols[Group1] = [ ISO_Level3_Shift, ISO_Next_Group ], virtualMods= AltGr }; include "level3(modifier_mapping)" }; // Either Alt key (while pressed) chooses the third shift level. // (To be used mostly to imitate Mac OS functionality.) partial modifier_keys xkb_symbols "alt_switch" { include "level3(lalt_switch)" include "level3(ralt_switch)" }; // The left Alt key (while pressed) chooses the third shift level. partial modifier_keys xkb_symbols "lalt_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // The right Ctrl key (while pressed) chooses the third shift level. partial modifier_keys xkb_symbols "switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // The Menu key (while pressed) chooses the third shift level. partial modifier_keys xkb_symbols "menu_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // Either Win key (while pressed) chooses the third shift level. partial modifier_keys xkb_symbols "win_switch" { include "level3(lwin_switch)" include "level3(rwin_switch)" }; // The left Win key (while pressed) chooses the third shift level. partial modifier_keys xkb_symbols "lwin_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // The right Win key (while pressed) chooses the third shift level. // (When using this map, you should set your keyboard as pc101 or pc102 // instead of pc104 or pc105.) partial modifier_keys xkb_symbols "rwin_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // The Enter key on the kepypad (while pressed) chooses the third shift level. // (This is especially useful for Mac laptops which miss the right Alt key.) partial modifier_keys xkb_symbols "enter_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // The CapsLock key (while pressed) chooses the third shift level. partial modifier_keys xkb_symbols "caps_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // The Backslash key (while pressed) chooses the third shift level. partial modifier_keys xkb_symbols "bksl_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // The Less/Greater key (while pressed) chooses the third shift level. partial modifier_keys xkb_symbols "lsgt_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // The CapsLock key (while pressed) chooses the third shift level, // and latches when pressed together with another third-level chooser. partial modifier_keys xkb_symbols "caps_switch_latch" { key { type[Group1]="THREE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift, ISO_Level3_Shift, ISO_Level3_Latch ] }; include "level3(modifier_mapping)" }; // The Backslash key (while pressed) chooses the third shift level, // and latches when pressed together with another third-level chooser. partial modifier_keys xkb_symbols "bksl_switch_latch" { key { type[Group1]="THREE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift, ISO_Level3_Shift, ISO_Level3_Latch ] }; include "level3(modifier_mapping)" }; partial modifier_keys xkb_symbols "bksl_latch_no_lock" { virtual_modifiers LevelThree; key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Latch ], actions[Group1] = [ LatchMods(modifiers=LevelThree, !clearLocks, !latchToLock)] }; }; // The Less/Greater key (while pressed) chooses the third shift level, // and latches when pressed together with another third-level chooser. partial modifier_keys xkb_symbols "lsgt_switch_latch" { key { type[Group1]="THREE_LEVEL", symbols[Group1] = [ ISO_Level3_Shift, ISO_Level3_Shift, ISO_Level3_Latch ] }; include "level3(modifier_mapping)" }; partial modifier_keys xkb_symbols "lsgt_latch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level3_Latch ] }; }; // Number key 4 chooses third shift level when pressed in isolation. partial modifier_keys xkb_symbols "4_switch_isolated" { override key { symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; // Number key 9 chooses third shift level when pressed in isolation. partial modifier_keys xkb_symbols "9_switch_isolated" { override key { symbols[Group1] = [ ISO_Level3_Shift ] }; include "level3(modifier_mapping)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/level5000066400000000000000000000112401510033435100233600ustar00rootroot00000000000000// These partial variants assign ISO_Level5_Shift to various XKB keycodes // so that the fifth shift level can be reached. // The right Ctrl key (while pressed) chooses the fifth shift level. partial modifier_keys xkb_symbols "rctrl_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level5_Shift ] }; include "level5(modifier_mapping)" }; // The Less/Greater key (while pressed) chooses the fifth shift level. partial modifier_keys xkb_symbols "lsgt_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level5_Shift ] }; include "level5(modifier_mapping)" }; // The right Alt key (while pressed) chooses the fifth shift level. partial modifier_keys xkb_symbols "ralt_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level5_Shift ] }; include "level5(modifier_mapping)" }; // The CapsLock key (while pressed) chooses the fifth shift level. partial modifier_keys xkb_symbols "caps_switch" { key { type[Group1]="ONE_LEVEL", symbols[Group1] = [ ISO_Level5_Shift ] }; include "level5(modifier_mapping)" }; // Ensure a mapping to a real modifier for LevelFive. partial modifier_keys xkb_symbols "modifier_mapping" { replace key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ ISO_Level5_Shift ] }; modifier_map Mod3 { }; }; // This adds the definitions needed to create a level5-lock behaviour, using // the real modifier NumLock as a lock indicator. // See also: types/level5 : EIGHT_LEVEL_LEVEL_FIVE_LOCK // See also: compat/level5(level5_lock) partial modifier_keys xkb_symbols "lock" { virtual_modifiers NumLock; key.type[Group1] = "ONE_LEVEL"; include "level5(modifier_mapping)" replace key { vmods = NumLock, symbols[Group1] = [ NoSymbol ], actions[Group1] = [ SetMods(modifiers=NumLock) ] }; modifier_map Mod2 { }; }; // The following modifier keys are used to switch to the third shift level // and to set a corresponding lock, implemented as NumLock. partial modifier_keys xkb_symbols "lsgt_switch_lock" { include "level5(lock)" key { type[Group1] = "EIGHT_LEVEL", symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ] }; }; partial modifier_keys xkb_symbols "lwin_switch_lock" { include "level5(lock)" key { type[Group1] = "EIGHT_LEVEL", symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ] }; }; partial modifier_keys xkb_symbols "ralt_switch_lock" { include "level5(lock)" key { type[Group1] = "EIGHT_LEVEL", symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ] }; }; partial modifier_keys xkb_symbols "rwin_switch_lock" { include "level5(lock)" key { type[Group1] = "EIGHT_LEVEL", symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ] }; }; partial modifier_keys xkb_symbols "lsgt_switch_lock_cancel" { include "level5(lock)" key { type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK", symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ] }; }; partial modifier_keys xkb_symbols "lwin_switch_lock_cancel" { include "level5(lock)" key { type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK", symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ] }; }; partial modifier_keys xkb_symbols "ralt_switch_lock_cancel" { include "level5(lock)" key { type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK", symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ] }; }; partial modifier_keys xkb_symbols "rwin_switch_lock_cancel" { include "level5(lock)" key { type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK", symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/macintosh_vndr/000077500000000000000000000000001510033435100252615ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/macintosh_vndr/apple000066400000000000000000000117571510033435100263200ustar00rootroot00000000000000// // Keyboard modification for Apple keyboards // default partial modifier_keys xkb_symbols "extended" { key { [ KP_Equal ] }; // The key in the PC's Insert position is sometimes engraved Help (at least // in Switzerland and Great Britain), with Insert sometimes above. But in the // US and Canada, it remains Insert. So this should probably be an XkbOption, // but I have to do more research. // Perhaps Help should be the primary symbol with Insert in the 1st shift-level // key { [ Help, Insert ] }; // The keys next to F12, labeled F13, F14, & F15 generate codes that XFree86 // claims not to generate. I think they should be equivalent to the PC keys // Print Screen / SysRq, Scroll Lock, and Pause. Linux kernel bug? // key { [ F13 ] }; // should be keycode 93 or // key { [ F13 ] }; // should be keycode 118 // key { [ F14 ] }; // should be keycode 123 or // key { [ F14 ] }; // should be keycode 119 // key { [ F15 ] }; // should be keycode 127 or // key { [ F15 ] }; // should be keycode 120 }; partial modifier_keys xkb_symbols "laptop" { include "macintosh_vndr/apple(extended)" // The real numlock key on the iBook (shared with F5) works internally to // the keyboard. It illuminates the Num_Lock led and locks the fn-key to // type only the keypad keys on the letter keys (U=4, I=5, O=6, P=*, etc.). // The key in the Num_lock position is engraved with Clear. override key { [ Clear ] }; // The key engraved Delete sends BKSP. To get Delete, use Shift-Delete override key { [ BackSpace, Delete ] }; // These keyboards only generate a when pressing fn+Alt. This makes // it impossible to get to the third shift level on keys that are on // the fn-keypad, so use the Enter key (right of ) for Mode_switch, // and use fn+Enter (Apple's code for Menu) for KP_Enter. replace key { [ ISO_Level3_Shift ] }; modifier_map Mod5 { ISO_Level3_Shift }; // Linux kernel bug with Menu on macs means this does not work yet // replace key { [ KP_Enter ] }; // should be keycode 117 }; partial modifier_keys xkb_symbols "laptop_bad_switch" { // Kept for backward compatibility include "macintosh_vndr/apple(laptop)" }; // Long Aluminium Keyboards partial function_keys xkb_symbols "alukbd" { // The base is a inet PC keyboard include "pc" // Additional Fxx keys key { [ F13 ] }; key { [ F14 ] }; key { [ F15 ] }; key { [ F16 ] }; key { [ F17 ] }; key { [ F18 ] }; key { [ F19 ] }; // On aluminium keyboards, Num_Lock is replace by Clear replace key { [ Clear ] }; // CAPS key is always Caps_Lock, even for JIS keyboards replace key { [ Caps_Lock ] }; // F1..F12 are multimedia keys when used with the 'Fn' key // Make those multimedia actions available via ISO_Level3_Shift too, // it is useful when the Fn key is remapped to something else (e.g. Insert) key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, XF86KbdBrightnessDown, NoSymbol, XF86_Switch_VT_1 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, XF86KbdBrightnessUp, NoSymbol, XF86_Switch_VT_2 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, XF86_Switch_VT_3 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, XF86_Switch_VT_4 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, XF86_Switch_VT_5 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, XF86_Switch_VT_6 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, XF86AudioPrev, NoSymbol, XF86_Switch_VT_7 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, XF86AudioPlay, NoSymbol, XF86_Switch_VT_8 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, XF86AudioNext, NoSymbol, XF86_Switch_VT_9 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, XF86AudioMute, NoSymbol, XF86_Switch_VT_10 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, XF86AudioLowerVolume, NoSymbol, XF86_Switch_VT_11 ] }; key { type= "FOUR_LEVEL_X", symbols[Group1]= [ NoSymbol, XF86AudioRaiseVolume, NoSymbol, XF86_Switch_VT_12 ] }; }; // Aluminium Keyboard: make F13, F14, F15 PC-ish (Print, Scroll_Lock, Pause) partial function_keys keypad_keys xkb_symbols "alupckeys" { key { type= "PC_ALT_LEVEL2", symbols[Group1]= [ Print, Sys_Req ] }; key { [ Scroll_Lock ] }; key { type= "PC_CONTROL_LEVEL2", symbols[Group1]= [ Pause, Break ] }; override key { [ Num_Lock, Pointer_EnableKeys ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/macintosh_vndr/us000066400000000000000000000101731510033435100256350ustar00rootroot00000000000000// symbols definition for a Macintosh "Extended" keyboard default xkb_symbols "extended" { name[Group1]= "USA"; key { [ Escape ] }; key { [ grave, asciitilde ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ 5, percent ] }; key { [ 6, asciicircum ] }; key { [ 7, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E ] }; key { [ r, R ] }; key { [ t, T ] }; key { [ y, Y ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ o, O ] }; key { [ p, P ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ backslash, bar ] }; key { [ a, A ] }; key { [ s, S ] }; key { [ d, D ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ h, H ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ l, L ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ z, Z ] }; key { [ x, X ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ b, B ] }; key { [ n, N ] }; key { [ m, M ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ slash, question ] }; key { [ space ] }; include "eurosign(e)" include "keypad(overlay)" key { [ equal ] }; }; hidden xkb_symbols "oldmac" { include "macintosh_vndr/us(extended)" // Begin "Function" section key { [ F1 ] }; key { [ F2 ] }; key { [ F3 ] }; key { [ F4 ] }; key { [ F5 ] }; key { [ F6 ] }; key { [ F7 ] }; key { [ F8 ] }; key { [ F9 ] }; key { [ F10 ] }; key { [ F11 ] }; key { [ F12 ] }; key { [ Print ] }; key { [ Scroll_Lock ] }; key { [ Pause ] }; // End "Function" section // Begin "Editing" section key { [ Insert ] }; key { [ Home ] }; key { [ Prior ] }; key { [ Delete ] }; key { [ End ] }; key { [ Next ] }; key { [ Up ] }; key { [ Left ] }; key { [ Down ] }; key { [ Right ] }; // End "Editing" section key { [ BackSpace ] }; key { [ Tab, ISO_Left_Tab ] }; key { [ Return ] }; key { [ Caps_Lock ] }; key { [ Num_Lock, Pointer_EnableKeys ] }; // Begin "Modifier" section key { [ Shift_L ] }; key { [ Shift_R ] }; key { [ Control_L ] }; key { [ Control_R ] }; key { [ Alt_L, Meta_L ] }; key { [ Alt_R, Meta_R ] }; key { [ Super_L ] }; key { [ Super_R ] }; // End "Modifier" section // begin modifier mappings modifier_map Shift { Shift_L, Shift_R }; modifier_map Lock { Caps_Lock }; modifier_map Control{ Control_L, Control_R }; modifier_map Mod2 { Num_Lock }; // Fake keys for virtual<->real modifiers mapping key { [ ISO_Level3_Shift ] }; key { [ Mode_switch ] }; modifier_map Mod5 { , }; key { [ NoSymbol, Alt_L ] }; modifier_map Mod1 { , }; key { [ NoSymbol, Meta_L ] }; modifier_map Mod1 { }; key { [ NoSymbol, Super_L ] }; modifier_map Mod4 { }; key { [ NoSymbol, Hyper_L ] }; modifier_map Mod4 { }; // end modifier mappings }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/merge_modes000066400000000000000000002664711510033435100244740ustar00rootroot00000000000000// WARNING: This file was auto-generated by: scripts/update-merge-modes-tests.py xkb_symbols "base-default" { key { }; key { }; key { }; key { }; key { }; key { }; key { [a] }; key { [SetGroup(group=2)] }; key { [a], [SetGroup(group=2)] }; key { [a] }; key { [SetGroup(group=2)] }; key { [a], [SetGroup(group=2)] }; key { [a, {A, Y}] }; key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; key { [NoAction(), SetGroup(group=2)] }; key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; key { [NoSymbol, A] }; key { [NoAction(), SetGroup(group=2)] }; key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; key { [NoAction(), SetGroup(group=2), NoAction()] }; key { [NoSymbol, A, NoSymbol], [NoAction(), SetGroup(group=2), NoAction()] }; key { [NoSymbol, A, NoSymbol] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A, a] }; key { [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; key { [a, A, a], [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [NoSymbol, NoSymbol] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A] }; key { [SetGroup(group=2), SetGroup(group=2)] }; key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{NoSymbol, NoSymbol}, {A, Y}] }; key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{a, NoSymbol}, {NoSymbol, B}] }; key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; key { [{a, NoSymbol}, {NoSymbol, B}] }; key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; key { [{a, y}, {A, Y}] }; key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{a, y}, {A, Y}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{a, y}, {X, B}] }; key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; key { [{a, y}, {X, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; key { [{a, y}, {X, NoSymbol, A}] }; key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; key { [{a, y}, {X, NoSymbol, A}] }; key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; key { [{NoSymbol, NoSymbol}, {A, Y}] }; key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{NoSymbol, NoSymbol}, {A, Y}] }; key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{a, NoSymbol}, {NoSymbol, B}] }; key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; key { [{a, NoSymbol}, {NoSymbol, B}] }; key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; key { [SetGroup(group=2)] }; key { [{SetGroup(group=2), SetMods(mods=Control)}] }; key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{a, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=2), NoAction()}] }; key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{a, b}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; key { [{a, NoSymbol}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; key { [{a, b}, {NoSymbol, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetMods(mods=Control)}] }; key { [a, {A, B}] }; key { [SetGroup(group=3), {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [a, {A, B}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; key { [A] }; key { [A], [SetGroup(group=2)] }; key { [{notAKeysym, NoSymbol, thisEither}] }; }; xkb_symbols "base-augment" { augment key { }; augment key { }; augment key { }; augment key { }; augment key { }; augment key { }; augment key { [a] }; augment key { [SetGroup(group=2)] }; augment key { [a], [SetGroup(group=2)] }; augment key { [a] }; augment key { [SetGroup(group=2)] }; augment key { [a], [SetGroup(group=2)] }; augment key { [a, {A, Y}] }; augment key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [NoAction(), SetGroup(group=2)] }; augment key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; augment key { [NoSymbol, A] }; augment key { [NoAction(), SetGroup(group=2)] }; augment key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; augment key { [NoAction(), SetGroup(group=2), NoAction()] }; augment key { [NoSymbol, A, NoSymbol], [NoAction(), SetGroup(group=2), NoAction()] }; augment key { [NoSymbol, A, NoSymbol] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A, a] }; augment key { [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A, a], [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A] }; augment key { [SetGroup(group=2), SetGroup(group=2)] }; augment key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; augment key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; augment key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; augment key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{NoSymbol, NoSymbol}, {A, Y}] }; augment key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}] }; augment key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}] }; augment key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; augment key { [{a, y}, {A, Y}] }; augment key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{a, y}, {A, Y}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{a, y}, {X, B}] }; augment key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; augment key { [{a, y}, {X, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; augment key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; augment key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; augment key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; augment key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; augment key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; augment key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; augment key { [{a, y}, {X, NoSymbol, A}] }; augment key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; augment key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; augment key { [{a, y}, {X, NoSymbol, A}] }; augment key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; augment key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; augment key { [{NoSymbol, NoSymbol}, {A, Y}] }; augment key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{NoSymbol, NoSymbol}, {A, Y}] }; augment key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}] }; augment key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}] }; augment key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; augment key { [SetGroup(group=2)] }; augment key { [{SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; augment key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{a, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=2), NoAction()}] }; augment key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{a, b}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [{a, NoSymbol}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; augment key { [{a, b}, {NoSymbol, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; augment key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetMods(mods=Control)}] }; augment key { [a, {A, B}] }; augment key { [SetGroup(group=3), {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [a, {A, B}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [A] }; augment key { [A], [SetGroup(group=2)] }; augment key { [{notAKeysym, NoSymbol, thisEither}] }; }; xkb_symbols "base-override" { override key { }; override key { }; override key { }; override key { }; override key { }; override key { }; override key { [a] }; override key { [SetGroup(group=2)] }; override key { [a], [SetGroup(group=2)] }; override key { [a] }; override key { [SetGroup(group=2)] }; override key { [a], [SetGroup(group=2)] }; override key { [a, {A, Y}] }; override key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [NoAction(), SetGroup(group=2)] }; override key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; override key { [NoSymbol, A] }; override key { [NoAction(), SetGroup(group=2)] }; override key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; override key { [NoAction(), SetGroup(group=2), NoAction()] }; override key { [NoSymbol, A, NoSymbol], [NoAction(), SetGroup(group=2), NoAction()] }; override key { [NoSymbol, A, NoSymbol] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A, a] }; override key { [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A, a], [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [NoSymbol, NoSymbol] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A] }; override key { [SetGroup(group=2), SetGroup(group=2)] }; override key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; override key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; override key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; override key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{NoSymbol, NoSymbol}, {A, Y}] }; override key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{a, NoSymbol}, {NoSymbol, B}] }; override key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; override key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; override key { [{a, NoSymbol}, {NoSymbol, B}] }; override key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; override key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; override key { [{a, y}, {A, Y}] }; override key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{a, y}, {A, Y}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{a, y}, {X, B}] }; override key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; override key { [{a, y}, {X, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; override key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; override key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; override key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; override key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; override key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; override key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; override key { [{a, y}, {X, NoSymbol, A}] }; override key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; override key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; override key { [{a, y}, {X, NoSymbol, A}] }; override key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; override key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; override key { [{NoSymbol, NoSymbol}, {A, Y}] }; override key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{NoSymbol, NoSymbol}, {A, Y}] }; override key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{a, NoSymbol}, {NoSymbol, B}] }; override key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; override key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; override key { [{a, NoSymbol}, {NoSymbol, B}] }; override key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; override key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; override key { [SetGroup(group=2)] }; override key { [{SetGroup(group=2), SetMods(mods=Control)}] }; override key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; override key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{a, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=2), NoAction()}] }; override key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{a, b}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [{a, NoSymbol}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; override key { [{a, b}, {NoSymbol, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; override key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetMods(mods=Control)}] }; override key { [a, {A, B}] }; override key { [SetGroup(group=3), {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [a, {A, B}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [A] }; override key { [A], [SetGroup(group=2)] }; override key { [{notAKeysym, NoSymbol, thisEither}] }; }; xkb_symbols "base-replace" { replace key { }; replace key { }; replace key { }; replace key { }; replace key { }; replace key { }; replace key { [a] }; replace key { [SetGroup(group=2)] }; replace key { [a], [SetGroup(group=2)] }; replace key { [a] }; replace key { [SetGroup(group=2)] }; replace key { [a], [SetGroup(group=2)] }; replace key { [a, {A, Y}] }; replace key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [NoAction(), SetGroup(group=2)] }; replace key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; replace key { [NoSymbol, A] }; replace key { [NoAction(), SetGroup(group=2)] }; replace key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; replace key { [NoAction(), SetGroup(group=2), NoAction()] }; replace key { [NoSymbol, A, NoSymbol], [NoAction(), SetGroup(group=2), NoAction()] }; replace key { [NoSymbol, A, NoSymbol] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A, a] }; replace key { [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A, a], [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A] }; replace key { [SetGroup(group=2), SetGroup(group=2)] }; replace key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; replace key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; replace key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; replace key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{NoSymbol, NoSymbol}, {A, Y}] }; replace key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}] }; replace key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}] }; replace key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; replace key { [{a, y}, {A, Y}] }; replace key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{a, y}, {A, Y}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{a, y}, {X, B}] }; replace key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; replace key { [{a, y}, {X, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; replace key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; replace key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; replace key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; replace key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; replace key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; replace key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; replace key { [{a, y}, {X, NoSymbol, A}] }; replace key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; replace key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; replace key { [{a, y}, {X, NoSymbol, A}] }; replace key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; replace key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; replace key { [{NoSymbol, NoSymbol}, {A, Y}] }; replace key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{NoSymbol, NoSymbol}, {A, Y}] }; replace key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}] }; replace key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}] }; replace key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; replace key { [SetGroup(group=2)] }; replace key { [{SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; replace key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{a, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=2), NoAction()}] }; replace key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{a, b}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [{a, NoSymbol}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; replace key { [{a, b}, {NoSymbol, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; replace key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetMods(mods=Control)}] }; replace key { [a, {A, B}] }; replace key { [SetGroup(group=3), {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [a, {A, B}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [A] }; replace key { [A], [SetGroup(group=2)] }; replace key { [{notAKeysym, NoSymbol, thisEither}] }; }; xkb_symbols "update-default" { ////// Trivial cases ////// key { }; key { }; key { }; key { [Greek_alpha] }; key { [SetGroup(group=3)] }; key { [Greek_alpha], [SetGroup(group=3)] }; key { }; key { }; key { }; ////// Same key ////// key { [a] }; key { [SetGroup(group=2)] }; key { [a], [SetGroup(group=2)] }; key { [a, {A, Y}] }; key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; ////// Mismatch levels count ////// key { [SetGroup(group=3), NoAction(), NoAction()] }; key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; key { [Greek_alpha, NoSymbol, NoSymbol] }; key { [SetGroup(group=3), NoAction(), NoAction()] }; key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; key { [SetGroup(group=3), NoAction()] }; key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; key { [Greek_alpha, NoSymbol] }; key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA] }; key { [SetGroup(group=3), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; ////// Single keysyms -> single keysyms ////// key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [SetGroup(group=3), NoAction()] }; key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; key { [Greek_alpha, NoSymbol] }; key { [NoSymbol, Greek_ALPHA] }; key { [NoAction(), SetGroup(group=3)] }; key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA] }; key { [SetGroup(group=3), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [SetGroup(group=3), NoAction()] }; key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; key { [Greek_alpha, NoSymbol] }; key { [NoSymbol, Greek_ALPHA] }; key { [NoAction(), SetGroup(group=3)] }; key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA] }; key { [SetGroup(group=3), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; ////// Single keysyms -> multiple keysyms ////// key { [{Greek_alpha, NoSymbol}, NoSymbol] }; key { [{SetGroup(group=3), NoAction()}, NoAction()] }; key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; key { [NoAction(), {SetGroup(group=3), NoAction()}] }; key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{Greek_alpha, NoSymbol}, NoSymbol] }; key { [{SetGroup(group=3), NoAction()}, NoAction()] }; key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; key { [NoAction(), {SetGroup(group=3), NoAction()}] }; key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Multiple keysyms -> multiple keysyms ////// key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; ////// Multiple keysyms -> single keysyms ////// key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [Greek_alpha, Greek_ALPHA] }; key { [SetGroup(group=3), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; key { [NoSymbol, NoSymbol] }; key { [NoAction(), NoAction()] }; key { [NoSymbol, NoSymbol] }; key { [Greek_alpha, Greek_ALPHA] }; key { [SetGroup(group=3), SetGroup(group=3)] }; key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; ////// Mix ////// key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; ////// Mix ////// key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; ////// Multiple keysyms/actions –> single ////// key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; ////// Multiple keysyms/actions –> multiple (xor) ////// key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; ////// Multiple keysyms/actions –> multiple (mix) ////// key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; ////// Multiple (mix) –> multiple keysyms/actions ////// key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Multiple (mix) –> multiple (mix) ////// key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; ////// Mismatch count with mix ////// key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; key { [{A, B}, a] }; key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; ////// Issue #564 ////// key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Drop NoSymbol/NoAction ////// key { [{NoSymbol, Y, NoSymbol}], [{NoAction(), SetGroup(group=3), NoAction()}] }; ////// Drop NoSymbol/NoAction and invalid keysyms ////// key { [{NoSymbol, NoSymbol}] }; }; xkb_symbols "update-augment" { ////// Trivial cases ////// augment key { }; augment key { }; augment key { }; augment key { [Greek_alpha] }; augment key { [SetGroup(group=3)] }; augment key { [Greek_alpha], [SetGroup(group=3)] }; augment key { }; augment key { }; augment key { }; ////// Same key ////// augment key { [a] }; augment key { [SetGroup(group=2)] }; augment key { [a], [SetGroup(group=2)] }; augment key { [a, {A, Y}] }; augment key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; augment key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; ////// Mismatch levels count ////// augment key { [SetGroup(group=3), NoAction(), NoAction()] }; augment key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; augment key { [Greek_alpha, NoSymbol, NoSymbol] }; augment key { [SetGroup(group=3), NoAction(), NoAction()] }; augment key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; augment key { [SetGroup(group=3), NoAction()] }; augment key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; augment key { [Greek_alpha, NoSymbol] }; augment key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; augment key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA] }; augment key { [SetGroup(group=3), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; ////// Single keysyms -> single keysyms ////// augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [SetGroup(group=3), NoAction()] }; augment key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; augment key { [Greek_alpha, NoSymbol] }; augment key { [NoSymbol, Greek_ALPHA] }; augment key { [NoAction(), SetGroup(group=3)] }; augment key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA] }; augment key { [SetGroup(group=3), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [SetGroup(group=3), NoAction()] }; augment key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; augment key { [Greek_alpha, NoSymbol] }; augment key { [NoSymbol, Greek_ALPHA] }; augment key { [NoAction(), SetGroup(group=3)] }; augment key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA] }; augment key { [SetGroup(group=3), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; augment key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; ////// Single keysyms -> multiple keysyms ////// augment key { [{Greek_alpha, NoSymbol}, NoSymbol] }; augment key { [{SetGroup(group=3), NoAction()}, NoAction()] }; augment key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; augment key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; augment key { [NoAction(), {SetGroup(group=3), NoAction()}] }; augment key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; augment key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; augment key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; augment key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; augment key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{Greek_alpha, NoSymbol}, NoSymbol] }; augment key { [{SetGroup(group=3), NoAction()}, NoAction()] }; augment key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; augment key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; augment key { [NoAction(), {SetGroup(group=3), NoAction()}] }; augment key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; augment key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; augment key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; augment key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; augment key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Multiple keysyms -> multiple keysyms ////// augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; augment key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; augment key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; augment key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; augment key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; augment key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; augment key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; augment key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; augment key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; augment key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; augment key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; augment key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; augment key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; augment key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; ////// Multiple keysyms -> single keysyms ////// augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [Greek_alpha, Greek_ALPHA] }; augment key { [SetGroup(group=3), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; augment key { [NoSymbol, NoSymbol] }; augment key { [NoAction(), NoAction()] }; augment key { [NoSymbol, NoSymbol] }; augment key { [Greek_alpha, Greek_ALPHA] }; augment key { [SetGroup(group=3), SetGroup(group=3)] }; augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; ////// Mix ////// augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; ////// Mix ////// augment key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; ////// Multiple keysyms/actions –> single ////// augment key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; ////// Multiple keysyms/actions –> multiple (xor) ////// augment key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; ////// Multiple keysyms/actions –> multiple (mix) ////// augment key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; ////// Multiple (mix) –> multiple keysyms/actions ////// augment key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; augment key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Multiple (mix) –> multiple (mix) ////// augment key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; augment key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; ////// Mismatch count with mix ////// augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; augment key { [{A, B}, a] }; augment key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; ////// Issue #564 ////// augment key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Drop NoSymbol/NoAction ////// augment key { [{NoSymbol, Y, NoSymbol}], [{NoAction(), SetGroup(group=3), NoAction()}] }; ////// Drop NoSymbol/NoAction and invalid keysyms ////// augment key { [{NoSymbol, NoSymbol}] }; }; xkb_symbols "update-override" { ////// Trivial cases ////// override key { }; override key { }; override key { }; override key { [Greek_alpha] }; override key { [SetGroup(group=3)] }; override key { [Greek_alpha], [SetGroup(group=3)] }; override key { }; override key { }; override key { }; ////// Same key ////// override key { [a] }; override key { [SetGroup(group=2)] }; override key { [a], [SetGroup(group=2)] }; override key { [a, {A, Y}] }; override key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; override key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; ////// Mismatch levels count ////// override key { [SetGroup(group=3), NoAction(), NoAction()] }; override key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; override key { [Greek_alpha, NoSymbol, NoSymbol] }; override key { [SetGroup(group=3), NoAction(), NoAction()] }; override key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; override key { [SetGroup(group=3), NoAction()] }; override key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; override key { [Greek_alpha, NoSymbol] }; override key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; override key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA] }; override key { [SetGroup(group=3), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; ////// Single keysyms -> single keysyms ////// override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [SetGroup(group=3), NoAction()] }; override key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; override key { [Greek_alpha, NoSymbol] }; override key { [NoSymbol, Greek_ALPHA] }; override key { [NoAction(), SetGroup(group=3)] }; override key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA] }; override key { [SetGroup(group=3), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [SetGroup(group=3), NoAction()] }; override key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; override key { [Greek_alpha, NoSymbol] }; override key { [NoSymbol, Greek_ALPHA] }; override key { [NoAction(), SetGroup(group=3)] }; override key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA] }; override key { [SetGroup(group=3), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; override key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; ////// Single keysyms -> multiple keysyms ////// override key { [{Greek_alpha, NoSymbol}, NoSymbol] }; override key { [{SetGroup(group=3), NoAction()}, NoAction()] }; override key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; override key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; override key { [NoAction(), {SetGroup(group=3), NoAction()}] }; override key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; override key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; override key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; override key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; override key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{Greek_alpha, NoSymbol}, NoSymbol] }; override key { [{SetGroup(group=3), NoAction()}, NoAction()] }; override key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; override key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; override key { [NoAction(), {SetGroup(group=3), NoAction()}] }; override key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; override key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; override key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; override key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; override key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Multiple keysyms -> multiple keysyms ////// override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; override key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; override key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; override key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; override key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; override key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; override key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; override key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; override key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; override key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; override key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; override key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; override key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; override key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; override key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; override key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; override key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; ////// Multiple keysyms -> single keysyms ////// override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [Greek_alpha, Greek_ALPHA] }; override key { [SetGroup(group=3), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; override key { [NoSymbol, NoSymbol] }; override key { [NoAction(), NoAction()] }; override key { [NoSymbol, NoSymbol] }; override key { [Greek_alpha, Greek_ALPHA] }; override key { [SetGroup(group=3), SetGroup(group=3)] }; override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; ////// Mix ////// override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; ////// Mix ////// override key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; ////// Multiple keysyms/actions –> single ////// override key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; ////// Multiple keysyms/actions –> multiple (xor) ////// override key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; ////// Multiple keysyms/actions –> multiple (mix) ////// override key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; ////// Multiple (mix) –> multiple keysyms/actions ////// override key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; override key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Multiple (mix) –> multiple (mix) ////// override key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; override key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; ////// Mismatch count with mix ////// override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; override key { [{A, B}, a] }; override key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; ////// Issue #564 ////// override key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Drop NoSymbol/NoAction ////// override key { [{NoSymbol, Y, NoSymbol}], [{NoAction(), SetGroup(group=3), NoAction()}] }; ////// Drop NoSymbol/NoAction and invalid keysyms ////// override key { [{NoSymbol, NoSymbol}] }; }; xkb_symbols "update-replace" { ////// Trivial cases ////// replace key { }; replace key { }; replace key { }; replace key { [Greek_alpha] }; replace key { [SetGroup(group=3)] }; replace key { [Greek_alpha], [SetGroup(group=3)] }; replace key { }; replace key { }; replace key { }; ////// Same key ////// replace key { [a] }; replace key { [SetGroup(group=2)] }; replace key { [a], [SetGroup(group=2)] }; replace key { [a, {A, Y}] }; replace key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; replace key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; ////// Mismatch levels count ////// replace key { [SetGroup(group=3), NoAction(), NoAction()] }; replace key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; replace key { [Greek_alpha, NoSymbol, NoSymbol] }; replace key { [SetGroup(group=3), NoAction(), NoAction()] }; replace key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; replace key { [SetGroup(group=3), NoAction()] }; replace key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; replace key { [Greek_alpha, NoSymbol] }; replace key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; replace key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA] }; replace key { [SetGroup(group=3), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; ////// Single keysyms -> single keysyms ////// replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [SetGroup(group=3), NoAction()] }; replace key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; replace key { [Greek_alpha, NoSymbol] }; replace key { [NoSymbol, Greek_ALPHA] }; replace key { [NoAction(), SetGroup(group=3)] }; replace key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA] }; replace key { [SetGroup(group=3), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [SetGroup(group=3), NoAction()] }; replace key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; replace key { [Greek_alpha, NoSymbol] }; replace key { [NoSymbol, Greek_ALPHA] }; replace key { [NoAction(), SetGroup(group=3)] }; replace key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA] }; replace key { [SetGroup(group=3), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; replace key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; ////// Single keysyms -> multiple keysyms ////// replace key { [{Greek_alpha, NoSymbol}, NoSymbol] }; replace key { [{SetGroup(group=3), NoAction()}, NoAction()] }; replace key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; replace key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; replace key { [NoAction(), {SetGroup(group=3), NoAction()}] }; replace key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; replace key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; replace key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; replace key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; replace key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{Greek_alpha, NoSymbol}, NoSymbol] }; replace key { [{SetGroup(group=3), NoAction()}, NoAction()] }; replace key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; replace key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; replace key { [NoAction(), {SetGroup(group=3), NoAction()}] }; replace key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; replace key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; replace key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; replace key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; replace key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Multiple keysyms -> multiple keysyms ////// replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; replace key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; replace key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; replace key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; replace key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; replace key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; replace key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; replace key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; replace key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; replace key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; replace key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; replace key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; replace key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; replace key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; ////// Multiple keysyms -> single keysyms ////// replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [Greek_alpha, Greek_ALPHA] }; replace key { [SetGroup(group=3), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; replace key { [NoSymbol, NoSymbol] }; replace key { [NoAction(), NoAction()] }; replace key { [NoSymbol, NoSymbol] }; replace key { [Greek_alpha, Greek_ALPHA] }; replace key { [SetGroup(group=3), SetGroup(group=3)] }; replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; ////// Mix ////// replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; ////// Mix ////// replace key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; ////// Multiple keysyms/actions –> single ////// replace key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; ////// Multiple keysyms/actions –> multiple (xor) ////// replace key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; ////// Multiple keysyms/actions –> multiple (mix) ////// replace key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; ////// Multiple (mix) –> multiple keysyms/actions ////// replace key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; replace key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Multiple (mix) –> multiple (mix) ////// replace key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; replace key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; ////// Mismatch count with mix ////// replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; replace key { [{A, B}, a] }; replace key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; ////// Issue #564 ////// replace key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; ////// Drop NoSymbol/NoAction ////// replace key { [{NoSymbol, Y, NoSymbol}], [{NoAction(), SetGroup(group=3), NoAction()}] }; ////// Drop NoSymbol/NoAction and invalid keysyms ////// replace key { [{NoSymbol, NoSymbol}] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/merge_modes_defaults000066400000000000000000000006241510033435100263450ustar00rootroot00000000000000default xkb_symbols { name[1] = "xxx"; name[1] = "yyy"; augment name[1] = "zzz"; key { [a, A] }; key { [s, S] }; modifier_map Shift { }; modifier_map Control { }; key.repeat = false; key.vmods = M1; key.vmods = M2; augment key.vmods = M3; key { vmods = M4, [d, D] }; augment key { vmods = M4, [f, F] }; augment key { vmods = M1, repeat = true }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/multiple-groups000066400000000000000000000015031510033435100253350ustar00rootroot00000000000000// Define a key with various groups at the same time. // Use RALT because the option `lv3:ralt_alt` used to have a similar // (buggy) implementation, that triggered an unexpected result // for `xkb_keymap_num_layouts` and `xkb_keymap_num_layouts_for_key`. default partial modifier_keys xkb_symbols "1" { key { type[Group1]="ONE_LEVEL", type[Group2]="ONE_LEVEL", type[Group3]="ONE_LEVEL", type[Group4]="ONE_LEVEL", symbols[Group1] = [ a ], symbols[Group2] = [ b ], symbols[Group3] = [ c ], symbols[Group4] = [ d ] }; }; xkb_symbols "2" { key { type[Group1]="ONE_LEVEL", type[Group2]="ONE_LEVEL", type[Group3]="ONE_LEVEL", type[Group4]="ONE_LEVEL", symbols[Group1] = [ a ], symbols[Group2] = [ B ], symbols[Group3] = [ C ], symbols[Group4] = [ D ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/multiple_actions000066400000000000000000000127161510033435100255500ustar00rootroot00000000000000default alphanumeric_keys modifier_keys xkb_symbols "basic" { name[1] = "Multiple actions"; virtual_modifiers Alt, Super, LevelThree; // Multiple keysyms but no actions: OK key { symbols[1] = [ { Control_L, ISO_Group_Shift } ] }; // Multiple actions but no keysyms: OK, but will use NoSymbol key { actions[1] = [ { SetMods(modifiers=Control), SetGroup(group=+1) } ] }; // Multiple keysyms and matching actions key { virtualModifiers = LevelThree, symbols[1] = [ { ISO_Level3_Shift, ISO_Group_Shift } ], actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; // Multiple actions and matching keysyms key { virtualModifiers = LevelThree, actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ], symbols[1] = [ { ISO_Level3_Shift, ISO_Group_Shift } ] }; // Different actions and keysyms count key { symbols[1] = [ Alt_L ], actions[1] = [ { SetMods(modifiers=Alt), SetGroup(group=+1) } ] }; key { symbols[1] = [ { Alt_R, ISO_Group_Shift } ], actions[1] = [ SetMods(modifiers=Alt) ] }; key { symbols[1] = [ { Super_L, ISO_Group_Shift } ], actions[1] = [ { SetMods(modifiers=Super), SetGroup(group=+1), NoAction() } ] }; key { symbols[1] = [ { Super_R, ISO_Group_Shift , NoSymbol } ], actions[1] = [ { SetMods(modifiers=Super), SetGroup(group=+1) } ] }; // Incompatible categories key { symbols[1] = [ { Control_L, Shift_L } ] }; modifier_map Control { }; key { symbols[1] = [ { Control_L, Shift_L } ], actions[1] = [ { SetMods(modifiers=Control), SetMods(modifiers=Shift) } ] }; // Various overrides, different keysyms, no explicit actions key { [ x ] }; key { [ { Control_L, ISO_Group_Shift } ] }; key { [ { Control_L, ISO_Group_Shift } ] }; key { [ x ] }; // Various overrides, no keysyms, explicit actions key { actions[1] = [ SetMods(modifiers=LevelThree) ] }; key { actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; key { actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; key { actions[1] = [ SetMods(modifiers=LevelThree) ] }; // Various overrides, different keysyms & actions key { virtualModifiers = LevelThree, symbols[1] = [ Control_L ], actions[1] = [ SetMods(modifiers=Control) ] }; key { symbols[1] = [ { ISO_Level3_Shift, ISO_Group_Shift } ], actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; key { virtualModifiers = LevelThree, symbols[1] = [ { ISO_Level3_Shift, ISO_Group_Shift } ], actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; key { symbols[1] = [ Control_L ], actions[1] = [ SetMods(modifiers=Control) ] }; // Various overrides, same keysyms but different actions key { virtualModifiers = LevelThree, symbols[1] = [ { ISO_Level3_Shift, ISO_Group_Shift } ], actions[1] = [ { SetMods(modifiers=Control), Private(type=254, data="foo") } ] }; key { symbols[1] = [ { ISO_Level3_Shift, ISO_Group_Shift } ], actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; // Mix various number of keysyms/actions key { symbols[1] = [ ISO_Level3_Shift , { ISO_Level3_Shift, ISO_Group_Shift } ] }; key { actions[1] = [ SetMods(modifiers=LevelThree), { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; key { symbols[1] = [ ISO_Level3_Shift , { ISO_Level3_Shift, ISO_Group_Shift } ], actions[1] = [ SetMods(modifiers=LevelThree), { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; key { symbols[1] = [ { ISO_Level3_Shift, ISO_Group_Shift }, ISO_Level3_Shift ] }; key { actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) }, SetMods(modifiers=LevelThree) ] }; key { symbols[1] = [ { ISO_Level3_Shift, ISO_Group_Shift }, ISO_Level3_Shift ], actions[1] = [ { SetMods(modifiers=LevelThree), SetGroup(group=+1) }, SetMods(modifiers=LevelThree) ] }; key { symbols[1] = [ ISO_Level3_Shift , { ISO_Level3_Shift, ISO_Group_Shift }, { ISO_Level3_Shift, ISO_Group_Shift } ] }; key { actions[1] = [ SetMods(modifiers=LevelThree), { SetMods(modifiers=LevelThree), SetGroup(group=+1) }, { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; key { symbols[1] = [ ISO_Level3_Shift , { ISO_Level3_Shift, ISO_Group_Shift }, { ISO_Level3_Shift, ISO_Group_Shift } ], actions[1] = [ SetMods(modifiers=LevelThree), { SetMods(modifiers=LevelThree), SetGroup(group=+1) }, { SetMods(modifiers=LevelThree), SetGroup(group=+1) } ] }; // Using modifier_map (may trigger multiple interprets) key { symbols[1] = [ { a, b } ] }; modifier_map Shift { }; // Our only alphanum key ✨ key { [ 2, at ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/nbsp000066400000000000000000000104661510033435100231370ustar00rootroot00000000000000// Let Space key provide No-Break Space (NBSP), Narrow No-Break Space (NNBSP), // Zero-Width Non-Joiner (ZWNJ), and Zero-Width Joiner (ZWJ) for the desired // levels. //////////////////////////////////////// // Only Space partial xkb_symbols "none" { key { type[Group1]="ONE_LEVEL", symbols[Group1]= [ space ] }; }; //////////////////////////////////////// // No-Break Space partial xkb_symbols "level2" { key { type[Group1]="TWO_LEVEL", symbols[Group1]= [ space, nobreakspace ] }; }; // level3 & level3ns provide no-breaking spaces starting from level3 // This is good for typographers but experience shows many users accidently // type no-breaking spaces on the CLI (resulting in errors) // Used by fr(latin9) and lt(std) partial xkb_symbols "level3" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, space, nobreakspace ] }; }; // level3s kills fourth level // Used by ca(multix) partial xkb_symbols "level3s" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, space, nobreakspace, NoSymbol ] }; }; // for this reason pushing no-breaking spaces to level4 is the safe default nowadays partial xkb_symbols "level4" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, space, space, nobreakspace ] }; }; //////////////////////////////////////// // Narrow No-Break Space // level3n provides narrow no-breaking space in addition to the normal one partial xkb_symbols "level3n" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, space, nobreakspace, 0x100202F ] }; }; // level4n provides narrow no-breaking space in addition to the normal one partial xkb_symbols "level4n" { key { type[Group1]="EIGHT_LEVEL", symbols[Group1]= [ space, space, space, nobreakspace, space, 0x100202F, NoSymbol, NoSymbol ] }; }; // level4nl provides narrow no-breaking space in addition to the normal one // without forcing the use of level5 for mostly four-level layouts // Used by fr(oss), be(oss)… partial xkb_symbols "level4nl" { key { type[Group1]="LOCAL_EIGHT_LEVEL", symbols[Group1]= [ space, space, space, nobreakspace, space, 0x100202F, NoSymbol, NoSymbol ] }; }; //////////////////////////////////////// // Zero-Width Non-Joiner & Zero-Width Joiner // Author: Behnam Esfahbod // ZWNJ and ZWJ are widely used in Persian, Kurdinsh, Pashto, Uzbek and other // languages that use PersoArabic script. // ZWNJ on level 2 partial xkb_symbols "zwnj2" { key { type[Group1]="TWO_LEVEL", symbols[Group1]= [ space, 0x100200c ] }; }; // ZWNJ on level 2 // ZWJ on level 3 partial xkb_symbols "zwnj2zwj3" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, 0x100200c, 0x100200d ] }; }; // ZWNJ on level 2 // ZWJ on level 3 // NBSP on level 4 partial xkb_symbols "zwnj2zwj3nb4" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, 0x100200c, 0x100200d, nobreakspace ] }; }; // ZWNJ on level 2 // NBSP on level 3 // Used by ir(ku_ara), af(basic), af(ps), af(uz), af(olpc-fa), af(olpc-ps), af(olpc-uz) partial xkb_symbols "zwnj2nb3" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, 0x100200c, nobreakspace ] }; }; // ZWNJ on level 2 // NBSP on level 3 partial xkb_symbols "zwnj2nb3s" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, 0x100200c, nobreakspace, NoSymbol ] }; }; // ZWNJ on level 2 // NBSP on level 3 // ZWJ on level 4 partial xkb_symbols "zwnj2nb3zwj4" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, 0x100200c, nobreakspace, 0x100200d ] }; }; // ZWNJ on level 2 // NBSP on level 3 // NNBSP on level 4 // Used by ir(pes) partial xkb_symbols "zwnj2nb3nnb4" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, 0x100200c, nobreakspace, 0x100202F ] }; }; // ZWNJ on level 3 // ZWJ on level 4 // Used by in(deva), in(olpc) partial xkb_symbols "zwnj3zwj4" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, space, 0x100200c, 0x100200d ] }; }; // NBSP on level 2 // ZWNJ on level 3 // Used by lk(sin_phonetic) partial xkb_symbols "nb2zwnj3s" { key { type[Group1]="FOUR_LEVEL", symbols[Group1]= [ space, nobreakspace, 0x100200c, NoSymbol ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/numeric_keysyms000066400000000000000000000005311510033435100254130ustar00rootroot00000000000000default alphanumeric_keys xkb_symbols "numeric keysyms" { name[Group1]= "My Awesome Layout"; key { [ 536870909 ] }; key { [ 0x1ffffffe ] }; key { [ 0x1fffffff, 0xffffffff ] }; modMap Mod1 { 536870909 }; modMap Mod2 { 0x1ffffffe }; modMap Mod3 { 0x1fffffff }; modMap Mod4 { 0xffffffff }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/overlapping_modifiers000066400000000000000000000004371510033435100265610ustar00rootroot00000000000000partial modifier_keys xkb_symbols "super_hyper" { key { type[1] = "TWO_LEVEL", symbols[1] = [ Super_L, Hyper_L ] }; modifier_map Mod3 { }; }; xkb_symbols "meta" { key { type[1] = "ONE_LEVEL", symbols[1] = [ Meta_L ] }; modifier_map Mod3 { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/pc000066400000000000000000000050061510033435100225710ustar00rootroot00000000000000xkb_symbols "pc105-pure-virtual-modifiers" { key { [ Escape ] }; // The extra key on many European keyboards: key { [ less, greater, bar, brokenbar ] }; // The following keys are common to all layouts. key { [ backslash, bar ] }; key { [ space ] }; include "srvr_ctrl(fkey2vt)" include "pc(editing)" include "keypad(x11)" key { [ BackSpace, BackSpace ] }; key { [ Tab, ISO_Left_Tab ] }; key { [ Return ] }; key { [ Caps_Lock ] }; key { [ Num_Lock ] }; key { [ Shift_L ] }; key { [ Control_L ] }; key { [ Super_L ] }; key { [ Shift_R ] }; key { [ Control_R ] }; key { [ Super_R ] }; key { [ Menu ] }; // Fake keys for virtual<->real modifiers mapping: key { [ ISO_Level3_Shift ] }; key { [ Mode_switch ] }; key { [ NoSymbol, Alt_L ] }; key { [ Alt_L, Meta_L ] }; key { type[Group1] = "TWO_LEVEL", symbols[Group1] = [ Alt_R, Meta_R ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; key { [ NoSymbol, Hyper_L ] }; // End of modifier mappings. key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; }; default partial alphanumeric_keys modifier_keys xkb_symbols "pc105" { include "pc(pc105-pure-virtual-modifiers)" // Beginning of modifier mappings. modifier_map Shift { Shift_L, Shift_R }; modifier_map Lock { Caps_Lock }; modifier_map Control{ Control_L, Control_R }; modifier_map Mod1 { , Alt_L, Alt_R, Meta_L, Meta_R }; modifier_map Mod2 { Num_Lock }; modifier_map Mod4 { , , Super_L, Super_R }; modifier_map Mod5 { , }; }; hidden partial alphanumeric_keys xkb_symbols "editing" { key { type= "PC_ALT_LEVEL2", symbols[Group1]= [ Print, Sys_Req ] }; key { [ Scroll_Lock ] }; key { type= "PC_CONTROL_LEVEL2", symbols[Group1]= [ Pause, Break ] }; key { [ Insert ] }; key { [ Home ] }; key { [ Prior ] }; key { [ Delete ] }; key { [ End ] }; key { [ Next ] }; key { [ Up ] }; key { [ Left ] }; key { [ Down ] }; key { [ Right ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/recursive000066400000000000000000000002411510033435100241720ustar00rootroot00000000000000default xkb_symbols "foo" { include "recursive" }; xkb_symbols "bar" { include "recursive(baz)" }; xkb_symbols "baz" { include "recursive(bar)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/ru000066400000000000000000002046241510033435100226240ustar00rootroot00000000000000// Keyboard layouts for Russia. // AEN // 2001/12/23 by Leon Kanter // 2005/12/09 Valery Inozemtsev // 2018/07/15 @a13 (a.k.a. @dbvvmpg) and Stepanenko Andrey // Windows layout default partial alphanumeric_keys xkb_symbols "winkeys" { include "ru(common)" name[Group1]= "Russian"; key { [ 3, numerosign ] }; key { [ 4, semicolon ] }; key { [ 5, percent ] }; key { [ 6, colon ] }; key { [ 7, question ] }; key { [ 8, asterisk, U20BD ] }; key { [ period, comma ] }; key { [ backslash, slash ] }; }; hidden partial alphanumeric_keys xkb_symbols "common" { key { [ 1, exclam ] }; key { [ 2, quotedbl ] }; key { [ 3, numbersign ] }; key { [ 4, asterisk ] }; key { [ 5, colon ] }; key { [ 6, comma ] }; key { [ 7, period ] }; key { [ 8, semicolon ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ backslash, bar ] }; key { [ slash, question ] }; key { [ slash, bar ] }; key { [ Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_u, Cyrillic_U ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [ Cyrillic_ie, Cyrillic_IE ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_ghe, Cyrillic_GHE ] }; key { [ Cyrillic_sha, Cyrillic_SHA ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ Cyrillic_ze, Cyrillic_ZE ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_e, Cyrillic_E ] }; key { [ Cyrillic_ya, Cyrillic_YA ] }; key { [ Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_es, Cyrillic_ES ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ Cyrillic_i, Cyrillic_I ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_yu, Cyrillic_YU ] }; include "kpdl(comma)" }; partial alphanumeric_keys xkb_symbols "legacy" { include "ru(common)" name[Group1]= "Russian (legacy)"; }; partial alphanumeric_keys xkb_symbols "olpc" { include "ru(common)" key { [ 0x01000451, 0x01000401, grave ] }; // Ñ‘, Ð key { [ 3, numbersign, 0x01002116 ] }; // â„– key { [ 4, dollar, semicolon ] }; key { [ 6, asciicircum, colon ] }; key { [ 7, ampersand ] }; key { [ 9, parenleft, acute ] }; key { [ backslash, bar, slash ] }; include "group(olpc)" }; partial alphanumeric_keys xkb_symbols "typewriter" { include "ru(common)" name[Group1]= "Russian (typewriter)"; key { [ bar, plus ] }; key { [ numerosign, 1 ] }; key { [ minus, 2 ] }; key { [ slash, 3 ] }; key { [ quotedbl, 4 ] }; key { [ colon, 5 ] }; key { [ comma, 6 ] }; key { [ period, 7 ] }; key { [ underscore, 8 ] }; key { [ question, 9 ] }; key { [ percent, 0 ] }; key { [ exclam, equal ] }; key { [ semicolon, backslash ] }; key { [ parenright, parenleft ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN ] }; key { [ Cyrillic_io, Cyrillic_IO ] }; }; partial alphanumeric_keys xkb_symbols "typewriter-legacy" { include "ru(common)" name[Group1]= "Russian (typewriter, legacy)"; key { [ apostrophe, quotedbl ] }; key { [ exclam, 1 ] }; key { [ numerosign, 2 ] }; key { [ slash, 3 ] }; key { [ semicolon, 4 ] }; key { [ colon, 5 ] }; key { [ comma, 6 ] }; key { [ period, 7 ] }; key { [ underscore, 8 ] }; key { [ question, 9 ] }; key { [ percent, 0 ] }; key { [ parenleft, parenright ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN ] }; key { [ Cyrillic_io, Cyrillic_IO ] }; }; partial alphanumeric_keys xkb_symbols "phonetic" { name[Group1]= "Russian (phonetic)"; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, Cyrillic_io ] }; key { [ 4, Cyrillic_IO ] }; key { [ 5, Cyrillic_hardsign ] }; key { [ 6, Cyrillic_HARDSIGN ] }; key { [ 7, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ minus, underscore ] }; key { [ period, greater ] }; key { [ slash, question ] }; key { [ comma, less ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ bar, brokenbar ] }; key { [ Cyrillic_yu, Cyrillic_YU ] }; key { [ Cyrillic_ya, Cyrillic_YA ] }; key { [ Cyrillic_ze, Cyrillic_ZE ] }; key { [ Cyrillic_es, Cyrillic_ES ] }; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_ie, Cyrillic_IE ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_ghe, Cyrillic_GHE ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; key { [ Cyrillic_u, Cyrillic_U ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [ Cyrillic_i, Cyrillic_I ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_sha, Cyrillic_SHA ] }; key { [ Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ Cyrillic_e, Cyrillic_E ] }; }; partial alphanumeric_keys xkb_symbols "phonetic_winkeys" { include "ru(phonetic)" name[Group1]= "Russian (phonetic, Windows)"; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; }; partial alphanumeric_keys xkb_symbols "phonetic_YAZHERTY" { include "ru(phonetic_winkeys)" name[Group1]= "Russian (phonetic, YAZHERTY)"; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; }; partial alphanumeric_keys xkb_symbols "tt" { include "ru(winkeys)" name[Group1]= "Tatar"; key.type[group1]="FOUR_LEVEL"; key { [ Cyrillic_shha, Cyrillic_SHHA, Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_o_bar, Cyrillic_O_bar, Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_schwa, Cyrillic_SCHWA, Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ Cyrillic_u_straight, Cyrillic_U_straight, Cyrillic_hardsign, Cyrillic_HARDSIGN ] }; key { [ Cyrillic_en_descender, Cyrillic_EN_descender, Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_zhe_descender, Cyrillic_ZHE_descender, Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "os_legacy" { include "ru(common)" name[Group1]= "Ossetian (legacy)"; key { [ Cyrillic_e, Cyrillic_E ] }; key { [ Cyrillic_o, Cyrillic_O, Cyrillic_io, Cyrillic_IO ] }; key { [ 0x010004D5, 0x010004D4 ] }; }; partial alphanumeric_keys xkb_symbols "os_winkeys" { include "ru(winkeys)" name[Group1]= "Ossetian (Windows)"; key { [ Cyrillic_e, Cyrillic_E ] }; key { [ Cyrillic_o, Cyrillic_O, Cyrillic_io, Cyrillic_IO ] }; key { [ 0x010004D5, 0x010004D4 ] }; }; partial alphanumeric_keys xkb_symbols "cv" { include "ru(winkeys)" name[Group1]= "Chuvash"; key.type[group1]="FOUR_LEVEL"; key { [ Cyrillic_u, Cyrillic_U, 0x010004f3, 0x010004f2 ] }; key { [ Cyrillic_ie, Cyrillic_IE, 0x010004d7, 0x010004d6 ] }; key { [ Cyrillic_a, Cyrillic_A, 0x010004d1, 0x010004d0 ] }; key { [ Cyrillic_es, Cyrillic_ES, 0x010004ab, 0x010004aa ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "udm" { include "ru(winkeys)" name[Group1]= "Udmurt"; key.type[group1]="FOUR_LEVEL"; key { [ question, exclam, 1, 1 ] }; key { [ parenleft, quotedbl, 2, 2 ] }; key { [ parenright, numerosign, 3, 3 ] }; key { [ colon, semicolon, 4, 4 ] }; key { [ asterisk, percent, 5, 5 ] }; key { [ 0x010004dd, 0x010004dc, 6, 6 ] }; key { [ 0x010004e7, 0x010004e6, 7, 7 ] }; key { [ 0x010004f5, 0x010004f4, 8, 8 ] }; key { [ 0x010004e5, 0x010004e4, 9, 9 ] }; key { [ 0x010004df, 0x010004de, 0, 0 ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "cv_latin" { include "us(alt-intl)" name[Group1]= "Chuvash (Latin)"; key.type[group1]="FOUR_LEVEL"; key { [ q, Q, 0x01000161, 0x01000160 ] }; key { [ w, W, udiaeresis, Udiaeresis ] }; key { [ e, E, 0x01000115, 0x01000114 ] }; key { [ u, U, udiaeresis, Udiaeresis ] }; key { [ i, I, 0x0100012d, 0x0100012c ] }; key { [ o, O, odiaeresis, Odiaeresis ] }; key { [ a, A, abreve, Abreve ] }; key { [ s, S, scedilla, Scedilla ] }; key { [ g, G, gbreve, Gbreve ] }; key { [ j, J, 0x01000131, 0x01000130 ] }; key { [ c, C, ccedilla, Ccedilla ] }; include "level3(ralt_switch)" }; // Komi language layout // Vlad Shakhov // last changes 2007/10/23 partial alphanumeric_keys xkb_symbols "kom" { include "ru(winkeys)" name[Group1]= "Komi"; key.type[group1]="FOUR_LEVEL_ALPHABETIC"; // cyrilllic o with diaeresis key { [ Cyrillic_o, Cyrillic_O, U04E7, U04E6 ] }; // hard I as additional key for soft Cyrillic_I key { [ Cyrillic_i, Cyrillic_I, Ukrainian_i, Ukrainian_I ] }; include "level3(ralt_switch)" }; // Yakut language layout // 2008/04/23 Yakov Aleksandrov // 2008/04/23 Anatoliy Zhozhikov // 2008/04/23 Aleksandr Varlamov partial alphanumeric_keys xkb_symbols "sah" { include "ru(winkeys)" name[Group1]= "Yakut"; key.type[group1]="FOUR_LEVEL_ALPHABETIC"; key { [ Cyrillic_io, Cyrillic_IO, U04EB, U04EA ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI, U048B, U048A ] }; key { [ Cyrillic_u, Cyrillic_U, Cyrillic_u_straight, Cyrillic_U_straight ] }; key { [ Cyrillic_ka, Cyrillic_KA, U04C4, U04C3 ] }; key { [ Cyrillic_en, Cyrillic_EN, U04A5, U04A4 ] }; key { [ Cyrillic_ghe, Cyrillic_GHE, U0495, U0494 ] }; key { [ Cyrillic_ze, Cyrillic_ZE, U04E1, U04E0 ] }; key { [ Cyrillic_ha, Cyrillic_HA, Cyrillic_shha, Cyrillic_SHHA ] }; key { [ Cyrillic_o, Cyrillic_O, Cyrillic_o_bar, Cyrillic_O_bar ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE, U0461, U0460 ] }; key { [ Cyrillic_che, Cyrillic_CHE, Cyrillic_u_macron, Cyrillic_U_macron ] }; key { [ Cyrillic_em, Cyrillic_EM, U04C8, U04C7 ] }; key { [ Cyrillic_i, Cyrillic_I, Cyrillic_i_macron, Cyrillic_I_macron ] }; include "level3(ralt_switch)" }; //Kalmyk language layout //based on the Kalmyk language layout: http://soft.oyrat.org/ //Nikolay Korneev //Toli Miron partial alphanumeric_keys xkb_symbols "xal" { include "ru(winkeys)" name[Group1]= "Kalmyk"; key.type[group1]="FOUR_LEVEL"; key { [ question, exclam, 1 ] }; key { [ numerosign, quotedbl, 2 ] }; key { [ Cyrillic_u_straight, Cyrillic_U_straight, 3 ] }; key { [ Cyrillic_schwa, Cyrillic_SCHWA, 4 ] }; key { [ asterisk, percent, 5 ] }; key { [ Cyrillic_en_descender, Cyrillic_EN_descender, 6 ] }; key { [ Cyrillic_o_bar, Cyrillic_O_bar, 7 ] }; key { [ Cyrillic_shha, Cyrillic_SHHA, 8 ] }; key { [ Cyrillic_zhe_descender, Cyrillic_ZHE_descender, 9 ] }; key { [ semicolon, colon, 0 ] }; key { [ parenleft, parenright, Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_tse, Cyrillic_TSE, dollar ] }; key { [ Cyrillic_u, Cyrillic_U, EuroSign ] }; key { [ Cyrillic_ka, Cyrillic_KA, registered ] }; key { [ Cyrillic_ie, Cyrillic_IE, trademark ] }; key { [ Cyrillic_ha, Cyrillic_HA, bracketleft ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, bracketright ] }; key { [ Cyrillic_e, Cyrillic_E, apostrophe ] }; key { [ Cyrillic_es, Cyrillic_ES, copyright ] }; key { [ Cyrillic_be, Cyrillic_BE, less ] }; key { [ Cyrillic_yu, Cyrillic_YU, greater ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "dos" { include "ru(common)" name[Group1]= "Russian (DOS)"; key { [ parenright, parenleft ] }; key { [ 4, currency ] }; key { [ 9, question ] }; key { [ 0, percent ] }; key { [ Cyrillic_io, Cyrillic_IO ] }; }; partial alphanumeric_keys xkb_symbols "bak" { include "ru(winkeys)" name[Group1]= "Bashkirian"; key.type[group1]="FOUR_LEVEL"; key { [ Cyrillic_schwa, Cyrillic_SCHWA, Cyrillic_io, Cyrillic_IO ] }; key { [ exclam, quotedbl, 1, 1 ] }; key { [ Cyrillic_o_bar, Cyrillic_O_bar, 2, 2 ] }; key { [ 0x010004a1, 0x010004a0, 3, 3 ] }; key { [ Cyrillic_ghe_bar, Cyrillic_GHE_bar, 4, 4 ] }; key { [ 0x010004ab, 0x010004aa, 5, 5 ] }; key { [ colon, semicolon, 6, 6 ] }; key { [ 0x01000499, 0x01000498, 7, 7 ] }; key { [ Cyrillic_shha, Cyrillic_SHHA, 8, 8 ] }; key { [ question, parenleft, 9, 9 ] }; key { [ numerosign, parenright, 0, 0 ] }; key { [ minus, percent, minus, underscore ] }; key { [ Cyrillic_u_straight, Cyrillic_U_straight, equal, plus ] }; key { [ Cyrillic_en_descender, Cyrillic_EN_descender, backslash, slash ] }; include "level3(ralt_switch)" }; // Serbian characters are added as third-level symbols to Russian keyboard layout. partial alphanumeric_keys xkb_symbols "srp" { include "ru(common)" name[Group1]= "Serbian (Russia)"; key { [ 3, numerosign ] }; key { [ 4, semicolon ] }; key { [ 5, percent ] }; key { [ 6, colon ] }; key { [ 7, question ] }; key { [ 8, asterisk ] }; key { [ period, comma ] }; key { [ backslash, slash ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI, U458, U408 ] }; key { [ Cyrillic_en, Cyrillic_EN, U45A, U40A ] }; key { [ Cyrillic_el, Cyrillic_EL, U459, U409 ] }; key { [ Cyrillic_de, Cyrillic_DE, U45F, U40F ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE, U452, U402 ] }; key { [ Cyrillic_che, Cyrillic_CHE, U45B, U40B ] }; include "level3(ralt_switch)" }; // Mari language layout // http://www.marlamuter.com/ // Last edit by Viatcheslav Kileev (slavakileev@yandex.ru) partial alphanumeric_keys xkb_symbols "chm" { include "ru(winkeys)" name[Group1]= "Mari"; key.type[group1]="FOUR_LEVEL_ALPHABETIC"; key { [ Cyrillic_a, Cyrillic_A, U04D3, U04D2 ] }; key { [ Cyrillic_u, Cyrillic_U, U04F1, U04F0 ] }; key { [ Cyrillic_yeru, Cyrillic_YERU, U04F9, U04F8 ] }; key { [ Cyrillic_en, Cyrillic_EN, U04A5, U04A4 ] }; key { [ Cyrillic_o, Cyrillic_O, U04E7, U04E6 ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "phonetic_azerty" { include "level3(ralt_switch)" name[Group1]= "Russian (phonetic, AZERTY)"; key { [ ampersand, 1, onesuperior, exclamdown ] }; key { [ eacute, 2, asciitilde, oneeighth ] }; key { [ quotedbl, 3, numbersign, sterling ] }; key { [apostrophe, 4, braceleft, dollar ] }; key { [ parenleft, 5, bracketleft, threeeighths ] }; key { [ minus, 6, bar, fiveeighths ] }; key { [ egrave, 7, grave, seveneighths ] }; key { [underscore, 8, backslash, trademark ] }; key { [ ccedilla, 9, asciicircum, plusminus ] }; key { [ agrave, 0, at, degree ] }; key { [parenright, degree, bracketright, questiondown ] }; key { [ equal, plus, braceright, dead_ogonek ] }; key { [ comma, question, acute, doubleacute ] }; key { [ semicolon, period, horizconnector, multiply ] }; key { [ colon, slash, periodcentered, division ] }; key { [ exclam, section, dead_belowdot, dead_abovedot ] }; key { [ ugrave, percent, asciicircum, caron ] }; key { [ bar, brokenbar ] }; key { [ Cyrillic_yu, Cyrillic_YU ] }; key { [ Cyrillic_ya, Cyrillic_YA ] }; // Q key { [ Cyrillic_ze, Cyrillic_ZE ] }; // Z key { [ Cyrillic_es, Cyrillic_ES ] }; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; // W key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_ie, Cyrillic_IE ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_ghe, Cyrillic_GHE ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; // M key { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; key { [ Cyrillic_u, Cyrillic_U ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [ Cyrillic_i, Cyrillic_I ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_sha, Cyrillic_SHA ] }; key { [ Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ Cyrillic_e, Cyrillic_E ] }; }; // Russian dvorak phonetic layout // Oleg Zalizniak partial alphanumeric_keys xkb_symbols "phonetic_dvorak" { include "level3(ralt_switch)" name[Group1]= "Russian (phonetic, Dvorak)"; key { [ Cyrillic_yu, Cyrillic_YU ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, Cyrillic_io ] }; key { [ 4, Cyrillic_IO ] }; key { [ 5, Cyrillic_hardsign ] }; key { [ 6, Cyrillic_HARDSIGN ] }; key { [ 7, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ Cyrillic_sha, Cyrillic_SHA ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ Cyrillic_e, Cyrillic_E ] }; key { [ apostrophe, quotedbl, dead_acute, dead_diaeresis ] }; key { [ comma, less, dead_cedilla, dead_caron ] }; key { [ period, greater, dead_abovedot, periodcentered ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_ghe, Cyrillic_GHE ] }; key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ slash, question ] }; key { [ Cyrillic_che, Cyrillic_CHE ] }; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_ie, Cyrillic_IE ] }; key { [ Cyrillic_u, Cyrillic_U ] }; key { [ Cyrillic_i, Cyrillic_I ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_es, Cyrillic_ES ] }; key { [ minus, underscore ] }; key { [ semicolon, colon, dead_ogonek, dead_doubleacute ] }; key { [ Cyrillic_ya, Cyrillic_YA ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_ze, Cyrillic_ZE ] }; }; partial alphanumeric_keys xkb_symbols "phonetic_fr" { include "fr" include "ru(phonetic_azerty)" name[Group1]= "Russian (phonetic, French)"; }; // EXTRAS: // Rulemak, Colemak based Russian phonetic layout // contact: Geert Hendrickx // http://forum.colemak.com/viewtopic.php?id=519 // // ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━┓ // │ Ё ``│ ! ˝ │ @ │ № │ $ │ % │ ^ ¯ │ & │ * ₴ │ ( │ ) │ _ — │ Ъ + ┃ ⌫ ┃ // │ ё ` │ 1 ´ │ 2 ¨ │ 3 # │ 4 ¢ │ 5 € │ 6 ˘ │ 7 │ 8 ₽ │ 9 [ │ 0 ] │ - – │ ъ = ┃Backspace┃ // ┢━━━━━┷━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┺━┳━━━━━━━┫ // ┃ ┃ Я Ѣ │ Ж Ѵ │ Ф Ѳ │ П │ Г Ґ │ й Ј │ Л Љ │ У Ў │ Ы Ї │ Ю : │ Ш { │ Щ } ┃ Enter ┃ // ┃ Tab ↹ ┃ я ѣ │ ж ѵ │ ф ѳ │ п │ г ґ │ й ј │ л љ │ у ў │ ы ї │ ю ; │ ш « │ щ » ┃ ⏎ ┃ // ┣━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┺┓ ┃ // ┃ ⌫ Back ┃ А │ Р │ С │ Т Ћ │ Д Ђ │ Ч Џ │ Н Њ │ Е Є │ И І │ О │ Ь " │ Э | ┃ ┃ // ┃ space ┃ а │ р │ с │ т ћ │ д ђ │ ч џ │ н њ │ е є │ и і │ о │ ь ' │ э \ ┃ ┃ // ┣━━━━━━━━┻━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┲━━━┷━━━━━┻━━━━━━┫ // ┃ ┃ З Ѕ │ Х │ Ц │ В │ Б Ѓ │ К Ќ │ М │ ; │ : │ ? Ӏ ┃ ┃ // ┃ Shift ⇧ ┃ з ѕ │ х │ ц │ в │ б ѓ │ к ќ │ м │ , < │ . > │ / ӏ ┃ Shift ⇧ ┃ // ┣━━━━━━━┳━━┻━━━━┳┷━━━━━┷┱────┴─────┴─────┴─────┴─────┴─────┴┲━━━━┷━━┳━━┻━━━━┳━━━━━━━┳━━━┛ // ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ // ┃ Ctrl ┃ Meta ┃ Alt ┃ Space ┃AltGr ⇮┃ Menu ┃ Ctrl ┃ // ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹───────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┛ partial alphanumeric_keys xkb_symbols "rulemak" { name[Group1]= "Russian (Rulemak, phonetic Colemak)"; key { [ Cyrillic_io, Cyrillic_IO, U0300, U030F ] }; // Combining grave, double grave key { [ 1, exclam, U0301, U030B ] }; // Combining acute, double acute key { [ 2, at, U0308 ] }; // Combining diaeresis key { [ 3, numerosign, numbersign ] }; key { [ 4, dollar, cent ] }; key { [ 5, percent, EuroSign ] }; key { [ 6, asciicircum, U0306, U0304 ] }; // Combining breve, macron key { [ 7, ampersand ] }; key { [ 8, asterisk, U20BD, U20B4 ] }; // ruble, hryvnia key { [ 9, parenleft, bracketleft ] }; key { [ 0, parenright, bracketright ] }; key { [ minus, underscore, endash, emdash ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, equal, plus ] }; key { [ Cyrillic_ya, Cyrillic_YA, U0463, U0462 ] }; // yat key { [ Cyrillic_zhe, Cyrillic_ZHE, U0475, U0474 ] }; // izhitsa key { [ Cyrillic_ef, Cyrillic_EF, U0473, U0472 ] }; // fita key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_ghe, Cyrillic_GHE, Ukrainian_ghe_with_upturn, Ukrainian_GHE_WITH_UPTURN ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI, Cyrillic_je, Cyrillic_JE ] }; key { [ Cyrillic_el, Cyrillic_EL, Cyrillic_lje, Cyrillic_LJE ] }; key { [ Cyrillic_u, Cyrillic_U, Byelorussian_shortu, Byelorussian_SHORTU ] }; key { [ Cyrillic_yeru, Cyrillic_YERU, Ukrainian_yi, Ukrainian_YI ] }; key { [ Cyrillic_yu, Cyrillic_YU, semicolon, colon ] }; key { [ Cyrillic_sha, Cyrillic_SHA, guillemotleft, braceleft ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA, guillemotright, braceright ] }; key { [ Cyrillic_e, Cyrillic_E, backslash, bar ] }; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_es, Cyrillic_ES ] }; key { [ Cyrillic_te, Cyrillic_TE, Serbian_tshe, Serbian_TSHE ] }; key { [ Cyrillic_de, Cyrillic_DE, Serbian_dje, Serbian_DJE ] }; key { [ Cyrillic_che, Cyrillic_CHE, Cyrillic_dzhe, Cyrillic_DZHE ] }; key { [ Cyrillic_en, Cyrillic_EN, Cyrillic_nje, Cyrillic_NJE ] }; key { [ Cyrillic_ie, Cyrillic_IE, Ukrainian_ie, Ukrainian_IE ] }; key { [ Cyrillic_i, Cyrillic_I, Ukrainian_i, Ukrainian_I ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN, apostrophe, quotedbl ] }; key { [ Cyrillic_ze, Cyrillic_ZE, Macedonia_dse, Macedonia_DSE ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_be, Cyrillic_BE, Macedonia_gje, Macedonia_GJE ] }; key { [ Cyrillic_ka, Cyrillic_KA, Macedonia_kje, Macedonia_KJE ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ comma, semicolon, less ] }; key { [ period, colon, greater ] }; key { [ slash, question, U04CF, U04C0 ] }; // palochka key { [ equal, plus, multiply, division ] }; include "level3(ralt_switch)" include "capslock(backspace)" include "nbsp(level4)" }; // Church Slavonic language layout // based on the Russian standard keyboard // by Aleksandr Andreev and Yuri Shardt // last changes 2010/08/01; contact partial alphanumeric_keys xkb_symbols "chu" { name[Group1]= "Church Slavonic"; key { [ Ukrainian_yi, Ukrainian_YI, U0482, U20DD ] }; // ї Ї ҂ e.g: а⃝ where the last is a combining ten thousands sign key { [ U0461, U0460, U047D, U047C ] }; // ѡ Ѡ ѽ Ѽ key { [ Ukrainian_ie, Ukrainian_IE, U0465, U0464 ] }; // є Є ѥ Ѥ key { [ U046F, U046E, U0469, U0468 ] }; // ѯ Ѯ ѩ Ѩ key { [ U0471, U0470, U046D, U046C ] }; // ѱ Ѱ ѭ Ѭ key { [ U0473, U0472, UA657, UA656 ] }; // ѳ Ѳ iotified A key { [ U0475, U0474, U0477, U0476 ] }; // ѵ Ѵ ѷ Ѷ key { [ U047B, U047A, UA64D, UA64C ] }; // ѻ Ѻ ꙍ Ꙍ key { [ U047F, U047E, U046B, U046A ] }; // ѿ Ѿ ѫ Ѫ key { [ Macedonia_dse, Macedonia_DSE, parenleft, asterisk ] }; // ѕ Ѕ ( * key { [ Cyrillic_u, Cyrillic_U, parenright, U0488]}; // у У ) NB: for digraph Ouk, use Cyrillic_o + Cyrillic_u key { [ U0483, U0486, U0487, U005F ] }; // а҃ а҆ а҇, _ (titlo, psili, pokrytie, underscore) key { [ U0301, U0300, U0484, UA67E ] }; // а̀ а́ а҄ ꙾ (oxia, varia, kamora, kavyka) key { [ Cyrillic_shorti, Cyrillic_SHORTI, Ukrainian_i ] }; key { [ Cyrillic_tse, Cyrillic_TSE, U2DF0 ] }; key { [ UA64B, UA64A, U2DF9 ] }; // Cyrillic monograph Uk (not U)! key { [ Cyrillic_ka, Cyrillic_KA, U2DE6 ] }; key { [ Cyrillic_ie, Cyrillic_IE, U2DF7 ] }; key { [ Cyrillic_en, Cyrillic_EN, U2DE9 ] }; key { [ Cyrillic_ghe, Cyrillic_GHE, U2DE2 ] }; key { [ Cyrillic_sha, Cyrillic_SHA, U2DF2 ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA, U2DF3 ] }; key { [ Cyrillic_ze, Cyrillic_ZE, U2DE5 ] }; key { [ Cyrillic_ha, Cyrillic_HA, U2DEF ] }; key { [Cyrillic_hardsign,Cyrillic_HARDSIGN, UA67D ] }; // Payerok key { [ backslash, slash, colon, question ] }; // \ / : ? NB: for Slavonic question, use semicolon key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_ve, Cyrillic_VE, U2DE1 ] }; key { [ Cyrillic_a, Cyrillic_A, U2DF6 ] }; key { [ Cyrillic_pe, Cyrillic_PE, U2DEB ] }; key { [ Cyrillic_er, Cyrillic_ER, U2DEC ] }; key { [ Cyrillic_o, Cyrillic_O, U2DEA ] }; key { [ Cyrillic_el, Cyrillic_EL, U2DE7 ] }; key { [ Cyrillic_de, Cyrillic_DE, U2DE3 ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE, U2DE4 ] }; key { [ U0463, U0462, U2DFA ] }; // Yat key { [ U0467, U0466, U2DFD ] }; // Small Yus key { [ Cyrillic_che, Cyrillic_CHE, U2DF1 ] }; key { [ Cyrillic_es, Cyrillic_ES, U2DED ] }; key { [ Cyrillic_em, Cyrillic_EM, U2DE8 ] }; key { [ Cyrillic_i, Cyrillic_I ] }; key { [ Cyrillic_te, Cyrillic_TE, U2DEE ] }; key { [Cyrillic_softsign,Cyrillic_SOFTSIGN ] }; key { [ Cyrillic_be, Cyrillic_BE, U2DE0 ] }; key { [ Cyrillic_yu, Cyrillic_YU, U2DFB ] }; key { [ period, comma, semicolon, exclam ] }; }; // RUU (Russian-Ukrainian United keyboard layout). // This is a modified Russian standard keyboard, with the third level containing // Ukrainian and Belorusian alphabetic letters and commonly used Unicode symbols. // For a description see http://wiki.opennet.ru/RUU [in Russian]. // Vasyĺ V. Vercynśkyj // last changes 2011/05/11 // // ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━┓ // │ ' ~ │ ! ≈ │ " ∞ │ № ₴ │ ; € │ % ‰ │ : ≤ │ ? ≥ │ * × │ ( { │ ) } │ _ – │ + ± ┃ ⌫ ┃ // │ ’ ́ │ 1 ÷ │ 2 ¤ │ 3 § │ 4 $ │ 5 ° │ 6 < │ 7 > │ 8 • │ 9 [ │ 0 ] │ - — │ = ≠ ┃Backspace┃ // ┢━━━━━┷━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┺━┳━━━━━━━┫ // ┃ ┃ Й │ Ц │ У Ў │ К │ Е Ё │ Н │ Г Ґ │ Ш │ Щ │ З │ Х │ Ъ Ї ┃ Enter ┃ // ┃ Tab ↹ ┃ й │ ц │ у ў │ к ® │ е ё │ н │ г ґ │ ш │ щ │ з │ х │ ъ ї ┃ ⏎ ┃ // ┣━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┺┓ ┃ // ┃ Caps ┃ Ф │ Ы І │ В │ А │ П │ Р │ О │ Л │ Д │ Ж │ Э Є │ | ¦ ┃ ┃ // ┃ Lock ⇬ ┃ ф │ ы і │ в │ а │ п │ р │ о │ л │ д │ ж │ э є │ / \ ┃ ┃ // ┣━━━━━━━━┻━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┲━━━┷━━━━━┻━━━━━━┫ // ┃ ┃ Я │ Ч │ С │ М │ И │ Т │ Ь │ Б „ │ Ю “ │ , … ┃ ┃ // ┃ Shift ⇧ ┃ я │ ч │ с © │ м │ и │ т ™ │ ь µ │ б « │ ю » │ . / ┃ Shift ⇧ ┃ // ┣━━━━━━━┳━━┻━━━━┳┷━━━━━┷┱────┴─────┴─────┴─────┴─────┴─────┴┲━━━━┷━━┳━━┻━━━━┳━━━━━━━┳━━━┛ // ┃ ┃ ┃ ┃ ┃ ┃ ┃ ┃ // ┃ Ctrl ┃ Meta ┃ Alt ┃ Space ┃AltGr ⇮┃ Menu ┃ Ctrl ┃ // ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹───────────────────────────────────┺━━━━━━━┻━━━━━━━┻━━━━━━━┛ partial alphanumeric_keys xkb_symbols "ruu" { include "ru(common)" name[Group1]= "Russian (with Ukrainian-Belorussian layout)"; key { [ U2019, apostrophe, U0301, asciitilde ] }; // Apostrophe and Stress symbol key { [ 1, exclam, division, U2248 ] }; // Division Sign and Almost Equal To key { [ 2, quotedbl, currency, infinity ] }; key { [ 3, numerosign, section, U20B4 ] }; // Paragraph and Hryvnia sign key { [ 4, semicolon, dollar, EuroSign ] }; key { [ 5, percent, degree, permille ] }; key { [ 6, colon, less, lessthanequal ] }; key { [ 7, question, greater, greaterthanequal ] }; key { [ 8, asterisk,enfilledcircbullet,multiply ] }; key { [ 9, parenleft, bracketleft, braceleft ] }; key { [ 0, parenright, bracketright, braceright ] }; key { [ minus, underscore, emdash, endash ] }; key { [ equal, plus, notequal, plusminus ] }; key { [ Cyrillic_u, Cyrillic_U, Byelorussian_shortu, Byelorussian_SHORTU ] }; key { [ Cyrillic_ka, Cyrillic_KA, registered ] }; key { [ Cyrillic_ie, Cyrillic_IE, Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_ghe, Cyrillic_GHE, Ukrainian_ghe_with_upturn, Ukrainian_GHE_WITH_UPTURN ] }; key { [ Cyrillic_ze, Cyrillic_ZE, paragraph ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, Ukrainian_yi, Ukrainian_YI ] }; key { [ Cyrillic_yeru, Cyrillic_YERU, Ukrainian_i, Ukrainian_I ] }; key { [ Cyrillic_e, Cyrillic_E, Ukrainian_ie, Ukrainian_IE ] }; key { [ slash, bar, backslash, brokenbar ] }; key { [ Cyrillic_es, Cyrillic_ES, copyright ] }; key { [ Cyrillic_te, Cyrillic_TE, trademark ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN, mu ] }; key { [ Cyrillic_be, Cyrillic_BE, guillemotleft, doublelowquotemark ] }; key { [ Cyrillic_yu, Cyrillic_YU, guillemotright, leftdoublequotemark ] }; key { [ period, comma, slash, ellipsis ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "sun_type6" { include "sun_vndr/ru(sun_type6)" }; // Apple layout partial alphanumeric_keys xkb_symbols "mac" { include "ru(common)" name[Group1]= "Russian (Macintosh)"; key { [ less, greater ] }; key { [ 2, quotedbl ] }; key { [ 3, numerosign ] }; key { [ 4, percent ] }; key { [ 5, colon ] }; key { [ 6, comma ] }; key { [ 7, period ] }; key { [ 8, semicolon ] }; key { [ bracketright, bracketleft ] }; key { [ Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_er, Cyrillic_ER, U20BD ] }; include "level3(ralt_switch)" }; // eng: Russian-based polyglot and reactionary keyboard layout // This keyboard layout covers Russian in Petrine 1708 and Bolshevik 1918 variant spelling, Ukrainian, Belorussian, Serbian in its modern and Slavenoserbian variants, and Bulgarian and Slavomacedonian in pre-1945 and post-1945 spelling, // in short all in any dominion prevailing Cyrillic orthographies of modern secular Slavic literary languages, even with dictionary accentuation marks, // but also the most-widespread Church Slavonic spellings, that is all Church-Slavonic in so far as variants can be replaced without loss of meaning – not to speak of Interslavic. // Furthermore, it suffices Romanian Cyrillic, Moldovan Cyrillic, Abkhazian excluding the more clumsy obsoleted forms unlikely to find devotees, Tajik, all Turkic and Mongolic Cyrillic alphabets // and virtually all overlooked languages in Cyrillic reigns at least by combining characters, taking advantage of eight key levels. // This is withal a pan-Cyrillic keyboard layout, or a comprehensive Cyrillic keyboard layout, an universal Cyrillic keyboard layout, a generic Cyrillic keyboard layout. // // rus: Многоязыковая и реакціонная клавіатурная разкладка основана на русскихъ // Сія разкладка покрываетъ русскій въ петровскомъ правописаніи 1708-го года и большевицкомъ 1918-го, украинскій, бѣлорусскій въ современномъ и славяносербскомъ видѣ, и булгарскій и славомацедонскій въ писаніи до и послѣ 1945-го года, // короче всѣ въ какомъ-либо державствѣ преобладающія правописанія, то есть весь церкославянскій, поскольку какъ разные виды буквъ можно возмѣщать безъ потери значенія — не говоря о междуславянскомъ. // Свѣрхъ этого, она подходитъ къ румынской кириллицѣ, къ молдавской кириллицѣ, къ абхазскому за изключеніемъ неуклюжихъ устарѣлыхъ образовъ, у которыхъ невѣроятно что они вообще найдутъ поклонниковъ, къ таджикскому, къ всѣмъ тюрксимъ и монголскимъ кириллицамъ, // и по сути дѣла всѣмъ упущеннымъ языкамъ въ кириллическихъ правленіяхъ хотя бы соединящими сѵмволами, извлѣкая выгоду изъ восьми уровней клавишъ. // Тѣмъ всѣмъ сё всекириллическая клавіатурная разкладка, или всеобъемлющая кириллическая разкладка, или универсальная кириллическая разкладка клавіатуры. // // srp: Многојезиков и реакционаран распоред тастера основан на рускима // Овај распоред покрива руски у петровском правопису 1708-е године и бољшевичком 1918-е године, украјински, белоруски, српски у сувременом и славеносрпском виду, те бугарски и славомакедонски у писању до и после 1945-е године, // укратко све у некој држави преовлађујуће правописе, то је читав црквенословенски, пошто је могуће разне видове слова замењивати без губитка значења — не говорећи о меџусловенском. // Поврх овог, он одговара к румунској ћирилици, к молдавској ћирилици, к абхаскоме с изузетком гломазних застарелих ликова, уз које није вероватно да они најђу поклонике, к таџичкоме, к свим туркијским и монголским ћирилицима, // те у спровођењу свим испуштеним језицима у ћириличким господарствима бар са спајајућим симболима, искориштавајући осам ступњева тастера. // Тиме свим ово је свећирилички тастатуран распоред, или свеобухватан ћирилички распоред тастера, или свеопшти ћирилички тастатуран распоред. partial alphanumeric_keys xkb_symbols "prxn" { name[Group1]= "Russian (Polyglot and Reactionary)"; key.type[Group1]="EIGHT_LEVEL"; key { [ U2019, apostrophe, U0301, U0300, U2053, U2015, U02BC, asciitilde ] }; // Typographic Apostrophe, Apostrophe, Combining Acute, Combining Grave, Swung Dash, Quotation Dash, Modifier Letter Apostrophe, Tilde key { [ 1, exclam, U0304, U0306, U0308, U0311, U0307, U0313 ] }; // 1, !, Combining Macron, Combining Breve, Combining Diaresis, Combining Inverted Breve, Combining Dot Above, Combining Comma Above key { [ 2,quotedbl,numerosign, U20BF, U20B8, U20AE, U00A3, U20B9 ] }; // 2 " № ₿ ₸ ₮ £ ₹ key { [ 3, section, U20B4, currency, U20BD, U20AA, U20BC, U20BE ] }; // 3 § ₴ ¤ ₽ ₪ ₼ ₾ key { [ 4, semicolon, dollar, EuroSign, U0482, U20DD, U0488, U0489 ] }; // 4 ; $ € Thousands Sign, Combining Enclosing Circle, Combining Hundred Thousands, Combining Millions key { [ 5, percent, degree, permille, UA670, UA671, UA672, UA66F ] }; // 5, %, °, ‰, Combinining Ten Millions, Combining Hundred Millions, Combining Thousand Millions, Combining Vzmet key { [ 6, colon, U0335, U0336, U0483, U0487, UFE2E, UFE2F ] }; // 6, :, Combining Short Stroke Overlay, Combining Long Stroke Overlay, Combining Titlo, Combining Pokrytie, Combining Titlo Left Half, Combining Titlo Right Half key { [ 7, question, U030B, U030F, U030C, U0303, U032C, U0360 ] }; // 7, ?, Combining Double Acute, Combining Double Grave, Combining Caron/Háček, Combining Tilde, Combining Caron/Háček Below, Combining Double Tilde key { [ 8, asterisk, U0331, U0332, U0333, U032F, U032D, U032E ] }; // 8, *, Combining Macron Below, Combining Low Line, Combining Double Low Line, Combining Inverted Breve Below, Combining Circumflex Accent, Combining Breve Below key { [ 9,parenleft, bracketleft, braceleft, U035F, U035D, U035E, U035C ] }; // 9 ( [ { Combining Double Macron Below, Combining Double Breve, Combining Double Macron, Combining Double Breve Below key { [ 0,parenright,bracketright, braceright, U27E8, U27E9, U04A7, U04A6 ] }; // 0 ) ] } ⟨⟩ ҧ Ҧ key { [ minus, underscore, emdash, endash, U2011,hyphen, U2010, U2212 ] }; // Hyphen-Minus, Underscore, Em Dash, En Dash, Non-Breaking-Hyphen, Soft Hyphen, Hyphen, Minus Sign key { [ equal, plus,notequal, U2248, U04FF, U04FE, U050D, U050C ] }; // = + ≠ ≈ ӿ Ӿ ԍ Ԍ key { [ Cyrillic_shorti, Cyrillic_SHORTI, Cyrillic_je, Cyrillic_JE, U04CF, U04C0, U030A, U0325 ] }; // й Й ј Ј ӏ Ӏ, Combining Ring Above and Below key { [ Cyrillic_tse, Cyrillic_TSE, U04B5, U04B4, Cyrillic_u_straight, Cyrillic_U_straight, U051B, U051A ] }; // ц Ц ҵ Ҵ ү Ү ԛ Ԛ key { [ Cyrillic_u, Cyrillic_U, Byelorussian_shortu, Byelorussian_SHORTU, Cyrillic_u_straight_bar,Cyrillic_U_straight_bar, Byelorussian_shortu, Byelorussian_SHORTU ] }; // у У ў Ў ұ Ұ ў Ў key { [ Cyrillic_ka, Cyrillic_KA, Cyrillic_ka_descender, Cyrillic_KA_descender, U049F, U049E, U046F, U046E ] }; // к К Қ қ ҟ Ҟ ѯ Ѯ key { [ Cyrillic_ie, Cyrillic_IE, Cyrillic_io, Cyrillic_IO, U0463, U0462, UA653, UA652 ] }; // е Е ё Ё ѣ Ѣ ꙓ Ꙓ key { [ Cyrillic_en, Cyrillic_EN, Cyrillic_nje, Cyrillic_NJE, Cyrillic_en_descender, Cyrillic_EN_descender, U04C8, U04C7 ] }; // н Н њ Њ ң Ң ӈ Ӈ key { [ Cyrillic_ghe, Cyrillic_GHE, Ukrainian_ghe_with_upturn,Ukrainian_GHE_WITH_UPTURN, Cyrillic_ghe_bar, Cyrillic_GHE_bar, U04F7, U04F6 ] }; // г Г Ґ ґ ғ Ғ ӷ Ӷ key { [ Cyrillic_sha, Cyrillic_SHA, U04A1, U04A0, U04AB, U04AA, UA67D, UA67F ] }; // ш Ш ҡ Ҡ ҫ Ҫ Combining Payerok Payerok key { [ Cyrillic_shcha, Cyrillic_SHCHA, U0505, U0504, UA68D, UA68C, U050F, U050E ] }; // щ Щ ԅ Ԅ ꚍ Ꚍ ԏ Ԏ key { [ Cyrillic_ze, Cyrillic_ZE, U04E1, U04E0, U0499, U0498, U0507, U0506 ] }; // з З ӡ Ӡ ҙ Ҙ ԇ Ԇ key { [ Cyrillic_ha, Cyrillic_HA, Cyrillic_shha, Cyrillic_SHHA, Cyrillic_ha_descender, Cyrillic_HA_descender, U04FD, U04FC ] }; // х Х һ Һ ҳ Ҳ ӽ Ӽ key { [Cyrillic_hardsign,Cyrillic_HARDSIGN, Ukrainian_yi, Ukrainian_YI, Macedonia_dse, Macedonia_DSE, U033E, U2E2F ] }; // ъ Ъ ї Ї ѕ Ѕ, Combining Yerok, Yerok key { [ Cyrillic_ef, Cyrillic_EF, U0473, U0472, U04C4, U04C3, U04FB, U04FA ] }; // ф Ф ѳ Ѳ ӄ Ӄ ӻ Ӻ key { [ Cyrillic_yeru, Cyrillic_YERU, Ukrainian_i, Ukrainian_I, U04D5, U04D4, U04A9, U04A8 ] }; // ы Ы і І ӕ Ӕ ҩ Ҩ key { [ Cyrillic_ve, Cyrillic_VE, U051D, U051C, U0529, U0528, U0527, U0526 ] }; // в В ԝ Ԝ ԩ Ԩ ԧ Ԧ key { [ Cyrillic_a, Cyrillic_A, Cyrillic_schwa, Cyrillic_SCHWA, UA657, UA656, UA655, UA654 ] }; // а А ә Ә ꙗ Ꙗ ꙕ Ꙕ key { [ Cyrillic_pe, Cyrillic_PE, U0525, U0524, U0471, U0470, UA65F, UA65E ] }; // п П ԥ Ԥ ѱ Ѱ ꙟ Ꙟ key { [ Cyrillic_er, Cyrillic_ER, U0481, U0480, U048F, U048E, U0521, U0520 ] }; // р Р ҁ Ҁ ҏ Ҏ ԡ Ԡ key { [ Cyrillic_o, Cyrillic_O, Cyrillic_o_bar, Cyrillic_O_bar, U047B, U047A, U0461, U0460 ] }; // о О ө Ө ѻ Ѻ ѡ Ѡ key { [ Cyrillic_el, Cyrillic_EL, Cyrillic_lje, Cyrillic_LJE, U04C6, U04C5, U052F, U052E ] }; // л Л љ Љ ӆ Ӆ ԯ Ԯ key { [ Cyrillic_de, Cyrillic_DE, Cyrillic_dzhe, Cyrillic_DZHE, U04BD, U04BC, U04BF, U04BE ] }; // д Д џ Џ ҽ Ҽ ҿ Ҿ key { [ Cyrillic_zhe, Cyrillic_ZHE, Serbian_dje, Serbian_DJE, Cyrillic_zhe_descender, Cyrillic_ZHE_descender, U04C2, U04C1 ] }; // ж Ж ђ Ђ Җ җ ӂ Ӂ key { [ Cyrillic_e, Cyrillic_E, Ukrainian_ie, Ukrainian_IE, U0465, U0464, U04CA, U04C9 ] }; // э Э є Є ѥ Ѥ ӊ Ӊ key { [ slash, bar, backslash, U260E, UA65B, UA65A, U0513, U0512 ] }; // / | \ ☎ ꙛ Ꙛ ԓ Ԓ key { [ U0495, U0494, U0501, U0500, U0503, U0502, U0509, U0508 ] }; // ҕ Ҕ ԁ Ԁ ԃ Ԃ ԉ Ԉ key { [ Cyrillic_ya, Cyrillic_YA, U0469, U0468, U0467, U0466, UA657, UA656 ] }; // я Я ѩ Ѩ ѧ Ѧ ꙗ Ꙗ key { [ Cyrillic_che, Cyrillic_CHE, Serbian_tshe, Serbian_TSHE, Cyrillic_che_descender, Cyrillic_CHE_descender, U2016, U00A6 ] }; // ч Ч ћ Ћ ҷ Ҷ ‖ ¦ key { [ Cyrillic_es, Cyrillic_ES, U046D, U046C, U046B, U046A, U04F7, U04F6 ] }; // с С ѭ Ѭ ѫ Ѫ ӷ Ӷ key { [ Cyrillic_em, Cyrillic_EM, multiply, division, U22C5, U2219, U04CE, U04CD ] }; // м М × ÷ ⋅ ∙ ӎ Ӎ key { [ Cyrillic_i, Cyrillic_I, U0475, U0474, U048B, U048A, periodcentered, U261B ] }; // и И ѵ Ѵ ҋ Ҋ · ☛ key { [ Cyrillic_te, Cyrillic_TE, U04AD, U04AC, U051F, U051E, Cyrillic_che_vertstroke, Cyrillic_CHE_vertstroke ] }; // т Т ҭ Ҭ ԟ Ԟ ҹ Ҹ key { [Cyrillic_softsign,Cyrillic_SOFTSIGN, U04A5, U04A4, UA64F, UA64E, U048D, U048C ] }; // ь Ь ҥ Ҥ ꙏ Ꙏ ҍ Ҍ key { [ Cyrillic_be, Cyrillic_BE, guillemotleft, doublelowquotemark, singlelowquotemark, U2039, U0523, U0522 ] }; // б Б « „ ‚ ‹ ԣ Ԣ key { [ Cyrillic_yu, Cyrillic_YU, guillemotright, leftdoublequotemark, leftsinglequotemark, U203A, rightdoublequotemark, rightsinglequotemark]}; // ю Ю » “ ‘ › ” ’ key { [ period, comma, ellipsis, enfilledcircbullet, U04CC, U04CB, UA649, UA648 ] }; // . , … • ӌ Ӌ ꙉ Ꙉ // eng: Maps Right Alt for reaching the third level // rus: Составляетъ правую Alt для достиженія третьяго уровня // srp: Саставља десни Alt за достизање трећег ступња include "level3(ralt_switch)" // eng: Maps for reaching the fifth level // rus: Составляетъ для достиженія пятаго уровня // srp: Саставља за достизање петег ступња include "level5(caps_switch)" // eng: Offers pressing both shift keys for capslock // rus: Предоставляетъ нажатие обѣихъ клавишъ Shift для защелкиванія прописности буквъ // srp: Ставља на располагање притискивање обију тастера Shift за учвршћивање верзала include "shift(both_shiftlock)" // eng: Makes return comma instead of dot, as the comma is decimal separator in Cyrillic written languages // rus: Дѣлаетъ что отдаетъ запятую вмѣсто точки, такъ какъ запятая десятичный раздѣлитель въ языкахъ пишемыхъ кириллицей // srp: Ради да враћа зарез уместо точке, будући да зарез је десетни разделитељ у језицима који се пишу ћирилицом include "kpdl(comma)" // eng: Bug notice: One has to set lv5:rwin_switch_lock or one of the other level 5 locks for the caps switch to work! // rus: Приходится ставить lv5:rwin_switch_lock либо одинъ изъ другихъ затворовъ пятаго уровня, чтобы работалъ переключатель Caps! // srp: Потребно да се ставља lv5:rwin_switch_lock или једна из других брава петег ступња, да би шљакао пребацивач Caps! // https://bugs.freedesktop.org/show_bug.cgi?id=102189 }; partial alphanumeric_keys xkb_symbols "unipunct" { // Раскладка представляет собой обычную русскую раскладку, в которой некоторые редко используемые буквы // убрали на третий уровень, и поставили все пунктуационные знаки на то же место, где они стоят на // US раскладке (+ добавлен знак номера, который отсутствует в US раскладке, но часто нужен в RU). // ru(unipunct): // `~ 1! 2@ 3#3№ 4$ 5% 6^ 7& 8* 9( 0) -_ =+ // хХ бБ уУюЮ кК еЕэЭ нН гГ шШщЩ жЖ зЗ [{ ]} \| // фФ ыЫ вВ аА пП рР оОёЁ лЛ дД ;: '" //" // яЯ чЧцЦ сС мМ иИйЙ тТ ьЬъЪ ,< .> /? include "us(basic)" name[Group1]= "Russian (with US punctuation)"; // Единственный символ, который отсутствует на US раскладке - № key { [ 3, numbersign, 3, numerosign ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_u, Cyrillic_U, Cyrillic_yu, Cyrillic_YU ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [ Cyrillic_ie, Cyrillic_IE, Cyrillic_e, Cyrillic_E ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_ghe, Cyrillic_GHE ] }; key { [ Cyrillic_sha, Cyrillic_SHA, Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_ze, Cyrillic_ZE ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_o, Cyrillic_O, Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_ya, Cyrillic_YA ] }; key { [ Cyrillic_che, Cyrillic_CHE, Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_es, Cyrillic_ES ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ Cyrillic_i, Cyrillic_I, Cyrillic_shorti, Cyrillic_SHORTI ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN, Cyrillic_hardsign, Cyrillic_HARDSIGN ] }; }; partial alphanumeric_keys xkb_symbols "phonetic_mac" { include "ru(phonetic_winkeys)" name[Group1]= "Russian (phonetic Macintosh)"; key { [ Cyrillic_ie, Cyrillic_IE, Cyrillic_io, Cyrillic_IO ] }; key { [ Cyrillic_sha, Cyrillic_SHA ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA ] }; key { [ Cyrillic_yu, Cyrillic_YU ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ 3, numbersign, numerosign ] }; key { [ 4, dollar, U20BD ] }; // ruble key { [ 5, percent ] }; key { [ 6, caret ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN, minus, underscore ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, equal, plus ] }; include "level3(ralt_switch)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/rupeesign000066400000000000000000000002031510033435100241620ustar00rootroot00000000000000// keyboards having the RupeeSign on the 4 key partial xkb_symbols "4" { key { [ NoSymbol, NoSymbol, U20B9 ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/shift000066400000000000000000000043041510033435100233040ustar00rootroot00000000000000// Cancel CapsLock when a Shift key is pressed. partial modifier_keys xkb_symbols "breaks_caps" { key { type = "ALPHABETIC", [Shift_L, Shift_L], [ SetMods(modifiers=Shift), SetMods(modifiers=Shift+Lock,clearLocks) ] }; key { type = "ALPHABETIC", [Shift_R, Shift_R], [ SetMods(modifiers=Shift), SetMods(modifiers=Shift+Lock,clearLocks) ] }; }; // Toggle CapsLock when pressed together with the other Shift key. partial modifier_keys xkb_symbols "lshift_both_capslock" { key { type[Group1]="TWO_LEVEL", symbols[Group1] = [ Shift_L, Caps_Lock ] }; }; // Toggle CapsLock when pressed together with the other Shift key. partial modifier_keys xkb_symbols "rshift_both_capslock" { key { type[Group1]="TWO_LEVEL", symbols[Group1] = [ Shift_R, Caps_Lock ] }; }; partial modifier_keys xkb_symbols "both_capslock" { include "shift(lshift_both_capslock)" include "shift(rshift_both_capslock)" }; // Set CapsLock when pressed with the other Shift key, release it when pressed alone. partial modifier_keys xkb_symbols "lshift_both_capslock_cancel" { key { type[Group1]="ALPHABETIC", symbols[Group1] = [ Shift_L, Caps_Lock ] }; }; // Set CapsLock when pressed with the other Shift key, release it when pressed alone. partial modifier_keys xkb_symbols "rshift_both_capslock_cancel" { key { type[Group1]="ALPHABETIC", symbols[Group1] = [ Shift_R, Caps_Lock ] }; }; partial modifier_keys xkb_symbols "both_capslock_cancel" { include "shift(lshift_both_capslock_cancel)" include "shift(rshift_both_capslock_cancel)" }; // Toggle ShiftLock when pressed together with the other Shift key. partial modifier_keys xkb_symbols "lshift_both_shiftlock" { key { type[Group1]="TWO_LEVEL", symbols[Group1] = [ Shift_L, Shift_Lock ] }; }; // Toggle ShiftLock when pressed together with the other Shift key. partial modifier_keys xkb_symbols "rshift_both_shiftlock" { key { type[Group1]="TWO_LEVEL", symbols[Group1] = [ Shift_R, Shift_Lock ] }; }; partial modifier_keys xkb_symbols "both_shiftlock" { include "shift(lshift_both_shiftlock)" include "shift(rshift_both_shiftlock)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/shift-v2000066400000000000000000000005531510033435100236330ustar00rootroot00000000000000xkb_symbols "breaks_caps" { key { type = "ALPHABETIC", [Shift_L, Shift_L], [ SetMods(modifiers=Shift), SetMods(modifiers=Shift+Lock,clearLocks,unlockOnPress) ] }; key { type = "ALPHABETIC", [Shift_R, Shift_R], [ SetMods(modifiers=Shift), SetMods(modifiers=Shift+Lock,clearLocks,unlockOnPress) ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/simultaneous-mods-latches000066400000000000000000000011721510033435100273000ustar00rootroot00000000000000default partial alphanumeric_keys xkb_symbols "base" { name[Group1] = "Test issue #583"; key { [ z, Z, y, Y, ezh, EZH, ydiaeresis, Ydiaeresis ], type[Group1] = "EIGHT_LEVEL" }; key { [ x, X ], type[Group1] = "PC_CONTROL_LEVEL2" }; key { [ ISO_Level3_Latch, ISO_Level5_Latch ], type[Group1] = "PC_CONTROL_LEVEL2" }; key { [ Control_R ], [LatchMods(modifiers=Control)] }; key { [ ISO_Level3_Latch ], type[Group1] = "ONE_LEVEL" }; key { [ ISO_Level5_Latch ], type[Group1] = "ONE_LEVEL" }; modifier_map None { }; modifier_map Mod3 { }; modifier_map Mod5 { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/srvr_ctrl000066400000000000000000000044331510033435100242120ustar00rootroot00000000000000// Actions which control the server's behavior. partial keypad_keys function_keys xkb_symbols "xfree86" { include "keypad(operators)" include "srvr_ctrl(fkey2vt)" }; partial function_keys xkb_symbols "fkey2vt" { key { type="CTRL+ALT", symbols[Group1]= [ F1, F1, F1, F1, XF86_Switch_VT_1 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F2, F2, F2, F2, XF86_Switch_VT_2 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F3, F3, F3, F3, XF86_Switch_VT_3 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F4, F4, F4, F4, XF86_Switch_VT_4 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F5, F5, F5, F5, XF86_Switch_VT_5 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F6, F6, F6, F6, XF86_Switch_VT_6 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F7, F7, F7, F7, XF86_Switch_VT_7 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F8, F8, F8, F8, XF86_Switch_VT_8 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F9, F9, F9, F9, XF86_Switch_VT_9 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F10, F10, F10, F10, XF86_Switch_VT_10 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F11, F11, F11, F11, XF86_Switch_VT_11 ] }; key { type="CTRL+ALT", symbols[Group1]= [ F12, F12, F12, F12, XF86_Switch_VT_12 ] }; }; partial function_keys keypad_keys xkb_symbols "no_srvr_keys" { key.type="TWO_LEVEL"; key { [ F1, F1 ] }; key { [ F2, F2 ] }; key { [ F3, F3 ] }; key { [ F4, F4 ] }; key { [ F5, F5 ] }; key { [ F6, F6 ] }; key { [ F7, F7 ] }; key { [ F8, F8 ] }; key { [ F9, F9 ] }; key { [ F10, F10 ] }; key { [ F11, F11 ] }; key { [ F12, F12 ] }; key { [ KP_Divide, KP_Divide ] }; key { [ KP_Multiply, KP_Multiply ] }; key { [ KP_Subtract, KP_Subtract ] }; key { [ KP_Add, KP_Add ] }; }; partial function_keys xkb_symbols "grab_debug" { key { type="CTRL+ALT", symbols[Group1]= [ F11, F11, F11, F11, XF86LogGrabInfo ] }; key { type="CTRL+ALT", symbols[Group1]= [ F12, F12, F12, F12, XF86LogWindowTree ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/terminate000066400000000000000000000003071510033435100241560ustar00rootroot00000000000000default partial modifier_keys xkb_symbols "ctrl_alt_bksp" { key { type="CTRL+ALT", symbols[Group1] = [ NoSymbol, NoSymbol, NoSymbol, NoSymbol, Terminate_Server ] }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/symbols/us000066400000000000000000002666711510033435100226370ustar00rootroot00000000000000default partial alphanumeric_keys modifier_keys xkb_symbols "basic" { name[Group1]= "English (US)"; key { [ grave, asciitilde ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ 5, percent ] }; key { [ { H, E, L, L, O }, asciicircum ] }; key { [ { Y, E, S, space, T, H, I, S, space, I, S, space, D, O, G }, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E ] }; key { [ r, R ] }; key { [ t, T ] }; key { [ y, Y ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ o, O ] }; key { [ p, P ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ a, A ] }; key { [ s, S ] }; key { [ d, D ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ h, H ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ l, L ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ z, Z ] }; key { [ x, X ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ b, B ] }; key { [ n, N ] }; key { [ m, M ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ slash, question ] }; key { [ backslash, bar ] }; }; partial alphanumeric_keys xkb_symbols "euro" { include "us(basic)" name[Group1]= "English (US, euro on 5)"; include "eurosign(5)" include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "ibm238l" { include "us(basic)" name[Group1]= "English (US, IBM Arabic 238_L)"; key { [ comma, comma ] }; key { [ period, period ] }; key { [ quoteleft, asciitilde ] }; key { [ backslash, bar ] }; key { [ leftcaret, rightcaret ] }; }; partial alphanumeric_keys xkb_symbols "intl" { include "us(basic)" name[Group1]= "English (US, intl., with dead keys)"; key { [dead_grave, dead_tilde, grave, asciitilde ] }; key { [ 1, exclam, exclamdown, onesuperior ] }; key { [ 2, at, twosuperior, dead_doubleacute ] }; key { [ 3, numbersign, threesuperior, dead_macron ] }; key { [ 4, dollar, currency, sterling ] }; key { [ 5, percent, EuroSign, dead_cedilla ] }; key { [ 6, dead_circumflex, onequarter, asciicircum ] }; key { [ 7, ampersand, onehalf, dead_horn ] }; key { [ 8, asterisk, threequarters, dead_ogonek ] }; key { [ 9, parenleft, leftsinglequotemark, dead_breve ] }; key { [ 0, parenright, rightsinglequotemark, dead_abovering ] }; key { [ minus, underscore, yen, dead_belowdot ] }; key { [ equal, plus, multiply, division ] }; key { [ q, Q, adiaeresis, Adiaeresis ] }; key { [ w, W, aring, Aring ] }; key { [ e, E, eacute, Eacute ] }; key { [ r, R, registered, registered ] }; key { [ t, T, thorn, THORN ] }; key { [ y, Y, udiaeresis, Udiaeresis ] }; key { [ u, U, uacute, Uacute ] }; key { [ i, I, iacute, Iacute ] }; key { [ o, O, oacute, Oacute ] }; key { [ p, P, odiaeresis, Odiaeresis ] }; key { [ bracketleft, braceleft, guillemotleft, leftdoublequotemark ] }; key { [bracketright, braceright, guillemotright, rightdoublequotemark ] }; key { [ a, A, aacute, Aacute ] }; key { [ s, S, ssharp, section ] }; key { [ d, D, eth, ETH ] }; key { [ f, F, f, F ] }; key { [ g, G, g, G ] }; key { [ h, H, h, H ] }; key { [ j, J, j, J ] }; key { [ k, K, oe, OE ] }; key { [ l, L, oslash, Ooblique ] }; key { [ semicolon, colon, paragraph, degree ] }; key { [dead_acute, dead_diaeresis, apostrophe, quotedbl ] }; key { [ z, Z, ae, AE ] }; key { [ x, X, x, X ] }; key { [ c, C, copyright, cent ] }; key { [ v, V, v, V ] }; key { [ b, B, b, B ] }; key { [ n, N, ntilde, Ntilde ] }; key { [ m, M, mu, mu ] }; key { [ comma, less, ccedilla, Ccedilla ] }; key { [ period, greater, dead_abovedot, dead_caron ] }; key { [ slash, question, questiondown, dead_hook ] }; key { [ backslash, bar, notsign, brokenbar ] }; key { [ backslash, bar, backslash, bar ] }; include "level3(ralt_switch)" }; // Based on symbols/us_intl keyboard map: // Dead-keys definition for a very simple US/ASCII layout. // by Conectiva (http://www.conectiva.com.br) // modified by Ricardo Y. Igarashi (iga@that.com.br) // Added the following deadkeys, to make it truly international: // // dead_macron: on AltGr-minus // dead_breve: on AltGr-parenleft // dead_abovedot: on AltGr-period // dead_abovering: on AltGr-0 // dead_doubleacute: on AltGr-equal (as quotedbl is already used) // dead_caron: on AltGr-less (AltGr-shift-comma) // dead_cedilla: on AltGr-comma // dead_ogonek: on AltGr-semicolon // dead_belowdot: on AltGr-underscore (AltGr-shift-minus) // dead_hook: on AltGr-question // dead_horn: on AltGr-plus (AltGr-shift-equal) // dead_diaeresis: on AltGr-colon (Alt-shift-semicolon) // // those were already there: // dead_grave // dead_acute // dead_circumflex // dead_tilde // dead_diaeresis partial alphanumeric_keys xkb_symbols "alt-intl" { include "us" name[Group1]= "English (US, alt. intl.)"; key { [ dead_grave, dead_tilde, grave, asciitilde ] }; key { [ 5, percent, EuroSign ] }; key { [ 6, dead_circumflex, asciicircum, asciicircum ] }; key { [ 9, parenleft, leftsinglequotemark, dead_breve ] }; key { [ 0, parenright, rightsinglequotemark, dead_abovering ] }; key { [ minus, underscore, dead_macron, dead_belowdot ] }; key { [ equal, plus, dead_doubleacute, dead_horn ] }; key { [ e, E, EuroSign, cent ] }; key { [ semicolon, colon, dead_ogonek, dead_diaeresis ] }; key { [ dead_acute, dead_diaeresis, apostrophe, quotedbl ] }; key { [ comma, less, dead_cedilla, dead_caron ] }; key { [ period, greater, dead_abovedot, dead_circumflex ] }; key { [ slash, question, dead_hook, dead_hook ] }; key { [ backslash, bar, backslash, bar ] }; include "level3(ralt_switch)" }; // based on a keyboard map from an 'xkb/symbols/dk' file partial alphanumeric_keys xkb_symbols "dvorak" { name[Group1]= "English (Dvorak)"; key { [ grave, asciitilde, dead_grave, dead_tilde ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ 5, percent ] }; key { [ 6, asciicircum, dead_circumflex, dead_circumflex ] }; key { [ 7, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft, dead_grave] }; key { [ 0, parenright ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright, dead_tilde] }; key { [ apostrophe, quotedbl, dead_acute, dead_diaeresis ] }; key { [ comma, less, dead_cedilla, dead_caron ] }; key { [ period, greater, dead_abovedot, periodcentered ] }; key { [ p, P ] }; key { [ y, Y ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ c, C ] }; key { [ r, R ] }; key { [ l, L ] }; key { [ slash, question ] }; key { [ equal, plus ] }; key { [ a, A ] }; key { [ o, O ] }; key { [ e, E ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ d, D ] }; key { [ h, H ] }; key { [ t, T ] }; key { [ n, N ] }; key { [ s, S ] }; key { [ minus, underscore ] }; key { [ semicolon, colon, dead_ogonek, dead_doubleacute ] }; key { [ q, Q ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ x, X ] }; key { [ b, B ] }; key { [ m, M ] }; key { [ w, W ] }; key { [ v, V ] }; key { [ z, Z ] }; key { [ backslash, bar ] }; }; // Dvorak intl., with dead keys // Olivier Mehani (shtrom-xorg@ssji.net) // Reproduce the per-key mapping of us(intl) for the dvorak layout // aka "I just swapped my keys over" partial alphanumeric_keys xkb_symbols "dvorak-intl" { include "us(dvorak)" name[Group1]= "English (Dvorak, intl., with dead keys)"; key { [dead_grave, dead_tilde, grave, asciitilde ] }; key { [ 1, exclam, exclamdown, onesuperior ] }; key { [ 2, at, twosuperior, dead_doubleacute ] }; key { [ 3, numbersign, threesuperior, dead_macron ] }; key { [ 4, dollar, currency, sterling ] }; key { [ 5, percent, EuroSign, dead_cedilla ] }; key { [ 6, dead_circumflex, onequarter, asciicircum ] }; key { [ 7, ampersand, onehalf, dead_horn ] }; key { [ 8, asterisk, threequarters, dead_ogonek ] }; key { [ 9, parenleft, leftsinglequotemark, dead_breve ] }; key { [ 0, parenright, rightsinglequotemark, dead_abovering ] }; key { [ bracketleft, braceleft, guillemotleft, leftdoublequotemark ] }; key { [bracketright, braceright, guillemotright, rightdoublequotemark ] }; key { [dead_acute, dead_diaeresis, apostrophe, quotedbl ] }; key { [ comma, less, ccedilla, Ccedilla ] }; key { [ period, greater, dead_abovedot, dead_caron ] }; key { [ p, P, odiaeresis, Odiaeresis ] }; key { [ y, Y, udiaeresis, Udiaeresis ] }; // key { [ f, F ] }; // key { [ g, G ] }; key { [ c, C, copyright, cent ] }; key { [ r, R, registered, registered ] }; key { [ l, L, oslash, Ooblique ] }; key { [ slash, question, questiondown, dead_hook ] }; // key { [ equal, plus, multiply, division ] }; key { [ a, A, aacute, Aacute ] }; key { [ o, O, oacute, Oacute ] }; key { [ e, E, eacute, Eacute ] }; key { [ u, U, uacute, Uacute ] }; key { [ i, I, iacute, Iacute ] }; key { [ d, D, eth, ETH ] }; // key { [ h, H ] }; key { [ t, T, thorn, THORN ] }; key { [ n, N, ntilde, Ntilde ] }; key { [ s, S, ssharp, section ] }; // key { [ minus, underscore, yen, dead_belowdot ] }; key { [ semicolon, colon, paragraph, degree ] }; key { [ q, Q, adiaeresis, Adiaeresis ] }; // key { [ j, J ] }; key { [ k, K, oe, OE ] }; // key { [ x, X ] }; // key { [ b, B ] }; key { [ m, M, mu, mu ] }; key { [ w, W, aring, Aring ] }; // key { [ v, V ] }; key { [ z, Z, ae, AE ] }; key { [ backslash, bar, notsign, brokenbar ] }; include "level3(ralt_switch)" }; // Dvorak international without dead keys // Stephane Magnenat (stephane at magnenat dot net, http://stephane.magnenat.net) // Based on information from http://www.poupinou.org/dvorak/index.html // // ` 1 2 3 4 5 6 7 8 9 0 [ ] \ // € // // ' , . p y f g c r l / = // ä ê ë ü ç // // a o e u i d h t n s - // à ô é û î ß // // ; q j k x b m w v z // â ö è ù ï partial alphanumeric_keys xkb_symbols "dvorak-alt-intl" { include "us(dvorak)" name[Group1]= "English (Dvorak, alt. intl.)"; key { [ 4, dollar, EuroSign ] }; key { [ comma, less, adiaeresis, dead_caron ] }; key { [ period, greater, ecircumflex, periodcentered ] }; key { [ p, P, ediaeresis, dead_cedilla ] }; key { [ y, Y, udiaeresis ] }; key { [ c, C, ccedilla, dead_abovedot ] }; key { [ a, A, agrave ] }; key { [ o, O, ocircumflex ] }; key { [ e, E, eacute ] }; key { [ u, U, ucircumflex ] }; key { [ i, I, icircumflex ] }; key { [ s, S, ssharp, U1E9E ] }; key { [ semicolon, colon, acircumflex ] }; key { [ q, Q, odiaeresis, dead_ogonek ] }; key { [ j, J, egrave, dead_doubleacute ] }; key { [ k, K, ugrave ] }; key { [ x, X, idiaeresis ] }; include "level3(ralt_switch)" }; // Left and right handed dvorak layouts // by sqweek 2006-01-30 // Based on the corresponding layouts in the console-tools package. partial alphanumeric_keys xkb_symbols "dvorak-l" { include "us(dvorak)" name[Group1]= "English (Dvorak, left-handed)"; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ slash, question ] }; key { [ p, P ] }; key { [ f, F ] }; key { [ m, M ] }; key { [ l, L ] }; key { [ j, J ] }; key { [ 4, dollar ] }; key { [ 3, numbersign ] }; key { [ 2, at ] }; key { [ 1, exclam ] }; key { [ semicolon, colon ] }; key { [ q, Q ] }; key { [ b, B ] }; key { [ y, Y ] }; key { [ u, U ] }; key { [ r, R ] }; key { [ s, S ] }; key { [ o, O ] }; key { [ period, greater ] }; key { [ 6, asciicircum ] }; key { [ 5, percent ] }; key { [ equal, plus ] }; key { [ minus, underscore ] }; key { [ k, K ] }; key { [ c, C ] }; key { [ d, D ] }; key { [ t, T ] }; key { [ h, H ] }; key { [ e, E ] }; key { [ a, A ] }; key { [ z, Z ] }; key { [ 8, asterisk ] }; key { [ 7, ampersand ] }; key { [ apostrophe, quotedbl ] }; key { [ x, X ] }; key { [ g, G ] }; key { [ v, V ] }; key { [ w, W ] }; key { [ n, N ] }; key { [ i, I ] }; key { [ comma, less ] }; key { [ 0, parenright ] }; key { [ 9, parenleft ] }; }; partial alphanumeric_keys xkb_symbols "dvorak-r" { include "us(dvorak)" name[Group1]= "English (Dvorak, right-handed)"; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ j, J ] }; key { [ l, L ] }; key { [ m, M ] }; key { [ f, F ] }; key { [ p, P ] }; key { [ slash, question ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ 5, percent ] }; key { [ 6, asciicircum ] }; key { [ q, Q ] }; key { [ period, greater ] }; key { [ o, O ] }; key { [ r, R ] }; key { [ s, S ] }; key { [ u, U ] }; key { [ y, Y ] }; key { [ b, B ] }; key { [ semicolon, colon ] }; key { [ equal, plus ] }; key { [ 7, ampersand ] }; key { [ 8, asterisk ] }; key { [ z, Z ] }; key { [ a, A ] }; key { [ e, E ] }; key { [ h, H ] }; key { [ t, T ] }; key { [ d, D ] }; key { [ c, C ] }; key { [ k, K ] }; key { [ minus, underscore ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ x, X ] }; key { [ comma, less ] }; key { [ i, I ] }; key { [ n, N ] }; key { [ w, W ] }; key { [ v, V ] }; key { [ g, G ] }; key { [ apostrophe, quotedbl ] }; }; // Classic dvorak layout // by Piter Punk - 2006-07-06 // Based on dvorak layout and e-mail from Russel L. Harris rlharris@oplink.net // on xorg list. partial alphanumeric_keys xkb_symbols "dvorak-classic" { name[Group1]= "English (classic Dvorak)"; key { [ grave, asciitilde, dead_grave, dead_tilde ] }; key { [ bracketleft, braceleft ] }; key { [ 7, ampersand ] }; key { [ 5, percent ] }; key { [ 3, numbersign ] }; key { [ 1, exclam ] }; key { [ 9, parenleft, dead_grave] }; key { [ 0, parenright ] }; key { [ 2, at ] }; key { [ 4, dollar ] }; key { [ 6, asciicircum, dead_circumflex, dead_circumflex ] }; key { [ 8, asterisk ] }; key { [ bracketright, braceright, dead_tilde] }; key { [ slash, question ] }; key { [ comma, less, dead_cedilla, dead_caron ] }; key { [ period, greater, dead_abovedot, periodcentered ] }; key { [ p, P ] }; key { [ y, Y ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ c, C ] }; key { [ r, R ] }; key { [ l, L ] }; key { [ apostrophe, quotedbl, dead_acute, dead_diaeresis ] }; key { [ equal, plus ] }; key { [ a, A ] }; key { [ o, O ] }; key { [ e, E ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ d, D ] }; key { [ h, H ] }; key { [ t, T ] }; key { [ n, N ] }; key { [ s, S ] }; key { [ minus, underscore ] }; key { [ semicolon, colon, dead_ogonek, dead_doubleacute ] }; key { [ q, Q ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ x, X ] }; key { [ b, B ] }; key { [ m, M ] }; key { [ w, W ] }; key { [ v, V ] }; key { [ z, Z ] }; key { [ backslash, bar ] }; }; // programmer Dvorak, by Roland Kaufmann // License: BSD, available at // Main features: Numbers are in shift position (like French), symbols have been // placed in locations that give good hand-alternation and finger rolling with // symbols that usually follows, accented characters are possible for I18N. // Patch suggestions should be sent upstream. partial alphanumeric_keys xkb_symbols "dvp" { include "us(dvorak)" name[Group1] = "English (programmer Dvorak)"; // Unmodified Shift AltGr Shift+AltGr // symbols row, left side key { [ dollar, asciitilde, dead_tilde ] }; key { [ ampersand, percent ] }; key { [ bracketleft, 7, currency ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ braceleft, 5, cent ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ braceright, 3, yen ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ parenleft, 1, EuroSign ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ equal, 9, sterling ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; // symbols row, right side key { [ asterisk, 0 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ parenright, 2, onehalf ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ plus, 4 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ bracketright, 6 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ exclam, 8, exclamdown, U2E18 ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; // reversed interrobang key { [ numbersign, grave, dead_grave ] }; key { [ BackSpace, BackSpace ] }; // upper row, left side key { [ semicolon, colon, dead_diaeresis ] }; key { [ comma, less, guillemotleft, U201C ] }; key { [ period, greater, guillemotright, U201D ] }; key { [ p, P, paragraph, section ] }; key { [ y, Y, udiaeresis, Udiaeresis ] }; // upper row, right side key { [ c, C, ccedilla, Ccedilla ] }; key { [ r, R, registered, trademark ] }; key { [ slash, question, questiondown, U203D ] }; // interrobang key { [ at, asciicircum, dead_circumflex, dead_caron ] }; // home row, left side key { [ a, A, aring, Aring ] }; key { [ o, O, oslash, Ooblique ] }; key { [ e, E, ae, AE ] }; key { [ u, U, eacute, Eacute ] }; // home row, right side key { [ d, D, eth, ETH ] }; key { [ h, H, dead_acute ] }; key { [ t, T, thorn, THORN ] }; key { [ n, N, ntilde, Ntilde ] }; key { [ s, S, ssharp, U1E9E ] }; key { [ minus, underscore, hyphen, endash ], type[Group1] = "FOUR_LEVEL_ALPHABETIC" }; key { [ backslash, bar ] }; // lower row, left side key { [ apostrophe, quotedbl, dead_acute ] }; // do NOT hardcode this switch; use lv3:ralt_switch option instead! //include "level3(ralt_switch)" }; // phonetic layout for Russian letters on an US keyboard // by Ivan Popov 2005-07-17 // level3 modifier is a shortcut to the "us" meaning of the keys where // we place cyrillic letters, handy for accessing the corresponding // punctuation marks. // It is important to have access to punctuation marks, and the rest of // alphabetical keys are added for being consequent so that the users // can expect the level3 modifier to give what the key label shows. partial alphanumeric_keys xkb_symbols "rus" { include "us(basic)" name[Group1]= "Russian (US, phonetic)"; key.type[group1]="FOUR_LEVEL_ALPHABETIC"; key { [ Cyrillic_a, Cyrillic_A ] }; key { [ Cyrillic_be, Cyrillic_BE ] }; key { [ Cyrillic_ve, Cyrillic_VE ] }; key { [ Cyrillic_ghe, Cyrillic_GHE ] }; key { [ Cyrillic_de, Cyrillic_DE ] }; key { [ Cyrillic_ie, Cyrillic_IE ] }; key { [ Cyrillic_io, Cyrillic_IO, grave, asciitilde ] }; key { [ Cyrillic_zhe, Cyrillic_ZHE ] }; key { [ Cyrillic_ze, Cyrillic_ZE ] }; key { [ Cyrillic_i, Cyrillic_I ] }; key { [ Cyrillic_shorti, Cyrillic_SHORTI ] }; key { [ Cyrillic_ka, Cyrillic_KA ] }; key { [ Cyrillic_el, Cyrillic_EL ] }; key { [ Cyrillic_em, Cyrillic_EM ] }; key { [ Cyrillic_en, Cyrillic_EN ] }; key { [ Cyrillic_o, Cyrillic_O ] }; key { [ Cyrillic_pe, Cyrillic_PE ] }; key { [ Cyrillic_er, Cyrillic_ER ] }; key { [ Cyrillic_es, Cyrillic_ES ] }; key { [ Cyrillic_te, Cyrillic_TE ] }; key { [ Cyrillic_u, Cyrillic_U ] }; key { [ Cyrillic_ef, Cyrillic_EF ] }; key { [ Cyrillic_ha, Cyrillic_HA ] }; key { [ Cyrillic_tse, Cyrillic_TSE ] }; key { [ Cyrillic_che, Cyrillic_CHE, semicolon, colon ] }; key { [ Cyrillic_sha, Cyrillic_SHA, bracketleft, braceleft] }; key { [ Cyrillic_shcha, Cyrillic_SHCHA, bracketright, braceright ] }; key { [ Cyrillic_hardsign, Cyrillic_HARDSIGN, equal, plus ] }; key { [ Cyrillic_yeru, Cyrillic_YERU ] }; key { [ Cyrillic_softsign, Cyrillic_SOFTSIGN ] }; key { [ Cyrillic_e, Cyrillic_E, backslash, bar ] }; key { [ Cyrillic_yu, Cyrillic_YU, apostrophe, quotedbl ] }; key { [ Cyrillic_ya, Cyrillic_YA ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "mac" { include "us(basic)" name[Group1]= "English (Macintosh)"; key.type[group1]="FOUR_LEVEL"; // Slightly improvised from http://homepage.mac.com/thgewecke/kblayout.jpg key { [ section, plusminus, section, plusminus ] }; key { [ grave, asciitilde, dead_grave, dead_horn ] }; key { [ 1, exclam, exclamdown, U2044 ] }; key { [ 2, at, trademark, EuroSign ] }; key { [ 3, numbersign, sterling, U2039 ] }; key { [ 4, dollar, cent, U203A ] }; key { [ 5, percent, infinity, UFB01 ] }; key { [ 6,asciicircum, section, UFB02 ] }; key { [ 7, ampersand, paragraph, doubledagger ] }; key { [ 8, asterisk, enfilledcircbullet, degree ] }; key { [ 9, parenleft, ordfeminine, periodcentered ] }; key { [ 0, parenright, masculine,singlelowquotemark] }; key { [ minus, underscore, endash, emdash ] }; key { [ equal, plus, notequal, plusminus ] }; key { [ q, Q, oe, OE ] }; key { [ w, W, U2211,doublelowquotemark] }; key { [ e, E, dead_acute, acute ] }; key { [ r, R, registered, U2030 ] }; key { [ t, T, dagger, dead_caron ] }; key { [ y, Y, yen, onequarter ] }; key { [ u, U, dead_diaeresis, diaeresis ] }; key { [ i, I, dead_circumflex, U02C6 ] }; key { [ o, O, oslash, Ooblique ] }; key { [ p, P, Greek_pi, U220F ] }; key { [ bracketleft, braceleft, leftdoublequotemark, rightdoublequotemark ] }; key { [bracketright, braceright, leftsinglequotemark, rightsinglequotemark ] }; key { [ backslash, bar, guillemotleft, guillemotright ] }; key { [ a, A, aring, Aring ] }; key { [ s, S, ssharp, dead_stroke ] }; key { [ d, D, partialderivative, eth ] }; key { [ f, F, function, dead_hook ] }; key { [ g, G, copyright, dead_doubleacute ] }; key { [ h, H, dead_abovedot, dead_belowdot ] }; key { [ j, J, U2206, onehalf ] }; key { [ k, K,dead_abovering, UF8FF ] }; key { [ l, L, notsign, THORN ] }; key { [ semicolon, colon, U2026, thorn ] }; key { [apostrophe, quotedbl, ae, AE ] }; key { [ z, Z, Greek_OMEGA, dead_cedilla ] }; key { [ x, X, U2248, dead_ogonek ] }; // unclear whether "approxeq" is 2248 or 2245 key { [ c, C, ccedilla, Ccedilla ] }; key { [ v, V, squareroot, U25CA ] }; key { [ b, B, integral, idotless ] }; key { [ n, N, dead_tilde, U02DC ] }; key { [ m, M, mu, threequarters ] }; key { [ comma, less, lessthanequal, dead_macron ] }; key { [ period, greater, greaterthanequal, dead_breve ] }; key { [ slash, question, division, questiondown ] }; include "level3(ralt_switch)" }; // Colemak symbols for xkb on X.Org Server 7.x // 2006-01-01 Shai Coleman, http://colemak.com/ partial alphanumeric_keys xkb_symbols "colemak" { include "us" name[Group1]= "English (Colemak)"; key { [ grave, asciitilde, dead_tilde, asciitilde ] }; key { [ 1, exclam, exclamdown, onesuperior ] }; key { [ 2, at, masculine, twosuperior ] }; key { [ 3, numbersign, ordfeminine, threesuperior ] }; key { [ 4, dollar, cent, sterling ] }; key { [ 5, percent, EuroSign, yen ] }; key { [ 6, asciicircum, hstroke, Hstroke ] }; key { [ 7, ampersand, eth, ETH ] }; key { [ 8, asterisk, thorn, THORN ] }; key { [ 9, parenleft, leftsinglequotemark, leftdoublequotemark ] }; key { [ 0, parenright, rightsinglequotemark, rightdoublequotemark ] }; key { [ minus, underscore, endash, emdash ] }; key { [ equal, plus, multiply, division ] }; key { [ q, Q, adiaeresis, Adiaeresis ] }; key { [ w, W, aring, Aring ] }; key { [ f, F, atilde, Atilde ] }; key { [ p, P, oslash, Ooblique ] }; key { [ g, G, dead_ogonek, asciitilde ] }; key { [ j, J, dstroke, Dstroke ] }; key { [ l, L, lstroke, Lstroke ] }; key { [ u, U, uacute, Uacute ] }; key { [ y, Y, udiaeresis, Udiaeresis ] }; key { [ semicolon, colon, odiaeresis, Odiaeresis ] }; key { [ bracketleft, braceleft, guillemotleft, 0x1002039 ] }; key { [ bracketright, braceright, guillemotright, 0x100203a ] }; key { [ backslash, bar, asciitilde, asciitilde ] }; key { [ a, A, aacute, Aacute ] }; key { [ r, R, dead_grave, asciitilde ] }; key { [ s, S, ssharp, 0x1001e9e ] }; key { [ t, T, dead_acute, dead_doubleacute ] }; key { [ d, D, dead_diaeresis, asciitilde ] }; key { [ h, H, dead_caron, asciitilde ] }; key { [ n, N, ntilde, Ntilde ] }; key { [ e, E, eacute, Eacute ] }; key { [ i, I, iacute, Iacute ] }; key { [ o, O, oacute, Oacute ] }; key { [ apostrophe, quotedbl, otilde, Otilde ] }; key { [ z, Z, ae, AE ] }; key { [ x, X, dead_circumflex, asciitilde ] }; key { [ c, C, ccedilla, Ccedilla ] }; key { [ v, V, oe, OE ] }; key { [ b, B, dead_breve, asciitilde ] }; key { [ k, K, dead_abovering, asciitilde ] }; key { [ m, M, dead_macron, asciitilde ] }; key { [ comma, less, dead_cedilla, asciitilde ] }; key { [ period, greater, dead_abovedot, asciitilde ] }; key { [ slash, question, questiondown, asciitilde ] }; key { [ BackSpace, BackSpace, BackSpace, BackSpace ] }; key { [ minus, underscore, endash, emdash ] }; key { [ space, space, space, nobreakspace ] }; include "level3(ralt_switch)" }; // I do NOT like dead-keys - the International keyboard as defined by Microsoft // does not fit my needs. Why use two keystrokes for all simple characters (eg ' // and generates a single ') just to have an é (eacute) in two strokes // as well? I type ' more often than é (eacute). // // This file works just like a regular keyboard, BUT has all dead-keys // accessible at level3 (through AltGr). An ë (ediaeresis) is now: AltGr+" // followed by an e. In other words, this keyboard is not international as long // as you leave the right Alt key alone. // // The original MS International keyboard was intended for Latin1 (iso8859-1). // With the introduction of iso8859-15, the (important) ligature oe (and OE) // became available. I added them next to ae. Because I write ediaeresis more // often than registered, I moved registered to be next to copyright and added // ediaeresis and idiaeresis. - Adriaan partial alphanumeric_keys xkb_symbols "altgr-intl" { include "us(intl)" name[Group1]= "English (intl., with AltGr dead keys)"; // five dead keys moved into level3: key { [ grave, asciitilde, dead_grave, dead_tilde ] }; key { [apostrophe,quotedbl, dead_acute, dead_diaeresis ] }; // diversions from the MS Intl keyboard: key { [ 1, exclam, onesuperior, exclamdown ] }; key { [ r, R, ediaeresis, Ediaeresis ] }; key { [ j, J, idiaeresis, Idiaeresis ] }; key { [ x, X, oe, OE ] }; key { [ v, V, registered, registered ] }; // onequarter etc (not in iso8859-15) moved to get three unshifted deadkeys: key { [ 6, asciicircum, dead_circumflex, onequarter ] }; key { [ 7, ampersand, dead_horn, onehalf ] }; key { [ 8, asterisk, dead_ogonek, threequarters ] }; include "level3(ralt_switch)" }; // Intel ClassmatePC Keyboard Layout // by Piter PUNK // // The keyboard layouts below maps the us(basic), us(intl) and us(alt-intl) // to ClassmatePC keyboard. All layouts uses RCTL as level3(switch) since // the keyboard does not have AltGr key. The EuroSign is engraved at 5 key. // classmate - us(basic) partial alphanumeric_keys xkb_symbols "classmate" { include "us(basic)" name[Group1]= "English (US)"; key { [ backslash, bar, backslash, bar ] }; include "eurosign(5)" include "level3(switch)" }; // classmate-intl - us(intl) // RCTL is generated by Fn+Alt, because that, when trying to access // the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got // the keypad keycodes. The keypad is changed to make Fn+Alt+ // generate the same symbol as the original key. partial alphanumeric_keys xkb_symbols "classmate-intl" { include "us(intl)" name[Group1]= "USA - ClassmatePC (International)"; key.type[Group1]="FOUR_LEVEL"; key { [ backslash, bar, backslash, bar ] }; key { [ KP_Home, KP_7, onehalf, dead_horn ] }; key { [ KP_Up, KP_8, threequarters, dead_ogonek ] }; key { [ KP_Prior, KP_9, leftsinglequotemark, dead_breve ] }; key { [ KP_Multiply, KP_Multiply, rightsinglequotemark, dead_abovering ] }; key { [ KP_Left, KP_4, uacute, Uacute ] }; key { [ KP_Begin, KP_5, iacute, Iacute ] }; key { [ KP_Right, KP_6, oacute, Oacute ] }; key { [ KP_Subtract, KP_Subtract, odiaeresis, Odiaeresis ] }; key { [ KP_Down, KP_2, oe, OE ] }; key { [ KP_Next, KP_3, oslash, Ooblique ] }; key { [ KP_Add, KP_Add, paragraph, degree ] }; key { [ KP_Insert, KP_0, mu, mu ] }; key { [ KP_Delete, KP_Decimal, dead_abovedot, dead_caron ] }; key { [ KP_Divide, KP_Divide, questiondown, dead_hook ] }; include "level3(switch)" }; // classmate-alt-intl - us(alt-intl) // RCTL is generated by Fn+Alt, because that, when trying to access // the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got // the keypad keycodes. The keypad is changed to make Fn+Alt+ // generate the same symbol as the original key. partial alphanumeric_keys xkb_symbols "classmate-alt-intl" { include "us(alt-intl)" name[Group1]= "USA - ClassmatePC (Alternative international)"; key.type[Group1]="FOUR_LEVEL"; key { [ backslash, bar, backslash, bar ] }; key { [ KP_Subtract, KP_Subtract ] }; key { [ KP_Prior, KP_9, leftsinglequotemark, dead_breve ] }; key { [ KP_Multiply, KP_Multiply, rightsinglequotemark, dead_abovering ] }; key { [ KP_Add, KP_Add, dead_ogonek, dead_diaeresis ] }; key { [ KP_Delete, KP_Decimal, dead_abovedot, dead_circumflex ] }; key { [ KP_Divide, KP_Divide, dead_hook, dead_hook ] }; include "level3(switch)" }; // classmate-altgr-intl - us(altgr-intl) // RCTL is generated by Fn+Alt, because that, when trying to access // the level3 symbols at 7,8,9,0,u,i,o,p,j,k,l,;,m,. and / we got // the keypad keycodes. The keypad is changed to make Fn+Alt+ // generate the same symbol as the original key. partial alphanumeric_keys xkb_symbols "classmate-altgr-intl" { include "us(altgr-intl)" name[Group1]= "USA - ClassmatePC (International Fn+Alt dead-keys)"; key.type[Group1]="FOUR_LEVEL"; key { [ backslash, bar, backslash, bar ] }; key { [ KP_Home, KP_7, dead_horn, dead_horn ] }; key { [ KP_Up, KP_8, dead_ogonek, dead_ogonek ] }; key { [ KP_Prior, KP_9, leftsinglequotemark, dead_breve ] }; key { [ KP_Multiply, KP_Multiply, rightsinglequotemark, dead_abovering ] }; key { [ KP_Left, KP_4, uacute, Uacute ] }; key { [ KP_Begin, KP_5, iacute, Iacute ] }; key { [ KP_Right, KP_6, oacute, Oacute ] }; key { [ KP_Subtract, KP_Subtract, odiaeresis, Odiaeresis ] }; key { [ KP_End, KP_1, idiaeresis, Idiaeresis ] }; key { [ KP_Down, KP_2, oe, OE ] }; key { [ KP_Next, KP_3, oslash, Ooblique ] }; key { [ KP_Add, KP_Add, paragraph, degree ] }; key { [ KP_Insert, KP_0, mu, mu ] }; key { [ KP_Delete, KP_Decimal, dead_abovedot, dead_caron ] }; key { [ KP_Divide, KP_Divide, questiondown, dead_hook ] }; include "level3(switch)" }; partial alphanumeric_keys xkb_symbols "olpc" { include "us(basic)" name[Group1]= "English (US)"; // OLPC international US English keyboard layout. // It's a little different from the usual international layout. // See: http://wiki.laptop.org/go/Image:Keyboard_english.png key { [ grave, asciitilde, dead_grave, dead_tilde ] }; key { [ 1, exclam, exclamdown, exclamdown ] }; key { [ 2, at, notsign, notsign ] }; key { [ 3, numbersign, 0x1000300, 0x1000300 ] }; // combining grave key { [ 4, dollar, 0x1000301, 0x1000301 ] }; // combining acute key { [ 5, percent, 0x1000306, 0x1000306 ] }; // combining breve above key { [ 6,asciicircum, 0x100030A, 0x100030A ] }; // combining ring above key { [ 7, ampersand, 0x1000302, 0x1000302 ] }; // combining circumflex above key { [ 8, asterisk, 0x100030C, 0x100030C ] }; // combining caron above key { [ 9, parenleft, 0x1000307, 0x1000307 ] }; // combining dot above key { [ 0, parenright, 0x1000308, 0x1000308 ] }; // combining diaeresis above key { [ minus, underscore, 0x1000304, 0x1000304 ] }; // combining macron above key { [ equal, plus, 0x1000303, 0x1000303 ] }; // combining tilde above key { [ q, Q, Greek_omega, Greek_OMEGA ] }; key { [ w, W, oslash, Oslash ] }; key { [ e, E, oe, OE ] }; key { [ r, R, 0x1000327, 0x1000327 ] }; // combining cedilla key { [ t, T, 0x100032E, 0x100032E ] }; // combining breve below key { [ y, Y, 0x1000325, 0x1000325 ] }; // combining ring below key { [ u, U, 0x100032D, 0x100032D ] }; // combining circumflex below key { [ i, I, 0x100032C, 0x100032C ] }; // combining caron below key { [ o, O, 0x1000323, 0x1000323 ] }; // combining dot below key { [ p, P, 0x1000324, 0x1000324 ] }; // combining diaeresis below key { [ bracketleft, braceleft, 0x1000331, 0x1000331 ] }; // combining macron below key { [bracketright, braceright, 0x1000330, 0x1000330 ] }; // combining tilde below key { [ a, A, ae, AE ] }; key { [ s, S, ssharp, 0x1001E9E ] }; // uppercase S sharp key { [ d, D, eth, ETH ] }; key { [ f, F, thorn, THORN ] }; key { [ h, H, sterling, sterling ] }; key { [ j, J, EuroSign, EuroSign ] }; key { [ semicolon, colon, masculine, ordfeminine ] }; key { [ apostrophe, quotedbl, currency, currency ] }; key { [ backslash, bar, section, section ] }; key { [ c, C, ccedilla, Ccedilla ] }; key { [ n, N, ntilde, Ntilde ] }; key { [ m, M, mu, mu ] }; key { [ comma, less, guillemotleft, guillemotleft ] }; key { [ period, greater, guillemotright, guillemotright ] }; key { [ slash, question, questiondown, questiondown ] }; key { [ multiply, division, ISO_Next_Group, ISO_Prev_Group ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "olpc2" { include "us(olpc)" name[Group1]= "English (the divide/multiply toggle the layout)"; include "group(olpc)" }; xkb_symbols "olpcm" { include "us(basic)" name[Group1]= "English (US)"; // Mechanical (non-membrane) OLPC int'l US English keyboard layout. // See: http://wiki.laptop.org/go/OLPC_English_Non-membrane_Keyboard key { [ grave, asciitilde, dead_grave, dead_tilde ] }; key { [ 1, exclam, exclamdown, exclamdown ] }; key { [ 2, at, notsign, notsign ] }; key { [ 3, numbersign, 0x1000300, 0x1000300 ] }; // combining grave key { [ 4, dollar, 0x1000301, 0x1000301 ] }; // combining acute key { [ 5, percent, 0x1000306, 0x1000306 ] }; // combining breve above key { [ 6,asciicircum, 0x100030A, 0x100030A ] }; // combining ring above key { [ 7, ampersand, 0x1000302, 0x1000302 ] }; // combining circumflex above key { [ 8, asterisk, 0x100030C, 0x100030C ] }; // combining caron above key { [ 9, parenleft, 0x1000307, 0x1000307 ] }; // combining dot above key { [ 0, parenright, 0x1000308, 0x1000308 ] }; // combining diaeresis above key { [ minus, underscore, 0x1000304, 0x1000304 ] }; // combining macron above key { [ q, Q, Greek_omega, Greek_OMEGA ] }; key { [ w, W, oslash, Oslash ] }; key { [ e, E, oe, OE ] }; key { [ r, R, 0x1000327, 0x1000327 ] }; // combining cedilla key { [ t, T, 0x100032E, 0x100032E ] }; // combining breve below key { [ y, Y, 0x1000325, 0x1000325 ] }; // combining ring below key { [ u, U, 0x100032D, 0x100032D ] }; // combining circumflex below key { [ i, I, 0x100032C, 0x100032C ] }; // combining caron below key { [ o, O, 0x1000323, 0x1000323 ] }; // combining dot below key { [ p, P, 0x1000324, 0x1000324 ] }; // combining diaeresis below key { [ bracketleft, braceleft, 0x1000331, 0x1000331 ] }; // combining macron below key { [bracketright, braceright, 0x1000330, 0x1000330 ] }; // combining tilde below key { [ a, A, ae, AE ] }; key { [ s, S, ssharp, 0x1001E9E ] }; // uppercase S sharp key { [ d, D, eth, ETH ] }; key { [ f, F, thorn, THORN ] }; key { [ h, H, sterling, sterling ] }; key { [ j, J, EuroSign, EuroSign ] }; key { [ semicolon, colon, masculine, ordfeminine ] }; // no AC11 or AC12 on olpcm key { [ c, C, ccedilla, Ccedilla ] }; key { [ n, N, ntilde, Ntilde ] }; key { [ m, M, mu, mu ] }; key { [ comma, less, guillemotleft, guillemotleft ] }; key { [ period, greater, guillemotright, guillemotright ] }; key { [ slash, question, questiondown, questiondown ] }; key { [ backslash, bar, section, section ] }; key { [ equal, plus, 0x1000303, 0x1000303 ] }; key { [ apostrophe, quotedbl, currency, currency ] }; include "level3(ralt_switch)" }; // Based on Cherokee Nation Official Layout // http://www.cherokee.org/extras/downloads/font/Keyboard.htm partial alphanumeric_keys modifier_keys xkb_symbols "chr" { name[Group1]= "Cherokee"; key.type[group1]="ALPHABETIC"; key { [ grave, U13CA ] }; key { [ 1, U13B1 ] }; key { [ 2, U13C7 ] }; key { [ 3, U13E7 ] }; key { [ U13D9, U13B0 ] }; key { [ U13E6, U13B9 ] }; key { [ U13DC, U13DD ] }; key { [ U13CB, U13E1 ] }; key { [ U13D6, U13BA ] }; key { [ U13D2, parenleft ] }; key { [ U13C4, parenright ] }; key { [ U13BF, U13BC ] }; key { [ U13F3, U13BD ] }; key { [ U13AA, U13C6 ] }; key { [ U13B3, U13EB ] }; key { [ U13A1, U13E3 ] }; key { [ U13DB, U13CF ] }; key { [ U13D4, U13D8 ] }; key { [ U13EF, U13F2 ] }; key { [ U13A4, U13AD ] }; key { [ U13A2, U13F1 ] }; key { [ U13A3, U13EC ] }; key { [ U13C1, U13EA ] }; key { [ U13D5, U13D1 ] }; key { [ U13B6, U13E4 ] }; key { [ U13E9, U13EE ] }; key { [ U13A0, U13CC ] }; key { [ U13CD, U13CE ] }; key { [ U13D7, U13D0 ] }; key { [ U13A9, U13C8 ] }; key { [ U13A6, U13E5 ] }; key { [ U13AF, U13B2 ] }; key { [ U13DA, U13AB ] }; key { [ U13B8, U13A7 ] }; key { [ U13B5, U13AE ] }; key { [ U13E8, U13E0 ] }; key { [ apostrophe, quotedbl ] }; key { [ U13AC, U13C3 ] }; key { [ U13F4, U13ED ] }; key { [ U13D3, U13DF ] }; key { [ U13A5, U13DE ] }; key { [ U13A8, U13F0 ] }; key { [ U13BE, U13BB ] }; key { [ U13C5, U13B7 ] }; key { [ comma, U13E2 ] }; key { [ period, U13B4 ] }; key { [ U13C2, U13C9 ] }; }; // Add Hawaiian `okina and kahako to US layout // Author: Greg Meyer , 2020 // this mapping follows the one for Windows here: http://www.olelo.hawaii.edu/enehana/winkbd.php // `okina replaces apostrophe (apostrophe moves to level 3) // vowels with kahako (macron) are level 3 symbols partial alphanumeric_keys xkb_symbols "haw" { include "us(basic)" name[Group1] = "Hawaiian"; // `okina replaces single apostrophe // alt gives the literal apostrophe key {[ U02BB, quotedbl, apostrophe ] }; // kahako key {[ a, A, amacron, Amacron ]}; key {[ e, E, emacron, Emacron ]}; key {[ u, U, umacron, Umacron ]}; key {[ i, I, imacron, Imacron ]}; key {[ o, O, omacron, Omacron ]}; include "level3(ralt_switch)" }; // Serbian charecters added as third level symbols to US keyboard layout. partial alphanumeric_keys xkb_symbols "hbs" { include "us" name[Group1]= "Serbo-Croatian (US)"; key { [ grave, asciitilde ] }; key { [ 6, dead_caron, asciicircum, asciicircum ] }; key { [ 8, asterisk, multiply, division ] }; key { [ minus, underscore, endash, emdash ] }; key { [ l, L, U1C9, U1C8 ] }; key { [ n, N, U1CC, U1CB ] }; key { [ z, Z, U1C6, U1C5 ] }; key { [ e, E, EuroSign, cent ] }; key { [ d, D, dstroke, Dstroke ] }; key { [ dead_acute, quotedbl, apostrophe, apostrophe ] }; key { [ space, space, nobreakspace, nobreakspace ] }; key { [ comma, less, U3003, guillemotright ] }; key { [ period, greater, ellipsis, guillemotleft ] }; include "level3(ralt_switch)" }; // Workman Keyboard Layout symbols for xkb on X.Org Server 7.x // 09-06-2010 OJ Bucao. http://www.workmanlayout.com partial alphanumeric_keys xkb_symbols "workman" { include "us(basic)" name[Group1]= "English (Workman)"; key { [ q, Q ] }; key { [ d, D ] }; key { [ r, R ] }; key { [ w, W ] }; key { [ b, B ] }; key { [ j, J ] }; key { [ f, F ] }; key { [ u, U ] }; key { [ p, P ] }; key { [ semicolon, colon ] }; key { [ a, A ] }; key { [ s, S ] }; key { [ h, H ] }; key { [ t, T ] }; key { [ g, G ] }; key { [ y, Y ] }; key { [ n, N ] }; key { [ e, E ] }; key { [ o, O ] }; key { [ i, I ] }; key { [ z, Z ] }; key { [ x, X ] }; key { [ m, M ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ k, K ] }; key { [ l, L ] }; key { [ BackSpace, Escape, BackSpace, BackSpace ] }; include "level3(ralt_switch)" }; partial alphanumeric_keys xkb_symbols "workman-intl" { include "us(intl)" name[Group1]= "English (Workman, intl., with dead keys)"; key { [ q, Q, adiaeresis, Adiaeresis ] }; key { [ d, D, eth, ETH ] }; key { [ r, R, registered, registered ] }; key { [ w, W, aring, Aring ] }; key { [ b, B, b, B ] }; key { [ j, J, j, J ] }; key { [ f, F, f, F ] }; key { [ u, U, uacute, Uacute ] }; key { [ p, P, odiaeresis, Odiaeresis ] }; key { [ semicolon, colon, paragraph, degree ] }; key { [ a, A, aacute, Aacute ] }; key { [ s, S, ssharp, section ] }; key { [ h, H, h, H ] }; key { [ t, T, thorn, THORN ] }; key { [ g, G, g, G ] }; key { [ y, Y, udiaeresis, Udiaeresis ] }; key { [ n, N, ntilde, Ntilde ] }; key { [ e, E, eacute, Eacute ] }; key { [ o, O, oacute, Oacute ] }; key { [ i, I, iacute, Iacute ] }; key { [ z, Z, ae, AE ] }; key { [ x, X, x, X ] }; key { [ m, M, mu, mu ] }; key { [ c, C, copyright, cent ] }; key { [ v, V, v, V ] }; key { [ k, K, oe, OE ] }; key { [ l, L, oslash, Ooblique ] }; key { [ BackSpace, Escape, BackSpace, BackSpace ] }; include "level3(ralt_switch)" }; // Norman keyboard layout symbols for xkb on X.Org Server 7.x // Written 11/23/2012, revised 3/7/2013 by David Norman http://normanlayout.info // To the extent possible under law, the author(s) have dedicated all // copyright and related and neighboring rights to this software to the // public domain worldwide. This software is distributed without any warranty. partial alphanumeric_keys xkb_symbols "norman" { include "us(basic)" name[Group1]= "English (Norman)"; key { [ q, Q ] }; key { [ w, W ] }; key { [ d, D ] }; key { [ f, F ] }; key { [ k, K ] }; key { [ j, J ] }; key { [ u, U ] }; key { [ r, R ] }; key { [ l, L ] }; key { [ semicolon, colon ] }; key { [ a, A ] }; key { [ s, S ] }; key { [ e, E ] }; key { [ t, T ] }; key { [ g, G ] }; key { [ y, Y ] }; key { [ n, N ] }; key { [ i, I ] }; key { [ o, O ] }; key { [ h, H ] }; key { [ z, Z ] }; key { [ x, X ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ b, B ] }; key { [ p, P ] }; key { [ m, M ] }; key { [ BackSpace ] }; include "level3(ralt_switch)" }; // Carpalx layout created by Martin Krzywinski // http://mkweb.bcgsc.ca/carpalx/ partial alphanumeric_keys xkb_symbols "carpalx" { name[Group1]= "English (Carpalx)"; key { [ grave, asciitilde ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ 5, percent ] }; key { [ 6, asciicircum ] }; key { [ 7, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ q, Q ] }; key { [ g, G ] }; key { [ m, M ] }; key { [ l, L ] }; key { [ w, W ] }; key { [ y, Y ] }; key { [ f, F ] }; key { [ u, U ] }; key { [ b, B ] }; key { [ semicolon, colon ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ d, D ] }; key { [ s, S ] }; key { [ t, T ] }; key { [ n, N ] }; key { [ r, R ] }; key { [ i, I ] }; key { [ a, A ] }; key { [ e, E ] }; key { [ o, O ] }; key { [ h, H ] }; key { [ apostrophe, quotedbl ] }; key { [ z, Z ] }; key { [ x, X ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ p, P ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ slash, question ] }; key { [ backslash, bar ] }; }; // Carpalx layout created by Martin Krzywinski // http://mkweb.bcgsc.ca/carpalx/ // Merged with us(intl) and modified to move // accented vowels closer to the plain vowels partial alphanumeric_keys xkb_symbols "carpalx-intl" { include "us(carpalx)" name[Group1]= "English (Carpalx, intl., with dead keys)"; key { [dead_grave, dead_tilde, grave, asciitilde ] }; key { [ 1, exclam, exclamdown, onesuperior ] }; key { [ 2, at, twosuperior, dead_doubleacute ] }; key { [ 3, numbersign, threesuperior, dead_macron ] }; key { [ 4, dollar, currency, sterling ] }; key { [ 5, percent, EuroSign, dead_cedilla ] }; key { [ 6, dead_circumflex, onequarter, asciicircum ] }; key { [ 7, ampersand, onehalf, dead_horn ] }; key { [ 8, asterisk, threequarters, dead_ogonek ] }; key { [ 9, parenleft, leftsinglequotemark, dead_breve ] }; key { [ 0, parenright, rightsinglequotemark, dead_abovering ] }; key { [ minus, underscore, yen, dead_belowdot ] }; key { [ equal, plus, multiply, division ] }; key { [ q, Q, degree, paragraph ] }; key { [ g, G, U011F, U011E ] }; key { [ m, M, mu, mu ] }; key { [ l, L, copyright, cent ] }; key { [ w, W, w, W ] }; key { [ y, Y, idiaeresis, Idiaeresis ] }; key { [ f, F, adiaeresis, Adiaeresis ] }; key { [ u, U, udiaeresis, Udiaeresis ] }; key { [ b, B, odiaeresis, Odiaeresis ] }; key { [ semicolon, colon, oslash, Ooblique ] }; key { [ bracketleft, braceleft, guillemotleft, leftdoublequotemark ] }; key { [bracketright, braceright, guillemotright, rightdoublequotemark ] }; key { [ d, D, eth, ETH ] }; key { [ s, S, ssharp, section ] }; key { [ t, T, thorn, THORN ] }; key { [ n, N, ntilde, Ntilde ] }; key { [ r, R, registered, registered ] }; key { [ i, I, iacute, Iacute ] }; key { [ a, A, aacute, Aacute ] }; key { [ e, E, eacute, Eacute ] }; key { [ o, O, oacute, Oacute ] }; key { [ h, H, uacute, Uacute ] }; key { [dead_acute, dead_diaeresis, apostrophe, quotedbl ] }; key { [ z, Z, z, Z ] }; key { [ x, X, U015F, U015E ] }; key { [ c, C, ccedilla, Ccedilla ] }; key { [ v, V, ae, AE ] }; key { [ j, J, oe, OE ] }; key { [ k, K, U0131, U0130 ] }; key { [ p, P, aring, Aring ] }; key { [ comma, less, ediaeresis, Ediaeresis ] }; key { [ period, greater, dead_abovedot, dead_caron ] }; key { [ slash, question, questiondown, dead_hook ] }; key { [ backslash, bar, notsign, brokenbar ] }; key { [ backslash, bar, backslash, bar ] }; include "level3(ralt_switch)" }; // Carpalx layout created by Martin Krzywinski // http://mkweb.bcgsc.ca/carpalx/ // Merged with us(intl) and us(altgr-intl) and modified to move // accented vowels closer to the plain vowels partial alphanumeric_keys xkb_symbols "carpalx-altgr-intl" { include "us(carpalx-intl)" name[Group1]= "English (Carpalx, intl., with AltGr dead keys)"; // five dead keys moved into level3: key { [ grave, asciitilde, dead_grave, dead_tilde ] }; key { [apostrophe,quotedbl, dead_acute, dead_diaeresis ] }; // diversions from the MS Intl keyboard: key { [ 1, exclam, onesuperior, exclamdown ] }; // onequarter etc (not in iso8859-15) moved to get three unshifted deadkeys: key { [ 6, asciicircum, dead_circumflex, onequarter ] }; key { [ 7, ampersand, dead_horn, onehalf ] }; key { [ 8, asterisk, dead_ogonek, threequarters ] }; include "level3(ralt_switch)" }; // Carpalx layout created by Martin Krzywinski // Full optimization variant without fixed QWERTY-like ZXCV keys // http://mkweb.bcgsc.ca/carpalx/ partial alphanumeric_keys xkb_symbols "carpalx-full" { include "us(carpalx)" name[Group1]= "English (Carpalx, full optimization)"; key { [ b, B ] }; key { [ y, Y ] }; key { [ v, V ] }; key { [ f, F ] }; }; // Carpalx layout created by Martin Krzywinski // Full optimization variant without fixed QWERTY-like ZXCV keys // http://mkweb.bcgsc.ca/carpalx/ // Merged with us(intl) and modified to move // accented vowels closer to the plain vowels partial alphanumeric_keys xkb_symbols "carpalx-full-intl" { include "us(carpalx-intl)" name[Group1]= "English (Carpalx, full optimization, intl., with dead keys)"; key { [ b, B, idiaeresis, Idiaeresis ] }; key { [ y, Y, adiaeresis, Adiaeresis ] }; key { [ v, V, odiaeresis, Odiaeresis ] }; key { [ f, F, ae, AE ] }; }; // Carpalx layout created by Martin Krzywinski // Full optimization variant without fixed QWERTY-like ZXCV keys // http://mkweb.bcgsc.ca/carpalx/ // Merged with us(intl) and us(altgr-intl) and modified to move // accented vowels closer to the plain vowels partial alphanumeric_keys xkb_symbols "carpalx-full-altgr-intl" { include "us(carpalx-altgr-intl)" name[Group1]= "English (Carpalx, full optimization, intl., with AltGr dead keys)"; key { [ b, B, idiaeresis, Idiaeresis ] }; key { [ y, Y, adiaeresis, Adiaeresis ] }; key { [ v, V, odiaeresis, Odiaeresis ] }; key { [ f, F, ae, AE ] }; }; // EXTRAS: // Czech, Slovak and German charecters added as third level symbols to US keyboard layout. partial alphanumeric_keys xkb_symbols "cz_sk_de" { include "us" name[Group1]="Czech Slovak and German (US)"; key { [grave, asciitilde, uring, Uring ] }; key { [ 1, exclam, uacute, Uacute ] }; key { [ 2, at, ecaron, Ecaron ] }; key { [ 3, numbersign, scaron, Scaron ] }; key { [ 4, dollar, ccaron, Ccaron ] }; key { [ 5, percent, rcaron, Rcaron ] }; key { [ 6, asciicircum, zcaron, Zcaron ] }; key { [ 7, ampersand, yacute, Yacute ] }; key { [ 8, asterisk, aacute, Aacute ] }; key { [ 9, parenleft, iacute, Iacute ] }; key { [ 0, parenright, eacute, Eacute ] }; key { [minus, underscore, ssharp, 0x1001E9E ] }; key { [equal, plus, dead_acute, dead_caron ] }; key { [ e, E, EuroSign, Eacute ] }; key { [bracketleft, braceleft, udiaeresis, Udiaeresis ] }; key { [ semicolon, colon, odiaeresis, Odiaeresis ] }; key { [apostrophe, quotedbl,adiaeresis, Adiaeresis ] }; key { [ a, A, aacute, Aacute ] }; key { [ i, I, iacute, Iacute ] }; key { [ o, O, oacute, Oacute ] }; key { [ y, Y, yacute, Yacute ] }; key { [ u, U, uring, Uring ] }; key { [ s, S, scaron, Scaron ] }; key { [ z, Z, zcaron, Zcaron ] }; key { [ c, C, ccaron, Ccaron ] }; key { [ r, R, rcaron, Rcaron ] }; key { [ t, T, tcaron, Tcaron ] }; key { [ d, D, dcaron, Dcaron ] }; key { [ n, N, ncaron, Ncaron ] }; key { [ l, L, lcaron, Lcaron ] }; key { [ p, P,ocircumflex, Ocircumflex ] }; key { [ space, space, nobreakspace, nobreakspace] }; include "level3(ralt_switch)" }; // 03 December 2017 - Added us(scn), please refer to // Cadèmia Siciliana partial alphanumeric_keys xkb_symbols "scn" { include "us(intl)" name[Group1]="Sicilian (US keyboard)"; key { [ e, E, U0259, U018F ] }; key { [ d, D, U1E0D, U1E0C ] }; key { [ f, F, U0111, U0110 ] }; key { [ h, H, U1E25, U1E24 ] }; key { [ x, X, U03C7, U03A7 ] }; key { [ period, greater, U1D58, dead_caron ] }; include "level3(ralt_switch)" }; // XCompose is out! Unicode combining is in! For those of us who live // on the edge: A keymap using Unicode combining characters instead of // deadkeys. This variation does not deviate from the lame MS-style // US-intl layout; but it uses AltGr for combining, like altgr-intl. // // This might break your font layout layout systems (because they // suck), caveat emptor. Also, most of today's software will count // individual combining marks for selection, deletion, character // counting &c., and won't be smart enough to do canonical equivalence // when searching, &c. // // With Unicode combining you use "handwriting order", not // "typewriting order" as with deadkeys. That is, you first type the // base character, then the diacritics/accents/modifiers. This has // the advantage of avoiding hidden states --- each keypress changes // something on screen. // // TODO: as of now, this duplicates all us(intl) functionality with // combining. With care, perhaps we could add more combining marks // not present in intl, and support all major languages. partial alphanumeric_keys xkb_symbols "intl-unicode" { name[Group1]= "English (US, intl., AltGr Unicode combining)"; include "us(intl)" include "level3(ralt_switch)" // grave, tilde key { [grave, asciitilde, U0300, U0303 ] }; // double acute key { [ 2, at, twosuperior, U030B ] }; // macron key { [ 3, numbersign, threesuperior, U0304 ] }; // circumflex key { [ 6, asciicircum, onequarter, U0302 ] }; // horn key { [ 7, ampersand, onehalf, U031B ] }; // ogonek key { [ 8, asterisk, threequarters, U0328 ] }; // breve key { [ 9, parenleft, leftsinglequotemark, U0306 ] }; // abovering key { [ 0, parenright, rightsinglequotemark, U030A ] }; // belowdot key { [ minus, underscore, yen, U0323 ] }; // acute, diaeresis key { [apostrophe, quotedbl, U0301, U0308 ] }; // abovedot, caron key { [ period, greater, U0307, U030C ] }; // hook key { [ slash, question, questiondown, U0309 ] }; // alt-intl compatibility // cedilla, caron key { [ comma, less, U0327, U030C ] }; // ogonek, diaeresis key { [ semicolon, colon, U0328, U0308 ] }; // doubleacute, horn key { [ equal, plus, U030B, U031B ] }; // we don't do combining latin letters and combining enclosures // because support for those is very rare. }; // XCompose is out! Unicode combining is in! For those of us who live // on the edge: A keymap using Unicode combining characters instead of // deadkeys. This variation does break compatibility with us-intl, // whenever I thought it would be more mnemonic or Unicodeish. partial alphanumeric_keys xkb_symbols "alt-intl-unicode" { name[Group1]= "English (US, intl., AltGr Unicode combining, alt.)"; include "us(intl-unicode)" // easier macron; em-dash. // em-dash is available via compose, but I added here since it's such // an important typographic character. key { [ minus, underscore, U0304, U2014 ] }; // belowdot, abovedot (caron at coma/less key, per above) key { [ period, greater, U0323, U0307 ] }; }; partial alphanumeric_keys xkb_symbols "ats" { include "us" name[Group1]= "Atsina"; //Using Dead key to get COMBINING COMMA ABOVE for ejectives on //q, l, t, s, m, g, k, p, w, y, r //XCompose key is used for the other accute and grave. key { [ e, E, eacute, Eacute ] }; key { [ u, U, uacute, Uacute ] }; key { [ i, I, iacute, Iacute ] }; key { [ o, O, oacute, Oacute ] }; key { [ bracketleft, braceleft, U03B8 ] }; key { [ bracketright, braceright, U010D, U010C ] }; //U+010C (uppercase Č) and U+010D (lowercase č). key { [ a, A, aacute, Aacute ] }; //Small letter Open use compose to key get acute accent key { [ c, C, U0254, U0186 ] }; key { [ comma, less, U0313 ] }; key { [ slash, question, U0294 ] }; include "level3(ralt_switch)" include "compose(rctrl)" }; partial alphanumeric_keys xkb_symbols "crd" { include "us" name[Group1]= "Coeur d'Alene Salish"; key { [ w, W, U02B7, U02B7 ] }; key { [ 7, ampersand, U0294 ] }; key { [ q, Q, U221A ] }; key { [ v, V, U0259 ] }; key { [ backslash, bar, U026B ] }; key { [ e, E, U025B ] }; key { [ i, I, U026A ] }; key { [ j, J, U01F0 ] }; key { [ 6, asciicircum, U0295 ] }; key { [ s, S, U0161 ] }; key { [ c, C, U010D ] }; key { [ o, O, U0254 ] }; key { [ period, greater, U0323 ] }; include "level3(ralt_switch)" include "compose(rctrl)" }; partial alphanumeric_keys xkb_symbols "sun_type6" { include "sun_vndr/us(sun_type6)" }; // Implementation of the 3l keyboard layout // See https://github.com/jackrosenthal/threelayout for specification partial alphanumeric_keys modifier_keys xkb_symbols "3l" { name[Group1] = "English (3l)"; key.type[Group1] = "ONE_LEVEL"; key { [ Escape ] }; key { [ Tab ] }; key { [ ISO_Level3_Shift ] }; // Sym Modifier key { [ ISO_Level5_Shift ] }; // Cur/Num Modifier // Top row numbers - not part of spec, but given for convenience key { [ 1 ] }; key { [ 2 ] }; key { [ 3 ] }; key { [ 4 ] }; key { [ 5 ] }; key { [ 6 ] }; key { [ 7 ] }; key { [ 8 ] }; key { [ 9 ] }; key { [ 0 ] }; // Main keys // Order of mods (defined by EIGHT_LEVEL_SEMIALPHABETIC) is: // [ None, Shift, Sym, Shift+Sym, Num, Shift+Num, Sym+Num, Shift+Sym+Num ] key.type[Group1] = "EIGHT_LEVEL_SEMIALPHABETIC"; // Second row key { [ q, Q, quotedbl, Greek_omicron, Prior, Prior, U21CD, Greek_OMICRON ] }; key { [ f, F, underscore, Greek_phi, BackSpace, BackSpace, U21A4, Greek_PHI ] }; key { [ u, U, bracketleft, Greek_upsilon, Up, Up, U2191, Greek_UPSILON ] }; key { [ y, Y, bracketright, Greek_psi, Delete, Delete, U21A6, Greek_PSI ] }; key { [ z, Z, asciicircum, Greek_zeta, Next, Next, U21CF, Greek_ZETA ] }; key { [ x, X, exclam, Greek_xi, NoSymbol, NoSymbol, U2260, Greek_XI ] }; key { [ k, K, less, Greek_kappa, 1, A, U2A7D, Greek_KAPPA ] }; key { [ c, C, greater, Greek_chi, 2, B, U2A7E, Greek_CHI ] }; key { [ w, W, equal, Greek_omega, 3, C, U2261, Greek_OMEGA ] }; key { [ b, B, ampersand, Greek_beta, NoSymbol, NoSymbol, U2248, Greek_BETA ] }; // Home row key { [ o, O, slash, Greek_omega, Home, Home, U21D0, Greek_OMEGA ] }; key { [ h, H, minus, Greek_theta, Left, Left, U2190, Greek_THETA ] }; key { [ e, E, braceleft, Greek_epsilon, Down, Down, U2193, Greek_EPSILON ] }; key { [ a, A, braceright, Greek_alpha, Right, Right, U2192, Greek_ALPHA ] }; key { [ i, I, asterisk, Greek_iota, End, End, U21D2, Greek_IOTA ] }; key { [ d, D, question, Greek_delta, period, colon, U2286, Greek_DELTA ] }; key { [ r, R, parenleft, Greek_rho, 4, D, U2227, Greek_RHO ] }; key { [ t, T, parenright, Greek_tau, 5, E, U2228, Greek_TAU ] }; key { [ n, N, apostrophe, Greek_eta, 6, F, U2200, Greek_ETA ] }; key { [ s, S, colon, Greek_sigma, NoSymbol, NoSymbol, U2203, Greek_SIGMA ] }; // Bottom row key { [ comma, comma, numbersign, NoSymbol, slash, NoSymbol, U21AE, NoSymbol ] }; key { [ m, M, dollar, Greek_mu, asterisk, NoSymbol, U2194, Greek_MU ] }; key { [ period, period, bar, NoSymbol, minus, NoSymbol, U21CE, NoSymbol ] }; key { [ j, J, asciitilde, Greek_SIGMA, plus, NoSymbol, U21D4, NoSymbol ] }; key { [ semicolon, semicolon, grave, NoSymbol, comma, NoSymbol, U2282, NoSymbol ] }; key { [ g, G, plus, Greek_gamma, 0, NoSymbol, U2229, Greek_GAMMA ] }; key { [ l, L, percent, Greek_lambda, 7, parenleft, U222A, Greek_LAMBDA ] }; key { [ p, P, backslash, Greek_pi, 8, parenright, U2208, Greek_PI ] }; key { [ v, V, at, Greek_nu, 9, NoSymbol, U2209, Greek_NU ] }; include "level5(modifier_mapping)" }; // Chromebooks typically have the key which is normally in the caps // lock position mapped to keycode 133 (LWIN). For 3l, it is critical // that the key in this positon correspond to tab, so there is a // variant available for chromebook hardware. partial modifier_keys xkb_symbols "3l-cros" { include "us(3l)" name[Group1] = "English (3l, Chromebook)"; key { type[Group1] = "ONE_LEVEL", symbols[Group1] = [ Tab ] }; }; // A 3l variant for emacs users, which maps control to caps lock and (re)maps // tab back to tab. partial modifier_keys xkb_symbols "3l-emacs" { include "us(3l)" name[Group1] = "English (3l, emacs)"; key { [ Tab ] }; key { [ Control_L ] }; modifier_map Control { }; }; // Drix EU Latin - version 3.1 (2019-10-07) // Author: Jerome Leclanche // Latin layout based on classic US qwerty, with azerty-style second-row m key. // Features: // - Programmer-centric punctuation keys (All common symbols on right hand except < and > on left) // - Most common dead accents on altgr-shift number row // - Unicode arrows on Altgr+shift+WASD // - Some commonly used special characters available: // - Most common european special characters // - Misc currency symbols, copyright/registered/trademark symbols // - Common math symbols + some common greek letters // - Compose key replaces Mod5 // // This layout is in the Public Domain. // // ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┲━━━━━━━━━┓ // │ ~ ~ │ " ´ │ ' ` │ ^ ^ │ ` ¨ │ ´ ° │ 6 ¯ │ 7 ¸ │ 8 ˛ │ 9 ˇ │ | ˝ │ _ ± │ = ≠ ┃Backspace┃ // │ @ £ │ 1 ¹ │ 2 ² │ 3 ³ │ 4 ⁴ │ 5 ⁵ │ 6 ⁶ │ 7 ⁷ │ 8 ⁸ │ 9 ⁹ │ 0 ⁰ │ - " │ + ' ┃ ⌫ ┃ // ┢━━━━━┷━┱───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┴─┬───┺━┳━━━━━━━┫ // ┃Tab ┃ Q Ø │ W ↑ │ E € │ R ₽ │ T τ │ Y ¥ │ U U │ I ’ │ O Ω │ P ₱ │ [ « │ ] » ┃ ⏎ ┃ // ┃ ↹ ┃ q ø │ w w │ e € │ r ® │ t ™ │ y ¥ │ u u │ i ‘ │ o œ │ p π │ ( { │ ) } ┃ Enter ┃ // ┣━━━━━━━┻┱────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┴┬────┺┓ ┃ // ┃Caps ┃ A ← │ S ↓ │ D → │ F Ƒ │ G G │ H H │ J ” │ K „ │ L λ │ M M │ % ‰ │ & × ┃ ┃ // ┃Lock ⇬ ┃ a æ │ s ß │ d Δ │ f ƒ │ g g │ h h │ j “ │ k ‚ │ l £ │ m µ │ # ~ │ * $ ┃ ┃ // ┣━━━━━━┳━┹───┬─┴───┬─┴───┬─┴───┬─┴───┬─┴───┬─┴───┬─┴───┬─┴───┬─┴───┬─┴───┲━┷━━━━━┻━━━━━━┫ // ┃Shift ┃ > ≥ │ Z ¶ │ X ÷ │ C ¢ │ V V │ B ₿ │ N N │ ? ¿ │ , · │ ; ´ │ \ ¦ ┃Shift ┃ // ┃ ⇧ ┃ < ≤ │ z § │ x × │ c © │ v ♀ │ b ♂ │ n ⚥ │ ! ¡ │ . … │ : ` │ / | ┃ ⇧ ┃ // ┣━━━━━━┻┳━━━━┷━━┳━━┷━━━━┱┴─────┴─────┴─────┴─────┴─────┴────┲┷━━━━━╈━━━━━┻┳━━━━━━┳━━━━━━┫ // ┃Ctrl ┃ Fn ┃Alt ┃ ␣ Space Nobreakspace ⍽ ┃AltGr ┃Multi ┃ Ctxt ┃ Ctrl ┃ // ┃ ┃ ┃ ┃ ␣ Space Nobreakspace ⍽ ┃ ┃ ┃ Menu ┃ ┃ // ┗━━━━━━━┻━━━━━━━┻━━━━━━━┹───────────────────────────────────┺━━━━━━┻━━━━━━┻━━━━━━┻━━━━━━┛ partial alphanumeric_keys modifier_keys xkb_symbols "drix" { name[Group1] = "English (Drix)"; // First row key {[ at, asciitilde, sterling, dead_tilde ]}; // @ ~ £ ~ key {[ 1, quotedbl, onesuperior, dead_grave ]}; // 1 " ¹ ` key {[ 2, apostrophe, twosuperior, dead_acute ]}; // 2 ' ² ´ key {[ 3, asciicircum, threesuperior, dead_circumflex ]}; // 3 ^ ³ ^ key {[ 4, grave, foursuperior, dead_diaeresis ]}; // 4 4 ⁴ ¨ key {[ 5, degree, fivesuperior, dead_abovering ]}; // 5 ° ⁵ ° key {[ 6, 6, sixsuperior, dead_macron ]}; // 6 6 ⁶ ¯ key {[ 7, 7, sevensuperior, dead_cedilla ]}; // 7 7 ⁷ ¸ key {[ 8, 8, eightsuperior, dead_ogonek ]}; // 8 8 ⁸ ˛ key {[ 9, 9, ninesuperior, dead_caron ]}; // 9 9 ⁹ ˇ key {[ 0, bar, zerosuperior, dead_doubleacute ]}; // 0 | ⁰ ˝ key {[ minus, underscore, quotedbl, plusminus ]}; // - _ " ± key {[ plus, equal, apostrophe, notequal ]}; // + = ' ≠ // Second row key {[ q, Q, oslash, Ooblique ]}; // q Q ø Ø key {[ w, W, w, uparrow ]}; // w W w ↑ key {[ e, E, EuroSign, EuroS ]}; // e E € € key {[ r, R, registered, 0x10020bd ]}; // r R ® ₽ key {[ t, T, trademark, Greek_tau ]}; // t T ™ τ key {[ y, Y, yen, yen ]}; // y Y ¥ ¥ key {[ u, U, u, U ]}; // u U u U key {[ i, I, leftsinglequotemark, rightsinglequotemark ]}; // i I ‘ ’ key {[ o, O, oe, Greek_OMEGA ]}; // o O œ Ω key {[ p, P, Greek_pi, 0x10020b1 ]}; // p P π ₱ key {[ parenleft, bracketleft, braceleft, guillemotleft ]}; // ( [ { « key {[ parenright, bracketright, braceright, guillemotright ]}; // ) ] } » // Third row key {[ a, A, ae, leftarrow ]}; // a A æ ← key {[ s, S, ssharp, downarrow ]}; // s S ß ↓ key {[ d, D, Greek_DELTA, rightarrow ]}; // d D Δ → key {[ f, F, 0x1000192, 0x1000191 ]}; // f F ƒ Ƒ key {[ g, G, g, G ]}; // g G g G key {[ h, H, h, H ]}; // h H h H key {[ j, J, leftdoublequotemark, rightdoublequotemark ]}; // j J “ ” key {[ k, K, singlelowquotemark, doublelowquotemark ]}; // k K ‚ „ key {[ l, L, sterling, Greek_lambda ]}; // l L £ λ key {[ m, M, mu, M ]}; // m M µ M key {[ numbersign, percent, asciitilde, 0x1002030 ]}; // # % ~ ‰ // Fourth row key {[ less, greater, lessthanequal, greaterthanequal ]}; // < > ≤ ≥ key {[ z, Z, section, paragraph ]}; // z Z § ¶ key {[ x, X, multiply, division ]}; // x X × ÷ key {[ c, C, copyright, cent ]}; // c C © ¢ key {[ v, V, 0x1002640, V ]}; // v V ♀ V key {[ b, B, 0x1002642, 0x10020bf ]}; // b B ♂ ₿ key {[ n, N, 0x10026a5, N ]}; // n N ⚥ N key {[ exclam, question, exclamdown, questiondown ]}; // ! ? ¡ ¿ key {[ period, comma, 0x1002026, periodcentered ]}; // . , … · key {[ colon, semicolon, grave, acute ]}; // : ; ` ´ key {[ slash, backslash, bar, brokenbar ]}; // / \ | ¦ // Next to the enter key key {[ asterisk, ampersand, dollar, multiply ]}; // * & $ × // Rebind right Super (windows key) into a Compose key key {[ Multi_key ]}; // Implement AltGr and AltGr+Shift // For some reason, include "level3(ralt_switch)" doesn't do the trick. key { type[Group1]="TWO_LEVEL", [ ISO_Level3_Shift, Multi_key ] }; }; // German and Swedish characters added as third level symbols to the US keyboard layout // Author: Stephan Lachnit , 2019 // the german umlauts are placed over the characters without diaeresis, the sharp-s over the s // the swedish ao is placed over the p, since it's closed to the position on a swedish keyboard // the euro sign is placed over the e, as it is usual for german and swedish keyboards partial alphanumeric_keys xkb_symbols "de_se_fi" { include "us(basic)" include "eurosign(e)" name[Group1] = "German, Swedish and Finnish (US)"; key {[ a, A, adiaeresis, Adiaeresis ]}; key {[ o, O, odiaeresis, Odiaeresis ]}; key {[ s, S, ssharp, U1E9E ]}; key {[ u, U, udiaeresis, Udiaeresis ]}; key {[ p, P, aring, Aring ]}; include "level3(ralt_switch)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/sync.sh000077500000000000000000000030211510033435100220620ustar00rootroot00000000000000#/bin/sh set -euo pipefail XKBCONFIGROOT='/usr/share/X11/xkb' XLOCALEDIR='/usr/share/X11/locale' if [ ! -d test/data ]; then echo "Run this from the top source dir" exit 1 fi for file in \ symbols/terminate \ symbols/in \ symbols/keypad \ symbols/altwin \ symbols/ctrl \ symbols/eurosign \ symbols/inet \ symbols/shift \ symbols/pc \ symbols/ca \ symbols/cz \ symbols/srvr_ctrl \ symbols/capslock \ symbols/latin \ symbols/level5 \ symbols/macintosh_vndr/apple \ symbols/macintosh_vndr/us \ symbols/us \ symbols/nbsp \ symbols/il \ symbols/group \ symbols/compose \ symbols/level3 \ symbols/ru \ symbols/rupeesign \ symbols/kpdl \ symbols/de \ symbols/ch \ symbols/empty \ keycodes/xfree86 \ keycodes/aliases \ keycodes/evdev \ keycodes/empty \ types/complete \ types/pc \ types/basic \ types/iso9995 \ types/level5 \ types/numpad \ types/extra \ types/mousekeys \ compat/complete \ compat/lednum \ compat/pc \ compat/ledscroll \ compat/basic \ compat/misc \ compat/iso9995 \ compat/accessx \ compat/xfree86 \ compat/level5 \ compat/caps \ compat/ledcaps \ compat/mousekeys \ rules/base \ rules/evdev \ ; do cp "$XKBCONFIGROOT/$file" "test/data/$file" done for file in \ compose.dir \ locale.alias \ locale.dir \ en_US.UTF-8/Compose \ ; do cp "$XLOCALEDIR/$file" "test/data/locale/$file" done xkbcommon-libxkbcommon-54ee7ac/test/data/types/000077500000000000000000000000001510033435100217175ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/types/basic000066400000000000000000000011371510033435100227250ustar00rootroot00000000000000default xkb_types "basic" { // Fairly standard definitions for // three of the four required key types. // The fourth type "KEYPAD" is defined in the "numpad" file. virtual_modifiers NumLock; type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers = Shift; map[Shift] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift] = Level2; map[Lock] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/complete000066400000000000000000000003171510033435100234530ustar00rootroot00000000000000default xkb_types "complete" { include "basic" include "mousekeys" include "pc" include "iso9995" include "level5" include "extra" include "numpad" include "extra(keypad)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/extra000066400000000000000000000125241510033435100227710ustar00rootroot00000000000000default partial xkb_types "default" { // Defines a type with a four-level shift, similar to the three-level // type used for iso9995, but it lets the Shift key behave "normally". virtual_modifiers Alt, NumLock, LevelThree; type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; // A four-level keypad variant. The first two levels are controlled by // NumLock (with active shifting like in KEYPAD). LevelThree overrides // this mode, with two additional shifted levels. type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers = Shift+NumLock+LevelThree; map[None] = Level1; map[Shift+NumLock] = Level1; map[NumLock] = Level2; map[Shift] = Level2; map[LevelThree] = Level3; map[NumLock+LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Shift+NumLock+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Number"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; // Base level, two shifted LevelThree levels, one Ctrl+Alt command level. type "FOUR_LEVEL_X" { modifiers = Shift+LevelThree+Control+Alt; map[None] = Level1; map[LevelThree] = Level2; map[Shift+LevelThree] = Level3; map[Control+Alt] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Alt Base"; level_name[Level3] = "Shift Alt"; level_name[Level4] = "Ctrl+Alt"; }; // A special type for keys used in the Serbian Latin Unicode keymap. // It makes it possible to use all three forms of latin letters // present in Unicode that are made up of two separate letters // (forms like LJ, Lj, and lj; NJ, Nj, and nj; etcetera). type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level4; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level3; preserve[Lock]= Lock; preserve[Lock+LevelThree]= Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "AltGr Base"; level_name[Level4] = "Shift AltGr"; }; // A key type for the German ssharp (for example), which is capitalized as SS. // CHARACTERISTICS: // It is FOUR_LEVEL with the exception that the fifth level is mapped to the // Lock modifier. If other modifiers are used, the Lock state is ignored. // DETAILS ABOUT GERMAN: // The capital form of ssharp (called sharp s) only exists for completely // capitalized text, not for words at the beginning of sentences nor for // nouns (nouns in German normally start with a captial letter). // The ssharp key, to the right of the zero key, takes this into account // and has a questionmark mapped to Shift-ssharp since normally no capital // version is needed. // When typing with active CapsLock, this key type is needed to // output two capital letters S because this is the only German key // whose capital letter is not the same as the one typed with Shift. type "FOUR_LEVEL_PLUS_LOCK" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock] = Level5; map[Lock+Shift] = Level2; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; level_name[Level5] = "Lock"; }; }; // This enables the four-level shifting also for the keypad. partial xkb_types "keypad" { virtual_modifiers NumLock, LevelThree; type "FOUR_LEVEL_KEYPAD" { modifiers = Shift+NumLock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[NumLock] = Level2; map[Shift+NumLock] = Level1; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[NumLock+LevelThree] = Level4; map[Shift+NumLock+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Number"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Alt Number"; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/iso9995000066400000000000000000000006551510033435100230020ustar00rootroot00000000000000default partial xkb_types "default" { // A key type which can be used to implement // an ISO9995-style level-three shift. virtual_modifiers LevelThree; type "THREE_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Level3"; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/level5000066400000000000000000000200431510033435100230350ustar00rootroot00000000000000default partial xkb_types "default" { // Defines a type with an eight-level shift, similar to the three-level // type used for iso9995, but it lets the Shift key behave "normally". virtual_modifiers NumLock,LevelThree,ScrollLock,LevelFive; type "EIGHT_LEVEL" { modifiers = Shift+LevelThree+LevelFive; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[LevelFive] = Level5; map[Shift+LevelFive] = Level6; map[LevelThree+LevelFive] = Level7; map[Shift+LevelThree+LevelFive] = Level8; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; level_name[Level5] = "X"; level_name[Level6] = "X Shift"; level_name[Level7] = "X Alt Base"; level_name[Level8] = "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree+LevelFive; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; map[LevelFive] = Level5; map[Shift+LevelFive] = Level6; map[Lock+LevelFive] = Level6; map[LevelThree+LevelFive] = Level7; map[Shift+LevelThree+LevelFive] = Level8; map[Lock+LevelThree+LevelFive] = Level8; map[Lock+Shift+LevelThree+LevelFive] = Level7; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; level_name[Level5] = "X"; level_name[Level6] = "X Shift"; level_name[Level7] = "X Alt Base"; level_name[Level8] = "X Shift Alt"; }; type "EIGHT_LEVEL_LEVEL_FIVE_LOCK" { // Level5-Lock is implemented by using NumLock, because a real modifier // is required. modifiers = Shift + Lock + LevelThree + NumLock + LevelFive; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[LevelThree+Shift] = Level4; map[LevelFive] = Level5; map[LevelFive+Shift] = Level6; map[LevelFive+LevelThree] = Level7; map[LevelFive+LevelThree+Shift] = Level8; map[NumLock] = Level5; map[NumLock+Shift] = Level6; map[NumLock+LevelThree] = Level7; map[NumLock+LevelThree+Shift] = Level8; map[NumLock+LevelFive] = Level1; map[NumLock+LevelFive+Shift] = Level2; map[NumLock+LevelFive+LevelThree] = Level3; map[NumLock+LevelFive+LevelThree+Shift] = Level4; // Lock has no effect map[Lock] = Level1; map[Lock+Shift] = Level2; map[Lock+LevelThree] = Level3; map[Lock+LevelThree+Shift] = Level4; map[Lock+LevelFive] = Level5; map[Lock+LevelFive+Shift] = Level6; map[Lock+LevelFive+LevelThree] = Level7; map[Lock+LevelFive+LevelThree+Shift] = Level8; map[Lock+NumLock] = Level5; map[Lock+NumLock+Shift] = Level6; map[Lock+NumLock+LevelThree] = Level7; map[Lock+NumLock+LevelThree+Shift] = Level8; map[Lock+NumLock+LevelFive] = Level1; map[Lock+NumLock+LevelFive+Shift] = Level2; map[Lock+NumLock+LevelFive+LevelThree] = Level3; map[Lock+NumLock+LevelFive+LevelThree+Shift] = Level4; preserve[LevelFive+Shift] = Shift; preserve[NumLock+Shift] = Shift; preserve[Lock+LevelFive+Shift] = Shift; preserve[Lock+NumLock+Shift] = Shift; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; level_name[Level5] = "X"; level_name[Level6] = "X Shift"; level_name[Level7] = "X Alt Base"; level_name[Level8] = "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK" { // Level5-Lock is implemented by using NumLock, because a real modifier // is required. modifiers = Shift + Lock + LevelThree + NumLock + LevelFive; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[LevelThree+Shift] = Level4; map[LevelFive] = Level5; map[LevelFive+Shift] = Level6; map[LevelFive+LevelThree] = Level7; map[LevelFive+LevelThree+Shift] = Level8; map[NumLock] = Level5; map[NumLock+Shift] = Level6; map[NumLock+LevelThree] = Level7; map[NumLock+LevelThree+Shift] = Level8; map[NumLock+LevelFive] = Level1; map[NumLock+LevelFive+Shift] = Level2; map[NumLock+LevelFive+LevelThree] = Level3; map[NumLock+LevelFive+LevelThree+Shift] = Level4; // Lock interchanges Level1 and Level2 map[Lock] = Level2; map[Lock+Shift] = Level1; map[Lock+LevelThree] = Level3; map[Lock+LevelThree+Shift] = Level4; map[Lock+LevelFive] = Level5; map[Lock+LevelFive+Shift] = Level6; map[Lock+LevelFive+LevelThree] = Level7; map[Lock+LevelFive+LevelThree+Shift] = Level8; map[Lock+NumLock] = Level5; map[Lock+NumLock+Shift] = Level6; map[Lock+NumLock+LevelThree] = Level7; map[Lock+NumLock+LevelThree+Shift] = Level8; map[Lock+NumLock+LevelFive] = Level2; map[Lock+NumLock+LevelFive+Shift] = Level1; map[Lock+NumLock+LevelFive+LevelThree] = Level4; map[Lock+NumLock+LevelFive+LevelThree+Shift] = Level3; preserve[LevelFive+Shift] = Shift; preserve[NumLock+Shift] = Shift; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; level_name[Level5] = "X"; level_name[Level6] = "X Shift"; level_name[Level7] = "X Alt Base"; level_name[Level8] = "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree+LevelFive; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; map[LevelFive] = Level5; map[Shift+LevelFive] = Level6; map[Lock+LevelFive] = Level6; map[Lock+Shift+LevelFive] = Level6; map[LevelThree+LevelFive] = Level7; map[Shift+LevelThree+LevelFive] = Level8; map[Lock+LevelThree+LevelFive] = Level7; map[Lock+Shift+LevelThree+LevelFive] = Level8; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; preserve[Lock+LevelFive] = Lock; preserve[Lock+Shift+LevelFive] = Lock; preserve[Lock+LevelThree+LevelFive] = Lock; preserve[Lock+Shift+LevelThree+LevelFive] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; level_name[Level5] = "X"; level_name[Level6] = "X Shift"; level_name[Level7] = "X Alt Base"; level_name[Level8] = "X Shift Alt"; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/merge_modes000066400000000000000000000627011510033435100241360ustar00rootroot00000000000000// WARNING: This file was auto-generated by: scripts/update-merge-modes-tests.py xkb_types "base-default" { virtual_modifiers NumLock, LevelThree=none, LevelFive=Mod3; virtual_modifiers U1, U2, U3; // virtual_modifiers U4, U5, U6; virtual_modifiers Z1=none, Z2=none, Z3=none; // virtual_modifiers Z4=none, Z5=none, Z6=none; virtual_modifiers M1=0x1000, M2=0x2000, M3=0x3000; // virtual_modifiers M4=0x4000, M5=0x5000, M6=0x6000; type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers = Shift; map[Shift] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift] = Level2; map[Lock] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; map[Lock] = 2; map[LevelThree] = 3; level_name[1] = "1"; level_name[2] = "2"; level_name[3] = "3"; }; }; xkb_types "base-augment" { augment virtual_modifiers NumLock, LevelThree=none, LevelFive=Mod3; augment virtual_modifiers U1, U2, U3; // augment virtual_modifiers U4, U5, U6; augment virtual_modifiers Z1=none, Z2=none, Z3=none; // augment virtual_modifiers Z4=none, Z5=none, Z6=none; augment virtual_modifiers M1=0x1000, M2=0x2000, M3=0x3000; // augment virtual_modifiers M4=0x4000, M5=0x5000, M6=0x6000; augment type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; augment type "TWO_LEVEL" { modifiers = Shift; map[Shift] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; augment type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift] = Level2; map[Lock] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; augment type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; augment type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; augment type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; augment type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; augment type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; map[Lock] = 2; map[LevelThree] = 3; level_name[1] = "1"; level_name[2] = "2"; level_name[3] = "3"; }; }; xkb_types "base-override" { override virtual_modifiers NumLock, LevelThree=none, LevelFive=Mod3; override virtual_modifiers U1, U2, U3; // override virtual_modifiers U4, U5, U6; override virtual_modifiers Z1=none, Z2=none, Z3=none; // override virtual_modifiers Z4=none, Z5=none, Z6=none; override virtual_modifiers M1=0x1000, M2=0x2000, M3=0x3000; // override virtual_modifiers M4=0x4000, M5=0x5000, M6=0x6000; override type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; override type "TWO_LEVEL" { modifiers = Shift; map[Shift] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; override type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift] = Level2; map[Lock] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; override type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; override type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; override type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; override type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; override type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; map[Lock] = 2; map[LevelThree] = 3; level_name[1] = "1"; level_name[2] = "2"; level_name[3] = "3"; }; }; xkb_types "base-replace" { replace virtual_modifiers NumLock, LevelThree=none, LevelFive=Mod3; replace virtual_modifiers U1, U2, U3; // replace virtual_modifiers U4, U5, U6; replace virtual_modifiers Z1=none, Z2=none, Z3=none; // replace virtual_modifiers Z4=none, Z5=none, Z6=none; replace virtual_modifiers M1=0x1000, M2=0x2000, M3=0x3000; // replace virtual_modifiers M4=0x4000, M5=0x5000, M6=0x6000; replace type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; replace type "TWO_LEVEL" { modifiers = Shift; map[Shift] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; replace type "ALPHABETIC" { modifiers = Shift+Lock; map[Shift] = Level2; map[Lock] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; replace type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; replace type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; replace type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; replace type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; replace type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; map[Lock] = 2; map[LevelThree] = 3; level_name[1] = "1"; level_name[2] = "2"; level_name[3] = "3"; }; }; xkb_types "update-default" { virtual_modifiers NumLock=Mod2; // Changed: now mapped virtual_modifiers LevelThree=Mod5; // Changed: altered mapping (from 0) virtual_modifiers LevelFive=Mod3; // Unhanged: same mapping virtual_modifiers U7, Z7=0, M7=0x700000; // Changed: new virtual_modifiers U1; // Unchanged (unmapped) virtual_modifiers U2 = none; // Changed: now mapped virtual_modifiers U3 = 0x300000; // Changed: now mapped // virtual_modifiers U4; // Unchanged (unmapped) // virtual_modifiers U5 = none; // Changed: now mapped // virtual_modifiers U6 = 0x600000; // Changed: now mapped virtual_modifiers Z1; // Unchanged (= 0) virtual_modifiers Z2 = none; // Unchanged (same mapping) virtual_modifiers Z3 = 0x310000; // Changed: altered mapping (from 0) // virtual_modifiers Z4; // Unchanged (= 0) // virtual_modifiers Z5 = none; // Unchanged (same mapping) // virtual_modifiers Z6 = 0x610000; // Changed: altered mapping (from 0) virtual_modifiers M1; // Unchanged (≠ 0) virtual_modifiers M2 = none; // Changed: reset virtual_modifiers M3 = 0x320000; // Changed: altered mapping (from ≠ 0) // virtual_modifiers M4; // Unchanged (≠ 0) // virtual_modifiers M5 = none; // Changed: reset // virtual_modifiers M6 = 0x620000; // Changed: altered mapping (from ≠ 0) type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; // Change name }; type "TWO_LEVEL" { modifiers = Shift+M1; // Changed map[Shift] = Level2; map[M1] = Level2; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; type "ALPHABETIC" { modifiers = Lock; // Changed map[None] = Level2; // Changed map[Lock] = Level1; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; // Changed map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; // Unchanged type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; // map[Lock] = 2; // Changed // map[LevelThree] = 3; map[LevelThree] = 1; // Changed map[Shift+LevelThree] = 4; // Changed level_name[1] = "A"; // Changed level_name[2] = "2"; level_name[3] = "3"; level_name[4] = "4"; // Changed }; // New type "YYY" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; }; }; xkb_types "update-augment" { augment virtual_modifiers NumLock=Mod2; // Changed: now mapped augment virtual_modifiers LevelThree=Mod5; // Changed: altered mapping (from 0) augment virtual_modifiers LevelFive=Mod3; // Unhanged: same mapping augment virtual_modifiers U7, Z7=0, M7=0x700000; // Changed: new augment virtual_modifiers U1; // Unchanged (unmapped) augment virtual_modifiers U2 = none; // Changed: now mapped augment virtual_modifiers U3 = 0x300000; // Changed: now mapped // augment virtual_modifiers U4; // Unchanged (unmapped) // augment virtual_modifiers U5 = none; // Changed: now mapped // augment virtual_modifiers U6 = 0x600000; // Changed: now mapped augment virtual_modifiers Z1; // Unchanged (= 0) augment virtual_modifiers Z2 = none; // Unchanged (same mapping) augment virtual_modifiers Z3 = 0x310000; // Changed: altered mapping (from 0) // augment virtual_modifiers Z4; // Unchanged (= 0) // augment virtual_modifiers Z5 = none; // Unchanged (same mapping) // augment virtual_modifiers Z6 = 0x610000; // Changed: altered mapping (from 0) augment virtual_modifiers M1; // Unchanged (≠ 0) augment virtual_modifiers M2 = none; // Changed: reset augment virtual_modifiers M3 = 0x320000; // Changed: altered mapping (from ≠ 0) // augment virtual_modifiers M4; // Unchanged (≠ 0) // augment virtual_modifiers M5 = none; // Changed: reset // augment virtual_modifiers M6 = 0x620000; // Changed: altered mapping (from ≠ 0) augment type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; // Change name }; augment type "TWO_LEVEL" { modifiers = Shift+M1; // Changed map[Shift] = Level2; map[M1] = Level2; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; augment type "ALPHABETIC" { modifiers = Lock; // Changed map[None] = Level2; // Changed map[Lock] = Level1; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; augment type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; // Changed map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; // Unchanged augment type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; augment type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; augment type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; augment type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; // map[Lock] = 2; // Changed // map[LevelThree] = 3; map[LevelThree] = 1; // Changed map[Shift+LevelThree] = 4; // Changed level_name[1] = "A"; // Changed level_name[2] = "2"; level_name[3] = "3"; level_name[4] = "4"; // Changed }; // New augment type "YYY" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; }; }; xkb_types "update-override" { override virtual_modifiers NumLock=Mod2; // Changed: now mapped override virtual_modifiers LevelThree=Mod5; // Changed: altered mapping (from 0) override virtual_modifiers LevelFive=Mod3; // Unhanged: same mapping override virtual_modifiers U7, Z7=0, M7=0x700000; // Changed: new override virtual_modifiers U1; // Unchanged (unmapped) override virtual_modifiers U2 = none; // Changed: now mapped override virtual_modifiers U3 = 0x300000; // Changed: now mapped // override virtual_modifiers U4; // Unchanged (unmapped) // override virtual_modifiers U5 = none; // Changed: now mapped // override virtual_modifiers U6 = 0x600000; // Changed: now mapped override virtual_modifiers Z1; // Unchanged (= 0) override virtual_modifiers Z2 = none; // Unchanged (same mapping) override virtual_modifiers Z3 = 0x310000; // Changed: altered mapping (from 0) // override virtual_modifiers Z4; // Unchanged (= 0) // override virtual_modifiers Z5 = none; // Unchanged (same mapping) // override virtual_modifiers Z6 = 0x610000; // Changed: altered mapping (from 0) override virtual_modifiers M1; // Unchanged (≠ 0) override virtual_modifiers M2 = none; // Changed: reset override virtual_modifiers M3 = 0x320000; // Changed: altered mapping (from ≠ 0) // override virtual_modifiers M4; // Unchanged (≠ 0) // override virtual_modifiers M5 = none; // Changed: reset // override virtual_modifiers M6 = 0x620000; // Changed: altered mapping (from ≠ 0) override type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; // Change name }; override type "TWO_LEVEL" { modifiers = Shift+M1; // Changed map[Shift] = Level2; map[M1] = Level2; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; override type "ALPHABETIC" { modifiers = Lock; // Changed map[None] = Level2; // Changed map[Lock] = Level1; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; override type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; // Changed map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; // Unchanged override type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; override type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; override type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; override type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; // map[Lock] = 2; // Changed // map[LevelThree] = 3; map[LevelThree] = 1; // Changed map[Shift+LevelThree] = 4; // Changed level_name[1] = "A"; // Changed level_name[2] = "2"; level_name[3] = "3"; level_name[4] = "4"; // Changed }; // New override type "YYY" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; }; }; xkb_types "update-replace" { replace virtual_modifiers NumLock=Mod2; // Changed: now mapped replace virtual_modifiers LevelThree=Mod5; // Changed: altered mapping (from 0) replace virtual_modifiers LevelFive=Mod3; // Unhanged: same mapping replace virtual_modifiers U7, Z7=0, M7=0x700000; // Changed: new replace virtual_modifiers U1; // Unchanged (unmapped) replace virtual_modifiers U2 = none; // Changed: now mapped replace virtual_modifiers U3 = 0x300000; // Changed: now mapped // replace virtual_modifiers U4; // Unchanged (unmapped) // replace virtual_modifiers U5 = none; // Changed: now mapped // replace virtual_modifiers U6 = 0x600000; // Changed: now mapped replace virtual_modifiers Z1; // Unchanged (= 0) replace virtual_modifiers Z2 = none; // Unchanged (same mapping) replace virtual_modifiers Z3 = 0x310000; // Changed: altered mapping (from 0) // replace virtual_modifiers Z4; // Unchanged (= 0) // replace virtual_modifiers Z5 = none; // Unchanged (same mapping) // replace virtual_modifiers Z6 = 0x610000; // Changed: altered mapping (from 0) replace virtual_modifiers M1; // Unchanged (≠ 0) replace virtual_modifiers M2 = none; // Changed: reset replace virtual_modifiers M3 = 0x320000; // Changed: altered mapping (from ≠ 0) // replace virtual_modifiers M4; // Unchanged (≠ 0) // replace virtual_modifiers M5 = none; // Changed: reset // replace virtual_modifiers M6 = 0x620000; // Changed: altered mapping (from ≠ 0) replace type "ONE_LEVEL" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; // Change name }; replace type "TWO_LEVEL" { modifiers = Shift+M1; // Changed map[Shift] = Level2; map[M1] = Level2; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Shift"; }; replace type "ALPHABETIC" { modifiers = Lock; // Changed map[None] = Level2; // Changed map[Lock] = Level1; // Changed level_name[Level1] = "Base"; level_name[Level2] = "Caps"; }; replace type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; // Changed map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; // Unchanged replace type "FOUR_LEVEL" { modifiers = Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; replace type "FOUR_LEVEL_ALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Lock+Shift+LevelThree] = Level3; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; replace type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers = Shift+Lock+LevelThree; map[None] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level4; preserve[Lock+LevelThree] = Lock; preserve[Lock+Shift+LevelThree] = Lock; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; }; replace type "XXX" { modifiers = Shift+Lock+LevelThree; map[None] = 1; map[Shift] = 2; // map[Lock] = 2; // Changed // map[LevelThree] = 3; map[LevelThree] = 1; // Changed map[Shift+LevelThree] = 4; // Changed level_name[1] = "A"; // Changed level_name[2] = "2"; level_name[3] = "3"; level_name[4] = "4"; // Changed }; // New replace type "YYY" { modifiers = None; map[None] = Level1; level_name[Level1]= "New"; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/merge_modes_vmods000066400000000000000000000011431510033435100253370ustar00rootroot00000000000000xkb_types "base" { virtual_modifiers U1, U2, U3, U4, U5, U6; virtual_modifiers Z1=none, Z2=none, Z3=none, Z4=none, Z5=none, Z6=none; virtual_modifiers M1=0x1000, M2=0x2000, M3=0x3000, M4=0x4000, M5=0x5000, M6=0x6000; }; xkb_types "new" { virtual_modifiers U7, Z7=0, M7=0x70000; augment virtual_modifiers U1, U2=none, U3=0x300000; override virtual_modifiers U4, U5=none, U6=0x600000; augment virtual_modifiers Z1, Z2=none, Z3=0x310000; override virtual_modifiers Z4, Z5=none, Z6=0x610000; augment virtual_modifiers M1, M2=none, M3=0x320000; override virtual_modifiers M4, M5=none, M6=0x620000; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/mousekeys000066400000000000000000000003261510033435100236670ustar00rootroot00000000000000default partial xkb_types "default" { virtual_modifiers Alt; type "SHIFT+ALT" { modifiers = Shift+Alt; map[Shift+Alt] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Shift+Alt"; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/numpad000066400000000000000000000037511510033435100231340ustar00rootroot00000000000000default partial xkb_types "pc" { virtual_modifiers NumLock; type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; map[Shift] = Level2; map[NumLock] = Level2; map[Shift+NumLock] = Level1; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; }; // On Mac keypads, level 1 and 2 are swapped. partial xkb_types "mac" { type "KEYPAD" { modifiers = None; map[None] = Level2; level_name[Level2] = "Number"; }; include "extra(keypad)" }; partial xkb_types "microsoft" { virtual_modifiers NumLock; type "KEYPAD" { modifiers = Shift+NumLock; map[None] = Level1; preserve[Shift] = Shift; map[NumLock] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Number"; }; include "extra(keypad)" }; // Swiss-German style numeric keypad: Shift and NumLock operate as // two independent modifiers; however, since we want shift state for // the cursor keys, only three levels are used from the key mappings. // Closest type is actually FOUR_LEVEL_X, but most numpad layouts use // FOUR_LEVEL_MIXED_KEYPAD, so that's the one we are going to override. partial xkb_types "shift3" { virtual_modifiers Alt, NumLock; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers = Shift+NumLock+Control+Alt; // NumLock Off => navigate using cursor keys map[None] = Level1; // NumLock Off + Shift pressed => select using cursor keys preserve[Shift] = Shift; // NumLock On => decimal digits map[NumLock] = Level2; // NumLock On + Shift pressed => auxiliary symbols, // e.g. hexadecimal digits map[Shift+NumLock] = Level3; // Ctrl + Alt, regardless of NumLock and Shift => command keys map[Control+Alt] = Level4; // reverse map from levels to modifiers level_name[Level1] = "Base"; level_name[Level2] = "NumLock"; level_name[Level3] = "Shift+NumLock"; level_name[Level4] = "Ctrl+Alt"; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/pc000066400000000000000000000064311510033435100222500ustar00rootroot00000000000000default partial xkb_types "default" { // Some types that are necessary // for a full implementation of // a PC-compatible keyboard. virtual_modifiers Alt; virtual_modifiers LevelThree; virtual_modifiers LAlt; virtual_modifiers RAlt; virtual_modifiers RControl; virtual_modifiers LControl; type "PC_SUPER_LEVEL2" { modifiers = Mod4; map[None] = Level1; map[Mod4] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Super"; }; type "PC_CONTROL_LEVEL2" { modifiers = Control; map[None] = Level1; map[Control] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers = LControl; map[None] = Level1; map[LControl] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers = RControl; map[None] = Level1; map[RControl] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "RControl"; }; type "PC_ALT_LEVEL2" { modifiers = Alt; map[None] = Level1; map[Alt] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "Alt"; }; type "PC_LALT_LEVEL2" { modifiers = LAlt; map[None] = Level1; map[LAlt] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers = RAlt; map[None] = Level1; map[RAlt] = Level2; level_name[Level1] = "Base"; level_name[Level2] = "RAlt"; }; type "CTRL+ALT" { modifiers = Control+Alt+Shift+LevelThree; map[None] = Level1; map[Shift] = Level2; map[LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Control+Alt] = Level5; preserve[Shift] = Shift; preserve[Shift+LevelThree] = Shift; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Alt Base"; level_name[Level4] = "Shift Alt"; level_name[Level5] = "Ctrl+Alt"; }; // Local eight level. // Needed when you want part of your layout eight-level but cannot use // LevelFive as modifier, as this will take over the right Ctrl by default // for the whole layout and is too invasive for the average four-level user. // Needed to fix bug #9529. // FIXME: Should really use RControl but it seems not to be enabled by // default and touching this requires a lot of testing. type "LOCAL_EIGHT_LEVEL" { modifiers = Shift+Lock+LevelThree+Control; map[None] = Level1; map[Lock+Shift] = Level1; map[Shift] = Level2; map[Lock] = Level2; map[LevelThree] = Level3; map[Lock+Shift+LevelThree] = Level3; map[Shift+LevelThree] = Level4; map[Lock+LevelThree] = Level4; map[Control] = Level5; map[Lock+Shift+Control] = Level5; map[Shift+Control] = Level6; map[Lock+Control] = Level6; map[LevelThree+Control] = Level7; map[Lock+Shift+LevelThree+Control] = Level7; map[Shift+LevelThree+Control] = Level8; map[Lock+LevelThree+Control] = Level8; level_name[Level1] = "Base"; level_name[Level2] = "Shift"; level_name[Level3] = "Level3"; level_name[Level4] = "Shift Level3"; level_name[Level5] = "Ctrl"; level_name[Level6] = "Shift Ctrl"; level_name[Level7] = "Level3 Ctrl"; level_name[Level8] = "Shift Level3 Ctrl"; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/recursive000066400000000000000000000007561510033435100236610ustar00rootroot00000000000000default xkb_types "foo" { type "FOO" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; include "recursive" }; xkb_types "bar" { type "BAR" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; include "recursive(baz)" }; xkb_types "baz" { type "BAZ" { modifiers = None; map[None] = Level1; level_name[Level1]= "Any"; }; include "recursive(bar)" }; xkbcommon-libxkbcommon-54ee7ac/test/data/types/virtual_modifiers000066400000000000000000000003361510033435100253730ustar00rootroot00000000000000default xkb_types "ordered_explicit_mapping" { virtual_modifiers Alt = 0x100, Meta = 0x200, Super = 0x400, Hyper = 0x800, NumLock = 0x1000, LevelThree = 0x2000, LevelFive = 0x4000, ScrollLock = 0x8000; }; xkbcommon-libxkbcommon-54ee7ac/test/evdev-scancodes.h000066400000000000000000000402231510033435100230650ustar00rootroot00000000000000/* * Copyright (c) 1999-2002 Vojtech Pavlik * SPDX-License-Identifier: GPL-2.0-only */ #pragma once /* * Copied from /usr/include/linux/input.h from Linux 3.16, for use * in libxkbcommon. Modified to only contain scancode definitions. */ /* * Keys and buttons * * Most of the keys/buttons are modeled after USB HUT 1.12 * (see http://www.usb.org/developers/hidpage). * Abbreviations in the comments: * AC - Application Control * AL - Application Launch Button * SC - System Control */ #define KEY_RESERVED 0 #define KEY_ESC 1 #define KEY_1 2 #define KEY_2 3 #define KEY_3 4 #define KEY_4 5 #define KEY_5 6 #define KEY_6 7 #define KEY_7 8 #define KEY_8 9 #define KEY_9 10 #define KEY_0 11 #define KEY_MINUS 12 #define KEY_EQUAL 13 #define KEY_BACKSPACE 14 #define KEY_TAB 15 #define KEY_Q 16 #define KEY_W 17 #define KEY_E 18 #define KEY_R 19 #define KEY_T 20 #define KEY_Y 21 #define KEY_U 22 #define KEY_I 23 #define KEY_O 24 #define KEY_P 25 #define KEY_LEFTBRACE 26 #define KEY_RIGHTBRACE 27 #define KEY_ENTER 28 #define KEY_LEFTCTRL 29 #define KEY_A 30 #define KEY_S 31 #define KEY_D 32 #define KEY_F 33 #define KEY_G 34 #define KEY_H 35 #define KEY_J 36 #define KEY_K 37 #define KEY_L 38 #define KEY_SEMICOLON 39 #define KEY_APOSTROPHE 40 #define KEY_GRAVE 41 #define KEY_LEFTSHIFT 42 #define KEY_BACKSLASH 43 #define KEY_Z 44 #define KEY_X 45 #define KEY_C 46 #define KEY_V 47 #define KEY_B 48 #define KEY_N 49 #define KEY_M 50 #define KEY_COMMA 51 #define KEY_DOT 52 #define KEY_SLASH 53 #define KEY_RIGHTSHIFT 54 #define KEY_KPASTERISK 55 #define KEY_LEFTALT 56 #define KEY_SPACE 57 #define KEY_CAPSLOCK 58 #define KEY_F1 59 #define KEY_F2 60 #define KEY_F3 61 #define KEY_F4 62 #define KEY_F5 63 #define KEY_F6 64 #define KEY_F7 65 #define KEY_F8 66 #define KEY_F9 67 #define KEY_F10 68 #define KEY_NUMLOCK 69 #define KEY_SCROLLLOCK 70 #define KEY_KP7 71 #define KEY_KP8 72 #define KEY_KP9 73 #define KEY_KPMINUS 74 #define KEY_KP4 75 #define KEY_KP5 76 #define KEY_KP6 77 #define KEY_KPPLUS 78 #define KEY_KP1 79 #define KEY_KP2 80 #define KEY_KP3 81 #define KEY_KP0 82 #define KEY_KPDOT 83 #define KEY_ZENKAKUHANKAKU 85 #define KEY_102ND 86 #define KEY_F11 87 #define KEY_F12 88 #define KEY_RO 89 #define KEY_KATAKANA 90 #define KEY_HIRAGANA 91 #define KEY_HENKAN 92 #define KEY_KATAKANAHIRAGANA 93 #define KEY_MUHENKAN 94 #define KEY_KPJPCOMMA 95 #define KEY_KPENTER 96 #define KEY_RIGHTCTRL 97 #define KEY_KPSLASH 98 #define KEY_SYSRQ 99 #define KEY_RIGHTALT 100 #define KEY_LINEFEED 101 #define KEY_HOME 102 #define KEY_UP 103 #define KEY_PAGEUP 104 #define KEY_LEFT 105 #define KEY_RIGHT 106 #define KEY_END 107 #define KEY_DOWN 108 #define KEY_PAGEDOWN 109 #define KEY_INSERT 110 #define KEY_DELETE 111 #define KEY_MACRO 112 #define KEY_MUTE 113 #define KEY_VOLUMEDOWN 114 #define KEY_VOLUMEUP 115 #define KEY_POWER 116 /* SC System Power Down */ #define KEY_KPEQUAL 117 #define KEY_KPPLUSMINUS 118 #define KEY_PAUSE 119 #define KEY_SCALE 120 /* AL Compiz Scale (Expose) */ #define KEY_KPCOMMA 121 #define KEY_HANGEUL 122 #define KEY_HANGUEL KEY_HANGEUL #define KEY_HANJA 123 #define KEY_YEN 124 #define KEY_LEFTMETA 125 #define KEY_RIGHTMETA 126 #define KEY_COMPOSE 127 #define KEY_STOP 128 /* AC Stop */ #define KEY_AGAIN 129 #define KEY_PROPS 130 /* AC Properties */ #define KEY_UNDO 131 /* AC Undo */ #define KEY_FRONT 132 #define KEY_COPY 133 /* AC Copy */ #define KEY_OPEN 134 /* AC Open */ #define KEY_PASTE 135 /* AC Paste */ #define KEY_FIND 136 /* AC Search */ #define KEY_CUT 137 /* AC Cut */ #define KEY_HELP 138 /* AL Integrated Help Center */ #define KEY_MENU 139 /* Menu (show menu) */ #define KEY_CALC 140 /* AL Calculator */ #define KEY_SETUP 141 #define KEY_SLEEP 142 /* SC System Sleep */ #define KEY_WAKEUP 143 /* System Wake Up */ #define KEY_FILE 144 /* AL Local Machine Browser */ #define KEY_SENDFILE 145 #define KEY_DELETEFILE 146 #define KEY_XFER 147 #define KEY_PROG1 148 #define KEY_PROG2 149 #define KEY_WWW 150 /* AL Internet Browser */ #define KEY_MSDOS 151 #define KEY_COFFEE 152 /* AL Terminal Lock/Screensaver */ #define KEY_SCREENLOCK KEY_COFFEE #define KEY_DIRECTION 153 #define KEY_CYCLEWINDOWS 154 #define KEY_MAIL 155 #define KEY_BOOKMARKS 156 /* AC Bookmarks */ #define KEY_COMPUTER 157 #define KEY_BACK 158 /* AC Back */ #define KEY_FORWARD 159 /* AC Forward */ #define KEY_CLOSECD 160 #define KEY_EJECTCD 161 #define KEY_EJECTCLOSECD 162 #define KEY_NEXTSONG 163 #define KEY_PLAYPAUSE 164 #define KEY_PREVIOUSSONG 165 #define KEY_STOPCD 166 #define KEY_RECORD 167 #define KEY_REWIND 168 #define KEY_PHONE 169 /* Media Select Telephone */ #define KEY_ISO 170 #define KEY_CONFIG 171 /* AL Consumer Control Configuration */ #define KEY_HOMEPAGE 172 /* AC Home */ #define KEY_REFRESH 173 /* AC Refresh */ #define KEY_EXIT 174 /* AC Exit */ #define KEY_MOVE 175 #define KEY_EDIT 176 #define KEY_SCROLLUP 177 #define KEY_SCROLLDOWN 178 #define KEY_KPLEFTPAREN 179 #define KEY_KPRIGHTPAREN 180 #define KEY_NEW 181 /* AC New */ #define KEY_REDO 182 /* AC Redo/Repeat */ #define KEY_F13 183 #define KEY_F14 184 #define KEY_F15 185 #define KEY_F16 186 #define KEY_F17 187 #define KEY_F18 188 #define KEY_F19 189 #define KEY_F20 190 #define KEY_F21 191 #define KEY_F22 192 #define KEY_F23 193 #define KEY_F24 194 #define KEY_PLAYCD 200 #define KEY_PAUSECD 201 #define KEY_PROG3 202 #define KEY_PROG4 203 #define KEY_DASHBOARD 204 /* AL Dashboard */ #define KEY_SUSPEND 205 #define KEY_CLOSE 206 /* AC Close */ #define KEY_PLAY 207 #define KEY_FASTFORWARD 208 #define KEY_BASSBOOST 209 #define KEY_PRINT 210 /* AC Print */ #define KEY_HP 211 #define KEY_CAMERA 212 #define KEY_SOUND 213 #define KEY_QUESTION 214 #define KEY_EMAIL 215 #define KEY_CHAT 216 #define KEY_SEARCH 217 #define KEY_CONNECT 218 #define KEY_FINANCE 219 /* AL Checkbook/Finance */ #define KEY_SPORT 220 #define KEY_SHOP 221 #define KEY_ALTERASE 222 #define KEY_CANCEL 223 /* AC Cancel */ #define KEY_BRIGHTNESSDOWN 224 #define KEY_BRIGHTNESSUP 225 #define KEY_MEDIA 226 #define KEY_SWITCHVIDEOMODE 227 /* Cycle between available video outputs (Monitor/LCD/TV-out/etc) */ #define KEY_KBDILLUMTOGGLE 228 #define KEY_KBDILLUMDOWN 229 #define KEY_KBDILLUMUP 230 #define KEY_SEND 231 /* AC Send */ #define KEY_REPLY 232 /* AC Reply */ #define KEY_FORWARDMAIL 233 /* AC Forward Msg */ #define KEY_SAVE 234 /* AC Save */ #define KEY_DOCUMENTS 235 #define KEY_BATTERY 236 #define KEY_BLUETOOTH 237 #define KEY_WLAN 238 #define KEY_UWB 239 #define KEY_UNKNOWN 240 #define KEY_VIDEO_NEXT 241 /* drive next video source */ #define KEY_VIDEO_PREV 242 /* drive previous video source */ #define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */ #define KEY_BRIGHTNESS_ZERO 244 /* brightness off, use ambient */ #define KEY_DISPLAY_OFF 245 /* display device to off state */ #define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */ #define KEY_WIMAX KEY_WWAN #define KEY_RFKILL 247 /* Key that controls all radios */ #define KEY_MICMUTE 248 /* Mute / unmute the microphone */ /* Code 255 is reserved for special needs of AT keyboard driver */ #define BTN_MISC 0x100 #define BTN_0 0x100 #define BTN_1 0x101 #define BTN_2 0x102 #define BTN_3 0x103 #define BTN_4 0x104 #define BTN_5 0x105 #define BTN_6 0x106 #define BTN_7 0x107 #define BTN_8 0x108 #define BTN_9 0x109 #define BTN_MOUSE 0x110 #define BTN_LEFT 0x110 #define BTN_RIGHT 0x111 #define BTN_MIDDLE 0x112 #define BTN_SIDE 0x113 #define BTN_EXTRA 0x114 #define BTN_FORWARD 0x115 #define BTN_BACK 0x116 #define BTN_TASK 0x117 #define BTN_JOYSTICK 0x120 #define BTN_TRIGGER 0x120 #define BTN_THUMB 0x121 #define BTN_THUMB2 0x122 #define BTN_TOP 0x123 #define BTN_TOP2 0x124 #define BTN_PINKIE 0x125 #define BTN_BASE 0x126 #define BTN_BASE2 0x127 #define BTN_BASE3 0x128 #define BTN_BASE4 0x129 #define BTN_BASE5 0x12a #define BTN_BASE6 0x12b #define BTN_DEAD 0x12f #define BTN_GAMEPAD 0x130 #define BTN_SOUTH 0x130 #define BTN_A BTN_SOUTH #define BTN_EAST 0x131 #define BTN_B BTN_EAST #define BTN_C 0x132 #define BTN_NORTH 0x133 #define BTN_X BTN_NORTH #define BTN_WEST 0x134 #define BTN_Y BTN_WEST #define BTN_Z 0x135 #define BTN_TL 0x136 #define BTN_TR 0x137 #define BTN_TL2 0x138 #define BTN_TR2 0x139 #define BTN_SELECT 0x13a #define BTN_START 0x13b #define BTN_MODE 0x13c #define BTN_THUMBL 0x13d #define BTN_THUMBR 0x13e #define BTN_DIGI 0x140 #define BTN_TOOL_PEN 0x140 #define BTN_TOOL_RUBBER 0x141 #define BTN_TOOL_BRUSH 0x142 #define BTN_TOOL_PENCIL 0x143 #define BTN_TOOL_AIRBRUSH 0x144 #define BTN_TOOL_FINGER 0x145 #define BTN_TOOL_MOUSE 0x146 #define BTN_TOOL_LENS 0x147 #define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */ #define BTN_TOUCH 0x14a #define BTN_STYLUS 0x14b #define BTN_STYLUS2 0x14c #define BTN_TOOL_DOUBLETAP 0x14d #define BTN_TOOL_TRIPLETAP 0x14e #define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */ #define BTN_WHEEL 0x150 #define BTN_GEAR_DOWN 0x150 #define BTN_GEAR_UP 0x151 #define KEY_OK 0x160 #define KEY_SELECT 0x161 #define KEY_GOTO 0x162 #define KEY_CLEAR 0x163 #define KEY_POWER2 0x164 #define KEY_OPTION 0x165 #define KEY_INFO 0x166 /* AL OEM Features/Tips/Tutorial */ #define KEY_TIME 0x167 #define KEY_VENDOR 0x168 #define KEY_ARCHIVE 0x169 #define KEY_PROGRAM 0x16a /* Media Select Program Guide */ #define KEY_CHANNEL 0x16b #define KEY_FAVORITES 0x16c #define KEY_EPG 0x16d #define KEY_PVR 0x16e /* Media Select Home */ #define KEY_MHP 0x16f #define KEY_LANGUAGE 0x170 #define KEY_TITLE 0x171 #define KEY_SUBTITLE 0x172 #define KEY_ANGLE 0x173 #define KEY_ZOOM 0x174 #define KEY_MODE 0x175 #define KEY_KEYBOARD 0x176 #define KEY_SCREEN 0x177 #define KEY_PC 0x178 /* Media Select Computer */ #define KEY_TV 0x179 /* Media Select TV */ #define KEY_TV2 0x17a /* Media Select Cable */ #define KEY_VCR 0x17b /* Media Select VCR */ #define KEY_VCR2 0x17c /* VCR Plus */ #define KEY_SAT 0x17d /* Media Select Satellite */ #define KEY_SAT2 0x17e #define KEY_CD 0x17f /* Media Select CD */ #define KEY_TAPE 0x180 /* Media Select Tape */ #define KEY_RADIO 0x181 #define KEY_TUNER 0x182 /* Media Select Tuner */ #define KEY_PLAYER 0x183 #define KEY_TEXT 0x184 #define KEY_DVD 0x185 /* Media Select DVD */ #define KEY_AUX 0x186 #define KEY_MP3 0x187 #define KEY_AUDIO 0x188 /* AL Audio Browser */ #define KEY_VIDEO 0x189 /* AL Movie Browser */ #define KEY_DIRECTORY 0x18a #define KEY_LIST 0x18b #define KEY_MEMO 0x18c /* Media Select Messages */ #define KEY_CALENDAR 0x18d #define KEY_RED 0x18e #define KEY_GREEN 0x18f #define KEY_YELLOW 0x190 #define KEY_BLUE 0x191 #define KEY_CHANNELUP 0x192 /* Channel Increment */ #define KEY_CHANNELDOWN 0x193 /* Channel Decrement */ #define KEY_FIRST 0x194 #define KEY_LAST 0x195 /* Recall Last */ #define KEY_AB 0x196 #define KEY_NEXT 0x197 #define KEY_RESTART 0x198 #define KEY_SLOW 0x199 #define KEY_SHUFFLE 0x19a #define KEY_BREAK 0x19b #define KEY_PREVIOUS 0x19c #define KEY_DIGITS 0x19d #define KEY_TEEN 0x19e #define KEY_TWEN 0x19f #define KEY_VIDEOPHONE 0x1a0 /* Media Select Video Phone */ #define KEY_GAMES 0x1a1 /* Media Select Games */ #define KEY_ZOOMIN 0x1a2 /* AC Zoom In */ #define KEY_ZOOMOUT 0x1a3 /* AC Zoom Out */ #define KEY_ZOOMRESET 0x1a4 /* AC Zoom */ #define KEY_WORDPROCESSOR 0x1a5 /* AL Word Processor */ #define KEY_EDITOR 0x1a6 /* AL Text Editor */ #define KEY_SPREADSHEET 0x1a7 /* AL Spreadsheet */ #define KEY_GRAPHICSEDITOR 0x1a8 /* AL Graphics Editor */ #define KEY_PRESENTATION 0x1a9 /* AL Presentation App */ #define KEY_DATABASE 0x1aa /* AL Database App */ #define KEY_NEWS 0x1ab /* AL Newsreader */ #define KEY_VOICEMAIL 0x1ac /* AL Voicemail */ #define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */ #define KEY_MESSENGER 0x1ae /* AL Instant Messaging */ #define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ #define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */ #define KEY_LOGOFF 0x1b1 /* AL Logoff */ #define KEY_DOLLAR 0x1b2 #define KEY_EURO 0x1b3 #define KEY_FRAMEBACK 0x1b4 /* Consumer - transport controls */ #define KEY_FRAMEFORWARD 0x1b5 #define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */ #define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ #define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ #define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ #define KEY_IMAGES 0x1ba /* AL Image Browser */ #define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOS 0x1c1 #define KEY_INS_LINE 0x1c2 #define KEY_DEL_LINE 0x1c3 #define KEY_FN 0x1d0 #define KEY_FN_ESC 0x1d1 #define KEY_FN_F1 0x1d2 #define KEY_FN_F2 0x1d3 #define KEY_FN_F3 0x1d4 #define KEY_FN_F4 0x1d5 #define KEY_FN_F5 0x1d6 #define KEY_FN_F6 0x1d7 #define KEY_FN_F7 0x1d8 #define KEY_FN_F8 0x1d9 #define KEY_FN_F9 0x1da #define KEY_FN_F10 0x1db #define KEY_FN_F11 0x1dc #define KEY_FN_F12 0x1dd #define KEY_FN_1 0x1de #define KEY_FN_2 0x1df #define KEY_FN_D 0x1e0 #define KEY_FN_E 0x1e1 #define KEY_FN_F 0x1e2 #define KEY_FN_S 0x1e3 #define KEY_FN_B 0x1e4 #define KEY_BRL_DOT1 0x1f1 #define KEY_BRL_DOT2 0x1f2 #define KEY_BRL_DOT3 0x1f3 #define KEY_BRL_DOT4 0x1f4 #define KEY_BRL_DOT5 0x1f5 #define KEY_BRL_DOT6 0x1f6 #define KEY_BRL_DOT7 0x1f7 #define KEY_BRL_DOT8 0x1f8 #define KEY_BRL_DOT9 0x1f9 #define KEY_BRL_DOT10 0x1fa #define KEY_NUMERIC_0 0x200 /* used by phones, remote controls, */ #define KEY_NUMERIC_1 0x201 /* and other keypads */ #define KEY_NUMERIC_2 0x202 #define KEY_NUMERIC_3 0x203 #define KEY_NUMERIC_4 0x204 #define KEY_NUMERIC_5 0x205 #define KEY_NUMERIC_6 0x206 #define KEY_NUMERIC_7 0x207 #define KEY_NUMERIC_8 0x208 #define KEY_NUMERIC_9 0x209 #define KEY_NUMERIC_STAR 0x20a #define KEY_NUMERIC_POUND 0x20b #define KEY_CAMERA_FOCUS 0x210 #define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */ #define KEY_TOUCHPAD_TOGGLE 0x212 /* Request switch touchpad on or off */ #define KEY_TOUCHPAD_ON 0x213 #define KEY_TOUCHPAD_OFF 0x214 #define KEY_CAMERA_ZOOMIN 0x215 #define KEY_CAMERA_ZOOMOUT 0x216 #define KEY_CAMERA_UP 0x217 #define KEY_CAMERA_DOWN 0x218 #define KEY_CAMERA_LEFT 0x219 #define KEY_CAMERA_RIGHT 0x21a #define KEY_ATTENDANT_ON 0x21b #define KEY_ATTENDANT_OFF 0x21c #define KEY_ATTENDANT_TOGGLE 0x21d /* Attendant call on or off */ #define KEY_LIGHTS_TOGGLE 0x21e /* Reading light on or off */ #define BTN_DPAD_UP 0x220 #define BTN_DPAD_DOWN 0x221 #define BTN_DPAD_LEFT 0x222 #define BTN_DPAD_RIGHT 0x223 #define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ #define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY2 0x2c1 #define BTN_TRIGGER_HAPPY3 0x2c2 #define BTN_TRIGGER_HAPPY4 0x2c3 #define BTN_TRIGGER_HAPPY5 0x2c4 #define BTN_TRIGGER_HAPPY6 0x2c5 #define BTN_TRIGGER_HAPPY7 0x2c6 #define BTN_TRIGGER_HAPPY8 0x2c7 #define BTN_TRIGGER_HAPPY9 0x2c8 #define BTN_TRIGGER_HAPPY10 0x2c9 #define BTN_TRIGGER_HAPPY11 0x2ca #define BTN_TRIGGER_HAPPY12 0x2cb #define BTN_TRIGGER_HAPPY13 0x2cc #define BTN_TRIGGER_HAPPY14 0x2cd #define BTN_TRIGGER_HAPPY15 0x2ce #define BTN_TRIGGER_HAPPY16 0x2cf #define BTN_TRIGGER_HAPPY17 0x2d0 #define BTN_TRIGGER_HAPPY18 0x2d1 #define BTN_TRIGGER_HAPPY19 0x2d2 #define BTN_TRIGGER_HAPPY20 0x2d3 #define BTN_TRIGGER_HAPPY21 0x2d4 #define BTN_TRIGGER_HAPPY22 0x2d5 #define BTN_TRIGGER_HAPPY23 0x2d6 #define BTN_TRIGGER_HAPPY24 0x2d7 #define BTN_TRIGGER_HAPPY25 0x2d8 #define BTN_TRIGGER_HAPPY26 0x2d9 #define BTN_TRIGGER_HAPPY27 0x2da #define BTN_TRIGGER_HAPPY28 0x2db #define BTN_TRIGGER_HAPPY29 0x2dc #define BTN_TRIGGER_HAPPY30 0x2dd #define BTN_TRIGGER_HAPPY31 0x2de #define BTN_TRIGGER_HAPPY32 0x2df #define BTN_TRIGGER_HAPPY33 0x2e0 #define BTN_TRIGGER_HAPPY34 0x2e1 #define BTN_TRIGGER_HAPPY35 0x2e2 #define BTN_TRIGGER_HAPPY36 0x2e3 #define BTN_TRIGGER_HAPPY37 0x2e4 #define BTN_TRIGGER_HAPPY38 0x2e5 #define BTN_TRIGGER_HAPPY39 0x2e6 #define BTN_TRIGGER_HAPPY40 0x2e7 /* We avoid low common keys in module aliases so they don't get huge. */ #define KEY_MIN_INTERESTING KEY_MUTE #define KEY_MAX 0x2ff #define KEY_CNT (KEY_MAX+1) xkbcommon-libxkbcommon-54ee7ac/test/external_xkb_compilers.h000066400000000000000000000141411510033435100245570ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "darray.h" #define PIPE_WRITE 1 #define PIPE_READ 0 #define SETUP_FAILURE 99 int compile_with(const char* compiler_name, const char* const *compiler_argv, const char *keymap_in, size_t keymap_size_in, char **keymap_out, size_t *keymap_size_out); int compile_with(const char* compiler_name, const char* const *compiler_argv, const char *keymap_in, size_t keymap_size_in, char **keymap_out, size_t *keymap_size_out) { int ret = EXIT_FAILURE; assert(keymap_in); /* Prepare parameters */ char *envp[] = { NULL }; /* Prepare input */ int stdin_pipe[2] = {0}; int stdout_pipe[2] = {0}; posix_spawn_file_actions_t action; if (pipe(stdin_pipe) == -1) { perror("stdin pipe"); ret = SETUP_FAILURE; goto pipe_error; } if (posix_spawn_file_actions_init(&action)) { perror("spawn_file_actions_init error"); goto posix_spawn_file_actions_init_error; } /* Make spawned process close unused write-end of pipe, else it will not * receive EOF when write-end of the pipe is closed below and it will result * in a deadlock. */ if (posix_spawn_file_actions_addclose(&action, stdin_pipe[PIPE_WRITE])) goto posix_spawn_file_actions_error; /* Make spawned process replace stdin with read end of the pipe */ if (posix_spawn_file_actions_adddup2(&action, stdin_pipe[PIPE_READ], STDIN_FILENO)) goto posix_spawn_file_actions_error; /* Prepare stdout */ if (pipe(stdout_pipe) == -1) { perror("stdout pipe"); ret = SETUP_FAILURE; goto pipe_error; } if (posix_spawn_file_actions_addclose(&action, stdout_pipe[PIPE_READ])) goto posix_spawn_file_actions_error; if (posix_spawn_file_actions_adddup2(&action, stdout_pipe[PIPE_WRITE], STDOUT_FILENO)) goto posix_spawn_file_actions_error; /* Launch compiler */ pid_t compiler_pid; ret = posix_spawnp(&compiler_pid, compiler_name, &action, NULL, (char* const*)compiler_argv, envp); if (ret != 0) { errno = ret; perror("posix_spawnp XKB compiler failed"); goto posix_spawn_file_actions_init_error; } /* Close unused read-end of pipe */ close(stdin_pipe[PIPE_READ]); close(stdout_pipe[PIPE_WRITE]); ssize_t ret2 = write(stdin_pipe[PIPE_WRITE], keymap_in, keymap_size_in); /* Close write-end of the pipe, to emit EOF */ close(stdin_pipe[PIPE_WRITE]); if (ret2 == -1) { perror("Cannot write keymap to stdin"); kill(compiler_pid, SIGTERM); } /* Capture stdout */ const size_t buffer_size = 1024; darray_char stdout = darray_new(); darray_resize0(stdout, buffer_size); size_t size = 0; ssize_t count; while ((count = read(stdout_pipe[PIPE_READ], darray_items(stdout) + size, buffer_size)) > 0) { size += (size_t) count; darray_resize0(stdout, size + buffer_size); } close(stdout_pipe[PIPE_READ]); /* Ensure we get a NULL-terminated string */ if (size > 0 && darray_item(stdout, size - 1) != '\0') darray_resize0(stdout, size + 1); darray_steal(stdout, keymap_out, NULL); *keymap_size_out = size; /* Wait for compiler to complete */ int status; ret = waitpid(compiler_pid, &status, 0); ret = (ret < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) ? SETUP_FAILURE : EXIT_SUCCESS; goto cleanup; posix_spawn_file_actions_error: perror("posix_spawn_file_actions_* error"); posix_spawn_file_actions_init_error: close(stdin_pipe[PIPE_WRITE]); close(stdin_pipe[PIPE_READ]); close(stdout_pipe[PIPE_READ]); close(stdout_pipe[PIPE_WRITE]); ret = SETUP_FAILURE; cleanup: posix_spawn_file_actions_destroy(&action); pipe_error: return ret; } int compile_with_xkbcomp(const char* display, const char *include_path, const char *keymap_in, size_t keymap_size_in, char **keymap_out, size_t *keymap_size_out); int compile_with_xkbcomp(const char* display, const char *include_path, const char *keymap_in, size_t keymap_size_in, char **keymap_out, size_t *keymap_size_out) { const bool has_display = !isempty(display); const char* const out = (has_display) ? display : "-"; /* Prepare xkbcomp parameters */ char include_path_arg[PATH_MAX+2] = "-I"; const char *xkbcomp_argv[] = { "xkbcomp", "-I" /* reset include path*/, include_path_arg, "-opt", "g", "-w", "10", "-xkb", "-" /* stdin */, out, NULL }; if (include_path) { int ret = snprintf(include_path_arg, ARRAY_SIZE(include_path_arg), "-I%s", include_path); if (ret < 0 || ret >= (int)ARRAY_SIZE(include_path_arg)) { return SETUP_FAILURE; } } return compile_with("xkbcomp", xkbcomp_argv, keymap_in, keymap_size_in, keymap_out, keymap_size_out); } int compile_with_kbvm(const char *include_path, const char *keymap_in, size_t keymap_size_in, char **keymap_out, size_t *keymap_size_out); int compile_with_kbvm(const char *include_path, const char *keymap_in, size_t keymap_size_in, char **keymap_out, size_t *keymap_size_out) { /* Prepare xkbcomp parameters */ const char *kbvm_argv[] = { "kbvm", "compile-xkb", "-", NULL, NULL, NULL, NULL }; if (include_path) { kbvm_argv[3] = "--no-default-includes"; kbvm_argv[4] = "--append-include"; kbvm_argv[5] = include_path; } return compile_with("kbvm", kbvm_argv, keymap_in, keymap_size_in, keymap_out, keymap_size_out); } xkbcommon-libxkbcommon-54ee7ac/test/filecomp.c000066400000000000000000000035371510033435100216140ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #include "config.h" #include "test.h" #include "xkbcommon/xkbcommon.h" static int test_file(struct xkb_context *ctx, const char *path_rel) { struct xkb_keymap *keymap = test_compile_file( ctx, XKB_KEYMAP_FORMAT_TEXT_V1, path_rel); if (!keymap) return 0; xkb_keymap_unref(keymap); return 1; } int main(void) { test_init(); struct xkb_context *ctx = test_get_context(0); assert(test_file(ctx, "keymaps/basic.xkb")); assert(test_file(ctx, "keymaps/comprehensive-plus-geom.xkb")); assert(test_file(ctx, "keymaps/no-types.xkb")); assert(test_file(ctx, "keymaps/quartz.xkb")); assert(test_file(ctx, "keymaps/no-aliases.xkb")); assert(test_file(ctx, "keymaps/modmap-none.xkb")); assert(test_file(ctx, "keymaps/invalid-escape-sequence.xkb")); assert(!test_file(ctx, "keymaps/divide-by-zero.xkb")); assert(!test_file(ctx, "keymaps/syntax-error.xkb")); assert(!test_file(ctx, "keymaps/syntax-error2.xkb")); assert(!test_file(ctx, "keymaps/empty-symbol-decl.xkb")); assert(!test_file(ctx, "keymaps/invalid-qualified-type-field.xkb")); assert(!test_file(ctx, "keymaps/invalid-qualified-symbols-field.xkb")); assert(!test_file(ctx, "does not exist")); /* Test response to invalid flags and formats. */ fclose(stdin); assert(!xkb_keymap_new_from_file(ctx, NULL, XKB_KEYMAP_FORMAT_TEXT_V1, 0)); assert(!xkb_keymap_new_from_file(ctx, stdin, 0, 0)); assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_USE_ORIGINAL_FORMAT, 0)); assert(!xkb_keymap_new_from_file(ctx, stdin, 1234, 0)); assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_FORMAT_TEXT_V1, -1)); assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_FORMAT_TEXT_V1, 1234)); xkb_context_unref(ctx); return 0; } xkbcommon-libxkbcommon-54ee7ac/test/introspection.c000066400000000000000000000500171510033435100227110ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "darray.h" #include "utils-paths.h" #include "xkbcommon/xkbcommon.h" #include "src/xkbcomp/keymap-file-iterator.h" #include "src/xkbcomp/ast.h" #include "test.h" #include "utils.h" struct file_include_test_data { bool valid:1; bool explicit_section:1; enum merge_mode merge; const char *path; /* relative to test data */ const char *file; const char *section; const char *modifier; enum xkb_map_flags flags; }; struct section_test_data { const char *name; enum xkb_file_type file_type; enum xkb_map_flags flags; struct xkb_file_include_group include_groups[3]; struct file_include_test_data includes[3]; darray_size_t num_include_groups; darray_size_t num_includes; }; static void test_resolve_file(struct xkb_context *ctx) { char *path; char resolved_path[PATH_MAX] = {0}; char resolved_section[1024] = {0}; FILE *file; /* Invalid paths */ static const char invalid[] = "---invalid---"; path = test_get_path(invalid); assert(path); assert(is_absolute_path(path)); const char * paths[] = { path, invalid }; static const char * sections[] = { NULL, "invalid" }; /* Note: inferior or equal to _FILE_TYPE_NUM_ENTRIES is correct here */ for (enum xkb_file_type t = 0; t <= _FILE_TYPE_NUM_ENTRIES; t++) { for (size_t p = 0; p < ARRAY_SIZE(paths); p++) { for (size_t s = 0; s < ARRAY_SIZE(sections); s++) { file = xkb_resolve_file(ctx, t, paths[p], sections[s], resolved_path, sizeof(resolved_path), resolved_section, sizeof(resolved_section)); assert(!file); } } } free(path); /* Valid absolute path */ path = test_get_path("types/numpad"); assert(path); assert(is_absolute_path(path)); const struct { const char *path; const char *section; const char *resolved_path; const char *resolved_section; enum xkb_file_type type; bool failure; } tests[] = { /* Absolute path */ { .failure = false, .path = path, .section = NULL, .type = FILE_TYPE_INVALID, .resolved_path = path, .resolved_section = "pc" /* default */ }, { .failure = false, .path = path, .section = "shift3", .type = FILE_TYPE_INVALID, .resolved_path = path, .resolved_section = "shift3" /* non-default */ }, { .failure = true, .path = path, .section = NULL, .type = FILE_TYPE_SYMBOLS, /* invalid type */ .resolved_path = NULL, .resolved_section = NULL }, { .failure = false, .path = path, .section = NULL, .type = FILE_TYPE_TYPES, /* valid type */ .resolved_path = path, .resolved_section = "pc" /* default */ }, { .failure = false, .path = path, .section = "shift3", .type = FILE_TYPE_TYPES, /* valid type */ .resolved_path = path, .resolved_section = "shift3" /* non default */ }, /* Relative path */ { .failure = true, .path = "numpad", .section = NULL, .type = FILE_TYPE_INVALID, /* type required */ .resolved_path = NULL, .resolved_section = NULL }, { .failure = true, .path = "numpad", .section = "shift3", .type = FILE_TYPE_INVALID, /* type required */ .resolved_path = NULL, .resolved_section = NULL }, { .failure = true, .path = "numpad", .section = NULL, .type = FILE_TYPE_KEYCODES, /* invalid type */ .resolved_path = NULL, .resolved_section = NULL }, { .failure = false, .path = "numpad", .section = NULL, .type = FILE_TYPE_TYPES, /* valid type */ .resolved_path = path, .resolved_section = "pc" /* default */ }, { .failure = false, .path = "numpad", .section = "shift3", .type = FILE_TYPE_TYPES, /* valid type */ .resolved_path = path, .resolved_section = "shift3" /* non default */ }, }; for (size_t t = 0; t < ARRAY_SIZE(tests); t++) { fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, t); file = xkb_resolve_file(ctx, tests[t].type, tests[t].path, tests[t].section, resolved_path, sizeof(resolved_path), resolved_section, sizeof(resolved_section)); if (tests[t].failure) { assert(!file); } else { assert(file); assert_streq_not_null("resolved path", resolved_path, tests[t].resolved_path); assert_streq_not_null("resolved section", resolved_section, tests[t].resolved_section); } } free(path); } static bool test_section(const struct section_test_data *data, const struct xkb_file_section *section) { assert(section->file_type == data->file_type); assert_streq_not_null("", data->name, xkb_file_section_get_string(section, section->name)); assert_eq("Section flags", data->flags, section->flags, "%#x"); assert_eq("Num include groups", data->num_include_groups, darray_size(section->include_groups), "%u"); assert_eq("Num includes", data->num_includes, darray_size(section->includes), "%u"); for (darray_size_t k = 0; k < data->num_include_groups; k++) { fprintf(stderr, "... %s: include group #%u ...\n", __func__, k); const struct xkb_file_include_group * const expected = &data->include_groups[k]; const struct xkb_file_include_group * const got = &darray_item(section->include_groups, k); assert_eq("Start", expected->start, got->start, "%d"); assert_eq("End", expected->end, got->end, "%d"); } for (darray_size_t k = 0; k < data->num_includes; k++) { fprintf(stderr, "... %s: include #%u ...\n", __func__, k); const struct file_include_test_data * const expected = &data->includes[k]; const struct xkb_file_include * const got = &darray_item(section->includes, k); assert_eq("Valid", expected->valid, got->valid, "%d"); assert_eq("Merge mode", expected->merge, got->merge, "%d"); char *path = test_get_path(expected->path); assert(path); assert_streq_not_null("File", path, xkb_file_section_get_string(section, got->path)); free(path); assert_streq_not_null("File", expected->file, xkb_file_section_get_string(section, got->file)); assert_streq_not_null("Section", expected->section, xkb_file_section_get_string(section, got->section)); assert_eq("Explicit section", expected->explicit_section, got->explicit_section, "%d"); assert_streq_not_null("Modifier", expected->modifier, xkb_file_section_get_string(section, got->modifier)); assert_eq("Section flags", expected->flags, got->flags, "%#x"); } return true; } static void test_file_section_parse(struct xkb_context *ctx) { char *path = test_get_path("symbols/pc"); assert(path); struct xkb_file_section section = {0}; struct section_test_data tests[] = { { .name = "editing", .file_type = FILE_TYPE_SYMBOLS, .flags = MAP_IS_HIDDEN | MAP_IS_PARTIAL | MAP_HAS_ALPHANUMERIC, .includes = {}, .num_includes = 0 }, { .name = "pc105", .file_type = FILE_TYPE_SYMBOLS, .flags = MAP_IS_DEFAULT | MAP_IS_PARTIAL | MAP_HAS_ALPHANUMERIC | MAP_HAS_MODIFIER, .num_include_groups = 1, .include_groups = { { .start = 0, .end = 0 }, }, .num_includes = 1, .includes = { { .valid = true, .merge = MERGE_DEFAULT, .path = "symbols/pc", .file = "pc", .section = "pc105-pure-virtual-modifiers", .explicit_section = true, .modifier = "", .flags = 0 } }, }, { .name = "pc105-pure-virtual-modifiers", .file_type = FILE_TYPE_SYMBOLS, .flags = 0, .num_include_groups = 3, .include_groups = { { .start = 0, .end = 0 }, { .start = 1, .end = 1 }, { .start = 2, .end = 2 }, }, .num_includes = 3, .includes = { { .valid = true, .merge = MERGE_DEFAULT, .path = "symbols/srvr_ctrl", .file = "srvr_ctrl", .section = "fkey2vt", .explicit_section = true, .modifier = "", .flags = MAP_IS_PARTIAL | MAP_HAS_FN, }, { .valid = true, .merge = MERGE_DEFAULT, .path = "symbols/pc", .file = "pc", .section = "editing", .explicit_section = true, .modifier = "", .flags = MAP_IS_HIDDEN | MAP_IS_PARTIAL | MAP_HAS_ALPHANUMERIC, }, { .valid = true, .merge = MERGE_DEFAULT, .path = "symbols/keypad", .file = "keypad", .section = "x11", .explicit_section = true, .modifier = "", .flags = MAP_IS_DEFAULT | MAP_IS_HIDDEN | MAP_IS_PARTIAL | MAP_HAS_KEYPAD, } }, } }; for (size_t k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, k); xkb_file_section_init(§ion); const bool is_default = tests[k].flags & MAP_IS_DEFAULT; assert(xkb_file_section_parse( ctx, XKB_FILE_ITERATOR_FAIL_ON_INCLUDE_ERROR, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS, 0, path, (is_default ? NULL : tests[k].name), §ion )); test_section(&tests[k], §ion); xkb_file_section_free(§ion); } free(path); } struct iterator_test_data { const char *string; const char *map; struct section_test_data sections[3]; unsigned int num_sections; bool error; }; static void test_file_iterator(struct xkb_context *ctx) { static const struct iterator_test_data tests[] = { { .string = "", .map = NULL, .num_sections = 0, .sections = {}, .error = false, }, { .string = "xkb_symbols \"1\" {};", .map = NULL, .num_sections = 1, .sections = { { .name = "1", .file_type = FILE_TYPE_SYMBOLS, .flags = 0, .includes = {}, .num_includes = 0, } }, .error = false, }, { .string = "xkb_symbols \"1\" {\n" " include \"pc\"\n" " replace \"+de:1|cz:2\"\n" "};", .map = NULL, .num_sections = 1, .sections = { { .name = "1", .file_type = FILE_TYPE_SYMBOLS, .flags = 0, .num_include_groups = 2, .include_groups = { { .start = 0, .end = 0 }, { .start = 1, .end = 2 }, }, .num_includes = 3, .includes = { { .valid = true, .merge = MERGE_DEFAULT, .path = "symbols/pc", .file = "pc", .section = "pc105", .explicit_section = false, .modifier = "", .flags = MAP_IS_DEFAULT | MAP_IS_PARTIAL | MAP_HAS_ALPHANUMERIC | MAP_HAS_MODIFIER, }, { .valid = true, /* First include uses the merge mode of the statement */ .merge = MERGE_REPLACE, .path = "symbols/de", .file = "de", .section = "basic", .explicit_section = false, .modifier = "1", .flags = MAP_IS_DEFAULT }, { .valid = true, .merge = MERGE_AUGMENT, .path = "symbols/cz", .file = "cz", .section = "basic", .explicit_section = false, .modifier = "2", .flags = MAP_IS_DEFAULT | MAP_IS_PARTIAL | MAP_HAS_ALPHANUMERIC, } }, } }, .error = false, }, { .string = "xkb_symbols \"1\" {};\n" "xkb_symbols \"2\" {};\n", .map = NULL, .num_sections = 2, .sections = { { .name = "1", .file_type = FILE_TYPE_SYMBOLS, .flags = 0, .num_include_groups = 0, .include_groups = {}, .num_includes = 0, .includes = {}, }, { .name = "2", .file_type = FILE_TYPE_SYMBOLS, .flags = 0, .num_include_groups = 0, .include_groups = {}, .num_includes = 0, .includes = {}, }, }, .error = false, }, { .string = "xkb_keymap \"1\" {\n" " xkb_types \"2\" {};\n" " xkb_symbols \"3\" {};\n" "};", .map = NULL, .num_sections = 3, .sections = { { .name = "1", .file_type = FILE_TYPE_KEYMAP, .flags = 0, .num_include_groups = 0, .include_groups = {}, .num_includes = 0, .includes = {}, }, { .name = "2", .file_type = FILE_TYPE_TYPES, .flags = 0, .num_include_groups = 0, .include_groups = {}, .num_includes = 0, .includes = {}, }, { .name = "3", .file_type = FILE_TYPE_SYMBOLS, .flags = 0, .num_include_groups = 0, .include_groups = {}, .num_includes = 0, .includes = {}, }, }, .error = false, }, { .string = "xkb_keymap \"10\" {\n" " xkb_types \"11\" {};\n" " xkb_symbols \"12\" {};\n" "};\n" "default xkb_keymap \"20\" {\n" " xkb_types \"21\" {};\n" " xkb_symbols \"22\" {};\n" "};", .map = NULL, .sections = {}, .num_sections = 0, .error = true, // TODO: enable multiple keymap per file // .num_sections = 6, // .sections = { // { // .path = NULL, // .name = "10", // .file_type = FILE_TYPE_KEYMAP, // .flags = 0, // .includes = {}, // .num_include = 0 // }, // { // .path = NULL, // .name = "11", // .file_type = FILE_TYPE_TYPES, // .flags = 0, // .includes = {}, // .num_include = 0 // }, // { // .path = NULL, // .name = "12", // .file_type = FILE_TYPE_SYMBOLS, // .flags = 0, // .includes = {}, // .num_include = 0 // }, // { // .path = NULL, // .name = "20", // .file_type = FILE_TYPE_KEYMAP, // .flags = MAP_IS_DEFAULT, // .includes = {}, // .num_include = 0 // }, // { // .path = NULL, // .name = "21", // .file_type = FILE_TYPE_TYPES, // .flags = 0, // .includes = {}, // .num_include = 0 // }, // { // .path = NULL, // .name = "22", // .file_type = FILE_TYPE_SYMBOLS, // .flags = 0, // .includes = {}, // .num_include = 0 // }, // }, // .error = false, }, }; for (size_t k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, k); struct xkb_file_iterator * const iter = xkb_file_iterator_new_from_buffer( ctx, XKB_FILE_ITERATOR_FAIL_ON_INCLUDE_ERROR, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_COMPILE_NO_FLAGS, "(string)", tests[k].map, FILE_TYPE_INVALID, tests[k].string, strlen(tests[k].string) ); assert(iter); const struct xkb_file_section *section; unsigned int s = 0; bool ok = true; while ((ok = xkb_file_iterator_next(iter, §ion)) && section) { fprintf(stderr, "section #%u\n", s); if (s >= tests[k].num_sections) { assert_eq("Section count", tests[k].num_sections, s, "%u"); break; } assert(test_section(&tests[k].sections[s], section)); s++; } assert_eq("Error", tests[k].error, !ok, "%d"); assert_eq("Section count", tests[k].num_sections, s, "%u"); xkb_file_iterator_free(iter); } } int main(void) { test_init(); struct xkb_context * const context = test_get_context(CONTEXT_NO_FLAG); test_resolve_file(context); test_file_section_parse(context); test_file_iterator(context); xkb_context_unref(context); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/keymap.c000066400000000000000000000707551510033435100213120ustar00rootroot00000000000000/* * Copyright © 2016 Intel Corporation * SPDX-License-Identifier: MIT * * Author: Mike Blumenkrantz */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-keysyms.h" #include "evdev-scancodes.h" #include "test.h" #include "context.h" #include "keymap.h" #include "keymap-formats.h" #include "utils.h" #define KEY_LVL3 84 #define KEY_LVL5 195 static void test_supported_formats(void) { assert(xkb_keymap_parse_format(NULL) == 0); assert(xkb_keymap_parse_format("") == 0); assert(xkb_keymap_parse_format("x") == 0); assert(xkb_keymap_parse_format("v") == 0); assert(xkb_keymap_parse_format("vx") == 0); assert(xkb_keymap_parse_format("0x1") == 0); /* only base 10 */ assert(xkb_keymap_parse_format("+1") == XKB_KEYMAP_FORMAT_TEXT_V1); assert(xkb_keymap_parse_format(" 1") == XKB_KEYMAP_FORMAT_TEXT_V1); const struct { int value; enum xkb_keymap_format expected; const char* const* labels; } entries[] = { { .value = -1 , .labels = NULL, .expected = 0 }, { .value = 0 , .labels = NULL, .expected = 0 }, { .value = 100000000 , .labels = NULL, .expected = 0 }, { .value = XKB_KEYMAP_USE_ORIGINAL_FORMAT, .labels = NULL, .expected = 0 }, { .value = XKB_KEYMAP_FORMAT_TEXT_V1, .labels = (const char* const[]) { "v1", NULL }, .expected = XKB_KEYMAP_FORMAT_TEXT_V1 }, { .value = XKB_KEYMAP_FORMAT_TEXT_V2, .labels = (const char* const[]) { "v2", NULL }, .expected = XKB_KEYMAP_FORMAT_TEXT_V2 }, }; char buf[15] = { 0 }; for (size_t k = 0; k < ARRAY_SIZE(entries); k++) { assert(xkb_keymap_is_supported_format(entries[k].value) == !!entries[k].expected); /* Parse labels */ for (size_t l = 0; entries[k].labels && entries[k].labels[l]; l++) { assert_printf(xkb_keymap_parse_format(entries[k].labels[l]) == entries[k].expected, "%s: expected %d, got: %d\n", entries[k].labels[l], entries[k].value, xkb_keymap_parse_format(entries[k].labels[l])); } /* Parse serialized numeric value */ const int ret = snprintf(buf, sizeof(buf), "%d", entries[k].value); assert(ret > 0 && ret < (int) sizeof(buf)); assert(xkb_keymap_parse_format(buf) == entries[k].expected); } const enum xkb_keymap_format *formats; const size_t count = xkb_keymap_supported_formats(&formats); assert(count == 2); enum xkb_keymap_format previous = 0; /* Lower bound */ for (size_t k = 0; k < count; k++) { /* Ascending order */ assert(previous < formats[k]); /* Valid numeric format */ assert(xkb_keymap_is_supported_format(formats[k])); /* Valid label */ const int ret = snprintf(buf, sizeof(buf), "%d", formats[k]); assert(ret > 0 && ret < (int) sizeof(buf)); assert(xkb_keymap_parse_format(buf) == formats[k]); previous = formats[k]; } } static void test_garbage_key(void) { struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); struct xkb_keymap *keymap; xkb_keycode_t kc; int nsyms; const xkb_keysym_t *syms; const xkb_layout_index_t first_layout = 0; xkb_level_index_t nlevels; assert(context); keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, NULL, NULL, "garbage", NULL, NULL); assert(keymap); /* TLDE uses the 'us' sym on the first level and is thus [grave, exclam] */ kc = xkb_keymap_key_by_name(keymap, "TLDE"); assert(kc != XKB_KEYCODE_INVALID); nlevels = xkb_keymap_num_levels_for_key(keymap, kc, first_layout); assert(nlevels == 2); nsyms = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &syms); assert(nsyms == 1); assert(*syms == XKB_KEY_grave); /* fallback from 'us' */ nsyms = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &syms); assert(nsyms == 1); assert(*syms == XKB_KEY_exclam); /* AE13 has no 'us' fallback and ends up as [NoSymbol, asciitilde] */ kc = xkb_keymap_key_by_name(keymap, "AE13"); assert(kc != XKB_KEYCODE_INVALID); nlevels = xkb_keymap_num_levels_for_key(keymap, kc, first_layout); assert(nlevels == 2); nsyms = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &syms); assert(nsyms == 0); nsyms = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &syms); assert(nsyms == 1); assert(*syms == XKB_KEY_asciitilde); xkb_keymap_unref(keymap); xkb_context_unref(context); } static void test_keymap(void) { struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); struct xkb_keymap *keymap; xkb_keycode_t kc; const char *keyname; xkb_mod_mask_t masks_out[4] = { 0, 0, 0, 0 }; size_t mask_count; xkb_mod_mask_t shift_mask; xkb_mod_mask_t lock_mask; xkb_mod_mask_t mod2_mask; assert(context); keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "us,ru", NULL, "grp:menu_toggle"); assert(keymap); kc = xkb_keymap_key_by_name(keymap, "AE09"); assert(kc != XKB_KEYCODE_INVALID); keyname = xkb_keymap_key_get_name(keymap, kc); assert(streq(keyname, "AE09")); kc = xkb_keymap_key_by_name(keymap, "COMP"); assert(kc != XKB_KEYCODE_INVALID); keyname = xkb_keymap_key_get_name(keymap, kc); assert(streq(keyname, "COMP")); kc = xkb_keymap_key_by_name(keymap, "MENU"); assert(kc != XKB_KEYCODE_INVALID); keyname = xkb_keymap_key_get_name(keymap, kc); assert(streq(keyname, "COMP")); kc = xkb_keymap_key_by_name(keymap, "AC01"); assert(kc != XKB_KEYCODE_INVALID); // AC01 level 0 ('a') requires no modifiers on us-pc104 mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 0, masks_out, 4); assert(mask_count == 1); assert(masks_out[0] == 0); shift_mask = UINT32_C(1) << xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); lock_mask = UINT32_C(1) << xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); mod2_mask = UINT32_C(1) << xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD2); // AC01 level 1 ('A') requires either Shift or Lock modifiers on us-pc104 mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 1, masks_out, 4); assert(mask_count == 2); assert(masks_out[0] == shift_mask); assert(masks_out[1] == lock_mask); kc = xkb_keymap_key_by_name(keymap, "KP1"); // KP1 level 0 ('End') requires no modifiers or Shift+Mod2 on us-pc104 mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 0, masks_out, 4); assert(mask_count == 2); assert(masks_out[0] == 0); assert(masks_out[1] == (shift_mask | mod2_mask)); // KP1 level 1 ('1') requires either Shift or Mod2 modifiers on us-pc104 mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 1, masks_out, 4); assert(mask_count == 2); assert(masks_out[0] == shift_mask); assert(masks_out[1] == mod2_mask); // Return key is not affected by modifiers on us-pc104 kc = xkb_keymap_key_by_name(keymap, "RTRN"); mask_count = xkb_keymap_key_get_mods_for_level(keymap, kc, 0, 0, masks_out, 4); assert(mask_count == 1); assert(masks_out[0] == 0); xkb_keymap_unref(keymap); xkb_context_unref(context); } static void test_no_extra_groups(void) { struct xkb_keymap *keymap; xkb_keycode_t kc; const xkb_keysym_t *syms; struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); assert(context); /* RMLVO: Legacy rules may add more layouts than the input RMLVO */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "multiple-groups", "old", "de", NULL, NULL); assert(keymap); kc = xkb_keymap_key_by_name(keymap, "AD01"); assert(kc != XKB_KEYCODE_INVALID); /* 2 layouts, while only 1 was provided */ assert(xkb_keymap_num_layouts_for_key(keymap, kc) == 2); assert(xkb_keymap_num_layouts(keymap) == 2); xkb_keymap_unref(keymap); /* RMLVO: “one group per key” in symbols sections */ const char *layouts[] = {"us", "us,us", "us,us,us", "us,us,us,us"}; for (xkb_layout_index_t k = 0; k < ARRAY_SIZE(layouts); k++) { /* `multiple-groups` option defines 4 groups for a key */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "multiple-groups", NULL, layouts[k], NULL, "multiple-groups"); assert(keymap); kc = xkb_keymap_key_by_name(keymap, "RALT"); assert(kc != XKB_KEYCODE_INVALID); /* Groups after the first one should be dropped */ assert(xkb_keymap_num_layouts_for_key(keymap, kc) == 1); /* Here we expect RMLVO layouts count = keymap layouts count */ assert(xkb_keymap_num_layouts(keymap) == k + 1); for (xkb_layout_index_t l = 0; l <= k; l++) { assert(xkb_keymap_key_get_syms_by_level(keymap, kc, l, 0, &syms) == 1); assert(syms[0] == XKB_KEY_a); syms = NULL; } xkb_keymap_unref(keymap); } /* RMLVO: Ensure the rule “one group per key” in symbols sections works * for the 2nd layout */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, NULL, NULL, "multiple-groups,multiple-groups", "1,2", NULL); assert(keymap); kc = xkb_keymap_key_by_name(keymap, "RALT"); assert(kc != XKB_KEYCODE_INVALID); assert(xkb_keymap_num_layouts_for_key(keymap, kc) == 2); assert(xkb_keymap_num_layouts(keymap) == 2); for (xkb_layout_index_t l = 0; l < 2; l++) { assert(xkb_keymap_key_get_syms_by_level(keymap, kc, l, 0, &syms) == 1); assert(syms[0] == XKB_KEY_a); syms = NULL; } xkb_keymap_unref(keymap); /* Same configuration as previous, but without using RMLVO resolution: * We do accept more than one group per key in symbols sections, but only * when not using a modifier: the second layout (`:2`) will have its extra * groups dropped. */ const char keymap_str[] = "xkb_keymap {" " xkb_keycodes { include \"evdev+aliases(qwerty)\" };" " xkb_types { include \"complete\" };" " xkb_compat { include \"complete\" };" " xkb_symbols { include \"pc+multiple-groups(1)+multiple-groups(2):2" "+inet(evdev)\" };" "};"; keymap = test_compile_string(context, XKB_KEYMAP_FORMAT_TEXT_V1, keymap_str); kc = xkb_keymap_key_by_name(keymap, "RALT"); assert(kc != XKB_KEYCODE_INVALID); assert(xkb_keymap_num_layouts_for_key(keymap, kc) == 4); assert(xkb_keymap_num_layouts(keymap) == 4); xkb_keysym_t ref_syms[] = { XKB_KEY_a, XKB_KEY_a, XKB_KEY_c, XKB_KEY_d }; for (xkb_layout_index_t l = 0; l < 4; l++) { assert(xkb_keymap_key_get_syms_by_level(keymap, kc, l, 0, &syms) == 1); assert(syms[0] == ref_syms[l]); syms = NULL; } xkb_keymap_unref(keymap); xkb_context_unref(context); } #define Mod1Mask (UINT32_C(1) << 3) #define Mod2Mask (UINT32_C(1) << 4) #define Mod3Mask (UINT32_C(1) << 5) static void test_numeric_keysyms(void) { struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); struct xkb_keymap *keymap; const struct xkb_key *key; xkb_keycode_t kc; int keysyms_count; const xkb_layout_index_t first_layout = 0; const xkb_keysym_t *keysyms; assert(context); keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "numeric_keysyms", NULL, NULL); assert(keymap); kc = xkb_keymap_key_by_name(keymap, "AD01"); keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms); assert(keysyms_count == 1); assert(keysyms[0] == 0x1ffffffd); key = XkbKey(keymap, kc); assert(key->modmap == Mod1Mask); kc = xkb_keymap_key_by_name(keymap, "AD02"); keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms); assert(keysyms_count == 1); assert(keysyms[0] == 0x1ffffffe); key = XkbKey(keymap, kc); assert(key->modmap == Mod2Mask); kc = xkb_keymap_key_by_name(keymap, "AD03"); keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms); assert(keysyms_count == 1); assert(keysyms[0] == 0x1fffffff); /* Invalid numeric keysym */ keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &keysyms); assert(keysyms_count == 0); key = XkbKey(keymap, kc); assert(key->modmap == Mod3Mask); xkb_keymap_unref(keymap); xkb_context_unref(context); } static void test_multiple_keysyms_per_level(void) { struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); struct xkb_keymap *keymap; xkb_keycode_t kc; int keysyms_count; const xkb_layout_index_t first_layout = 0; const xkb_keysym_t *keysyms; assert(context); keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "awesome", NULL, NULL); assert(keymap); kc = xkb_keymap_key_by_name(keymap, "AD01"); keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms); assert(keysyms_count == 3); assert(keysyms[0] == 'q'); assert(keysyms[1] == 'a'); assert(keysyms[2] == 'b'); kc = xkb_keymap_key_by_name(keymap, "AD03"); keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &keysyms); assert(keysyms_count == 2); assert(keysyms[0] == 'E'); assert(keysyms[1] == 'F'); // Invalid keysyms kc = xkb_keymap_key_by_name(keymap, "AD06"); // Only the invalid keysym is dropped, remaining one overrides previous entry keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms); assert(keysyms_count == 1); assert(keysyms[0] == XKB_KEY_ydiaeresis); // All the keysyms are invalid and dropped, previous entry not overriden keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 1, &keysyms); assert(keysyms_count == 1); assert(keysyms[0] == 'Y'); xkb_keymap_unref(keymap); xkb_context_unref(context); } static void test_multiple_actions_per_level(void) { struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); struct xkb_keymap *keymap; struct xkb_state *state; xkb_keycode_t kc; int keysyms_count; const xkb_layout_index_t first_layout = 0; const xkb_keysym_t *keysyms; xkb_mod_index_t ctrl, level3; xkb_layout_index_t layout; xkb_mod_mask_t base_mods; assert(context); /* Test various ways to set multiple actions */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "multiple_actions,cz", NULL, NULL); assert(keymap); kc = xkb_keymap_key_by_name(keymap, "LCTL"); keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms); assert(keysyms_count == 2); assert(keysyms[0] == XKB_KEY_Control_L); assert(keysyms[1] == XKB_KEY_ISO_Group_Shift); ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); level3 = xkb_keymap_mod_get_index(keymap, "Mod5"); state = xkb_state_new(keymap); assert(state); layout = xkb_state_key_get_layout(state, KEY_LEFTCTRL + EVDEV_OFFSET); assert(layout == 0); xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == (UINT32_C(1) << ctrl)); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED); assert(layout == 1); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); assert(layout == 1); xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); assert(layout == 0); xkb_state_update_key(state, KEY_LVL3 + EVDEV_OFFSET, XKB_KEY_DOWN); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == (UINT32_C(1) << level3)); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED); assert(layout == 1); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); assert(layout == 1); xkb_state_update_key(state, KEY_LVL3 + EVDEV_OFFSET, XKB_KEY_UP); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED); assert(layout == 0); layout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); assert(layout == 0); xkb_state_unref(state); assert(test_key_seq( keymap, KEY_2, BOTH, XKB_KEY_2, NEXT, /* Control switch to the second group */ KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_LEFTCTRL, UP, XKB_KEY_Control_L, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_RIGHTCTRL, DOWN, XKB_KEY_Control_R, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_RIGHTCTRL, UP, XKB_KEY_Control_R, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, /* Fake keys switch to the second group too */ KEY_LVL3, DOWN, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_at, NEXT, KEY_LVL3, UP, XKB_KEY_ISO_Level3_Shift, /* Only one keysym, group=2 + level3(ralt_switch):2 */ NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_LVL5, DOWN, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_at, NEXT, KEY_LVL5, UP, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, /* Alt have different keysyms & actions count */ KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_Alt_R, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_RIGHTALT, UP, XKB_KEY_Alt_R, XKB_KEY_ISO_Group_Shift, NEXT, /* Super have different keysyms & actions count */ KEY_LEFTMETA, DOWN, XKB_KEY_Super_L, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_LEFTMETA, UP, XKB_KEY_Super_L, XKB_KEY_ISO_Group_Shift, NEXT, KEY_RIGHTMETA, DOWN, XKB_KEY_Super_R, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_RIGHTMETA, UP, XKB_KEY_Super_R, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, /* Incompatible actions categories */ KEY_RO, DOWN, XKB_KEY_Control_L, XKB_KEY_Shift_L, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_RO, UP, XKB_KEY_Control_L, XKB_KEY_Shift_L, NEXT, KEY_YEN, DOWN, XKB_KEY_Control_L, XKB_KEY_Shift_L, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_YEN, UP, XKB_KEY_Control_L, XKB_KEY_Shift_L, NEXT, /* Test various overrides */ KEY_Z, DOWN, XKB_KEY_Control_L, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_Z, UP, XKB_KEY_y, NEXT, KEY_X, BOTH, XKB_KEY_x, NEXT, KEY_C, DOWN, XKB_KEY_NoSymbol, NEXT, KEY_2, BOTH, XKB_KEY_at, NEXT, KEY_C, UP, XKB_KEY_ampersand, NEXT, KEY_V, DOWN, XKB_KEY_NoSymbol, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_V, UP, XKB_KEY_NoSymbol, NEXT, KEY_B, DOWN, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_at, NEXT, KEY_B, UP, XKB_KEY_braceleft,NEXT, KEY_N, DOWN, XKB_KEY_Control_L, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_N, UP, XKB_KEY_Control_L, NEXT, KEY_M, DOWN, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Group_Shift, NEXT, KEY_2, BOTH, XKB_KEY_at, NEXT, KEY_M, UP, XKB_KEY_asciicircum, NEXT, /* Modifier_Map */ KEY_Q, DOWN, XKB_KEY_a, XKB_KEY_b, NEXT, KEY_2, BOTH, XKB_KEY_at, NEXT, KEY_Q, UP, XKB_KEY_a, XKB_KEY_b, NEXT, KEY_2, BOTH, XKB_KEY_2, FINISH)); xkb_keymap_unref(keymap); /* TODO: This example is intended to make keyboard shortcuts use the first * layout. However, this requires to be able to configure group redirect * at the *keymap* level, then use ISO_First_Group and SetGroup(group=-4). * Change the symbols and this test once this is merged. */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "awesome,cz", NULL, "grp:menu_toggle"); assert(keymap); ctrl = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); kc = xkb_keymap_key_by_name(keymap, "LCTL"); keysyms_count = xkb_keymap_key_get_syms_by_level(keymap, kc, first_layout, 0, &keysyms); assert(keysyms_count == 2); assert(keysyms[0] == XKB_KEY_Control_L); assert(keysyms[1] == XKB_KEY_ISO_Next_Group); state = xkb_state_new(keymap); assert(state); layout = xkb_state_key_get_layout(state, KEY_LEFTCTRL + EVDEV_OFFSET); assert(layout == 0); xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == (UINT32_C(1) << ctrl)); layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET); assert(layout == 1); xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == 0); layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET); assert(layout == 0); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET); assert(layout == 1); xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == (UINT32_C(1) << ctrl)); layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET); assert(layout == 0); xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == 0); layout = xkb_state_key_get_layout(state, XKB_KEY_2 + EVDEV_OFFSET); assert(layout == 1); xkb_state_unref(state); assert(test_key_seq(keymap, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L, XKB_KEY_ISO_Next_Group, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_LEFTCTRL, UP, XKB_KEY_Control_L, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L, XKB_KEY_ISO_Next_Group, NEXT, KEY_2, BOTH, XKB_KEY_2, NEXT, KEY_LEFTCTRL, UP, XKB_KEY_Control_L, XKB_KEY_ISO_Next_Group, NEXT, KEY_2, BOTH, XKB_KEY_ecaron, FINISH)); xkb_keymap_unref(keymap); xkb_context_unref(context); } static void count_keys(struct xkb_keymap *keymap, xkb_keycode_t key, void *data) { if (!xkb_keymap_key_get_name(keymap, key)) return; darray_size_t * const count = data; (*count)++; } static void test_keynames_atoms(void) { static struct { const char *rules; xkb_keycode_t max_keycode; darray_size_t num_aliases; darray_size_t num_atoms; darray_size_t num_key_names; } tests[] = { { .rules = "base", .max_keycode = 255, .num_aliases = 63, .num_atoms = 484, .num_key_names = 325, }, { .rules = "evdev", .max_keycode = 569, .num_aliases = 33, .num_atoms = 501, .num_key_names = 305, }, }; for (size_t t = 0; t < ARRAY_SIZE(tests); t++) { fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, t); struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); struct xkb_keymap *keymap = test_compile_rules( context, XKB_KEYMAP_FORMAT_TEXT_V1, tests[t].rules, "pc104", "us", NULL, NULL ); assert(keymap); darray_size_t expected, got; expected = (darray_size_t) tests[t].max_keycode; got = xkb_keymap_max_keycode(keymap); assert_eq("keynames max keycode", expected, got, "%u"); expected = tests[t].num_aliases; got = keymap->num_key_aliases; assert_eq("keynames num aliases", expected, got, "%u"); expected = tests[t].num_atoms; got = xkb_atom_table_size(context); assert_eq("atoms", expected, got, "%u"); /* * Find size of the temporary key name LUT used during compilation. * It corresponds to: max(key name/alias atom) + 1. */ darray_size_t num_key_names = 0; for (xkb_atom_t a = 0; a < xkb_atom_table_size(context); a++) { const char *name = xkb_atom_text(context, a); if (name == NULL) continue; if (xkb_keymap_key_by_name(keymap, name) != XKB_KEYCODE_INVALID) { num_key_names = a + 1; } } expected = tests[t].num_key_names; got = num_key_names; assert_eq("keynames atoms", expected, got, "%u"); /* Count valid key names */ got = keymap->num_key_aliases; xkb_keymap_key_for_each(keymap, count_keys, &got); /* * Check that we do not waste too much memory with non-key name/alias * entries in the LUT. */ const double valid_entries = (double) got / num_key_names; const double valid_entries_min = 0.92; const double valid_entries_max = 1.0; assert_printf(valid_entries >= valid_entries_min && valid_entries < valid_entries_max, "No enough valid entries; expected: %f <= %f < %f\n", valid_entries_min, valid_entries, valid_entries_max); xkb_keymap_unref(keymap); xkb_context_unref(context); } } int main(void) { test_init(); test_supported_formats(); test_garbage_key(); test_keymap(); test_no_extra_groups(); test_numeric_keysyms(); test_multiple_keysyms_per_level(); test_multiple_actions_per_level(); test_keynames_atoms(); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/keyseq.c000066400000000000000000003206161510033435100213170ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include "xkbcommon/xkbcommon-keysyms.h" #include "xkbcommon/xkbcommon.h" #include "evdev-scancodes.h" #include "test.h" #include "keymap.h" #include "utils.h" enum fake_keys { KEY_LVL3 = 84 }; static const enum xkb_keymap_format keymap_formats[] = { XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_FORMAT_TEXT_V2, }; static inline xkb_keysym_t get_keysym(struct xkb_keymap *keymap, xkb_keysym_t v1, xkb_keysym_t v2) { return (keymap->format == XKB_KEYMAP_FORMAT_TEXT_V1) ? v1 : v2; } static void test_group_lock(struct xkb_context *ctx) { struct xkb_keymap *keymap; /* * Group lock on press (all formats) * Implicit lockOnRelease=false (XKB spec) */ for (unsigned int f = 0; f < ARRAY_SIZE(keymap_formats); f++) { keymap = test_compile_rules(ctx, keymap_formats[f], "evdev", "pc105", "us,de", "", "grp:alt_shift_toggle"); assert(keymap); #define test_group_lock_on_press(keymap) assert( \ test_key_seq((keymap), \ KEY_Y, BOTH, XKB_KEY_y, NEXT, \ KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, \ KEY_LEFTSHIFT, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ /* Group change on press */ \ KEY_Y, BOTH, XKB_KEY_z, NEXT, \ KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, \ /* Group change on press */ \ KEY_Y, BOTH, XKB_KEY_y, NEXT, \ KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_Y, BOTH, XKB_KEY_y, NEXT, \ KEY_LEFTALT, UP, XKB_KEY_Alt_L, FINISH)\ ) test_group_lock_on_press(keymap); xkb_keymap_unref(keymap); } /* * Group lock on press for format V2 * Explicit lockOnRelease=false (XKB spec) */ keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "pc105", "us,de", "", "grp:alt_shift_toggle,grp:lockOnPress"); test_group_lock_on_press(keymap); xkb_keymap_unref(keymap); #undef test_group_lock_on_press /* * Group lock on release for format V2 * Explicit lockOnRelease=true (XKB extension) */ keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "pc105", "us,de", "", "grp:alt_shift_toggle,grp:lockOnRelease"); #define test_group_lock_on_release(keymap) assert( \ test_key_seq((keymap), \ KEY_Y, BOTH, XKB_KEY_y, NEXT, \ KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, \ KEY_LEFTSHIFT, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ /* Group lock on release */ \ KEY_Y, BOTH, XKB_KEY_z, NEXT, \ KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, \ /* Key not released, no group change */ \ KEY_Y, BOTH, XKB_KEY_z, NEXT, \ KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Next_Group, NEXT, \ /* Group lock cancelled by intermediate key press */\ KEY_Y, BOTH, XKB_KEY_z, NEXT, \ KEY_Y, DOWN, XKB_KEY_z, NEXT, \ KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, \ /* Group lock not cancelled by intermediate key release */\ KEY_Y, UP, XKB_KEY_z, NEXT, \ KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Next_Group, NEXT, \ /* Group lock on release */ \ KEY_Y, BOTH, XKB_KEY_y, NEXT, \ KEY_LEFTALT, UP, XKB_KEY_Alt_L, FINISH)\ ) test_group_lock_on_release(keymap); xkb_keymap_unref(keymap); #undef test_group_lock_on_release } static void test_group_latch(struct xkb_context *ctx) { /* Absolute group, no lock */ for (unsigned int f = 0; f < ARRAY_SIZE(keymap_formats); f++) { fprintf(stderr, "=== %s, format %u ===\n", __func__, keymap_formats[f]); struct xkb_keymap *keymap = test_compile_rules( ctx, keymap_formats[f], "evdev", "pc104", "us,il,ru,de", ",,phonetic,neo", "grp:menu_latch_group2,grp:sclk_toggle,grp:lctrl_rctrl_switch"); assert(keymap); /* Set only */ #define test_set_only(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ KEY_E, BOTH, XKB_KEY_e, NEXT, \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ /* Lock the second group */ \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ /* Event if the latch group is absolute, it sums with \ * the locked group (see spec) */ \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_E, BOTH, XKB_KEY_Cyrillic_ie, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, FINISH)) test_set_only(keymap); /* Latch only */ #define test_latch_only(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Empty level breaks latches */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_YEN, BOTH, XKB_KEY_NoSymbol, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Unknown key does not break latches */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ UINT32_MAX, BOTH, XKB_KEY_NoSymbol, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Lock the second group */ \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ /* Event if the latch group is absolute, it sums with \ * the locked group (see spec) */ \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, FINISH)) test_latch_only(keymap); /* Latch not broken by modifier */ #define test_latch_not_broken_by_modifier(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Sequential */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_LEFTALT, BOTH, XKB_KEY_Alt_L, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Simultaneous */ \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_LEFTALT, BOTH, XKB_KEY_Alt_L, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, get_keysym(keymap, XKB_KEY_h, XKB_KEY_hebrew_yod), NEXT, \ /* Simultaneous */ \ KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Simultaneous */ \ KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_h, FINISH)) test_latch_not_broken_by_modifier(keymap); /* Simulatenous group actions */ #define test_simultaneous_group_latches(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Sequential */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_LEFTCTRL, BOTH, XKB_KEY_ISO_First_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Simultaneous */ \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, get_keysym(keymap, XKB_KEY_hebrew_yod, XKB_KEY_Cyrillic_ha), NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_LEFTCTRL, BOTH, XKB_KEY_ISO_First_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Simultaneous */ \ KEY_SCROLLLOCK, DOWN, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_SCROLLLOCK, UP, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_LEFTCTRL, BOTH, XKB_KEY_ISO_First_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Simultaneous */ \ KEY_SCROLLLOCK, DOWN, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_SCROLLLOCK, UP, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_LEFTCTRL, BOTH, XKB_KEY_ISO_First_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_h, FINISH)) test_simultaneous_group_latches(keymap); /* No lock */ #define test_no_latch_to_lock(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* No latch-to-lock */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_E, BOTH, XKB_KEY_e, NEXT, \ /* Lock the second group */ \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, \ /* No latch-to-lock */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_s, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, \ /* Lock the third group */ \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_E, BOTH, XKB_KEY_Cyrillic_ie, NEXT, \ /* No latch-to-lock */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ KEY_E, BOTH, XKB_KEY_Cyrillic_ie, FINISH)) test_no_latch_to_lock(keymap); xkb_keymap_unref(keymap); /* Absolute group, latch-to-lock */ keymap = test_compile_rules( ctx, keymap_formats[f], "evdev", "pc104", "us,il,ru,de", ",,phonetic,neo", "grp:menu_latch_group2_lock,grp:sclk_toggle,grp:lctrl_rctrl_switch"); assert(keymap); test_set_only(keymap); test_latch_only(keymap); test_latch_not_broken_by_modifier(keymap); test_simultaneous_group_latches(keymap); /* Lock */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, /* Lock the second group via latch-to-lock */ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, /* Lock the third group via usual lock */ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, KEY_E, BOTH, XKB_KEY_Cyrillic_ie, NEXT, /* Lock the second group via latch-to-lock */ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_E, BOTH, XKB_KEY_hebrew_qoph, FINISH)); xkb_keymap_unref(keymap); /* Relative group (positive), no lock */ keymap = test_compile_rules( ctx, keymap_formats[f], "evdev", "pc104", "us,il,ru,de", ",,phonetic,neo", "grp:menu_latch,grp:sclk_toggle,grp:lctrl_rctrl_switch"); assert(keymap); test_set_only(keymap); test_latch_only(keymap); test_latch_not_broken_by_modifier(keymap); test_simultaneous_group_latches(keymap); test_no_latch_to_lock(keymap); xkb_keymap_unref(keymap); /* Relative group (positive), latch-to-lock */ keymap = test_compile_rules( ctx, keymap_formats[f], "evdev", "pc104", "us,il,ru,de", ",,phonetic,neo", "grp:menu_latch_lock,grp:sclk_toggle,grp:lctrl_rctrl_switch"); assert(keymap); test_set_only(keymap); test_latch_only(keymap); test_latch_not_broken_by_modifier(keymap); test_simultaneous_group_latches(keymap); /* Lock */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, /* Lock the second group via latch-to-lock */ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, /* Lock the third group via usual lock */ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, KEY_E, BOTH, XKB_KEY_Cyrillic_ie, NEXT, /* Lock the fourth group via latch-to-lock */ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_H, BOTH, XKB_KEY_s, NEXT, KEY_E, BOTH, XKB_KEY_l, FINISH)); xkb_keymap_unref(keymap); #undef test_set_only #undef test_latch_only #undef test_latch_not_broken_by_modifier #undef test_simultaneous_group_latches /* Relative group (negative), no lock */ keymap = test_compile_rules( ctx, keymap_formats[f], "evdev", "pc104", "us,il,ru,de", ",,phonetic,neo", "grp:menu_latch_negative,grp:sclk_toggle,grp:lctrl_rctrl_switch"); assert(keymap); /* Set only */ #define test_set_only(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ KEY_E, BOTH, XKB_KEY_e, NEXT, \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_s, NEXT, \ KEY_E, BOTH, XKB_KEY_l, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Lock the second group */ \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ KEY_E, BOTH, XKB_KEY_e, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, FINISH)) test_set_only(keymap); /* Latch only */ #define test_latch_only(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_s, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Empty level breaks latches */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_YEN, BOTH, XKB_KEY_NoSymbol, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Unknown key does not break latches */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ UINT32_MAX, BOTH, XKB_KEY_NoSymbol, NEXT, \ KEY_H, BOTH, XKB_KEY_s, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Lock the second group */ \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_E, BOTH, XKB_KEY_hebrew_qoph, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, FINISH)) test_latch_only(keymap); /* Latch not broken by modifier */ #define test_latch_not_broken_by_modifier(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Sequential */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_LEFTALT, BOTH, XKB_KEY_Alt_L, NEXT, \ KEY_H, BOTH, XKB_KEY_s, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Simultaneous */ \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_LEFTALT, BOTH, XKB_KEY_Alt_L, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, get_keysym(keymap, XKB_KEY_h, XKB_KEY_s), NEXT,\ /* Simultaneous */ \ KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, \ KEY_H, BOTH, XKB_KEY_s, NEXT, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ /* Simultaneous */ \ KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_s, NEXT, \ KEY_H, BOTH, XKB_KEY_h, FINISH)) test_latch_not_broken_by_modifier(keymap); /* Simulatenous group actions */ #define test_simultaneous_group_latches(keymap_) \ assert(test_key_seq(keymap_, \ KEY_H, BOTH, XKB_KEY_h, NEXT, \ KEY_RIGHTCTRL, BOTH, XKB_KEY_ISO_Last_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ /* Sequential */ \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_RIGHTCTRL, BOTH, XKB_KEY_ISO_Last_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ /* Simultaneous */ \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, get_keysym(keymap, XKB_KEY_Cyrillic_ha, XKB_KEY_hebrew_yod), NEXT,\ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_RIGHTCTRL, BOTH, XKB_KEY_ISO_Last_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ /* Simultaneous */ \ KEY_SCROLLLOCK, DOWN, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_SCROLLLOCK, UP, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_RIGHTCTRL, BOTH, XKB_KEY_ISO_Last_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ /* Simultaneous */ \ KEY_SCROLLLOCK, DOWN, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_COMPOSE, DOWN, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_SCROLLLOCK, UP, XKB_KEY_ISO_Next_Group, NEXT, \ KEY_COMPOSE, UP, XKB_KEY_ISO_Group_Latch, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, \ KEY_RIGHTCTRL, BOTH, XKB_KEY_ISO_Last_Group, NEXT, \ KEY_H, BOTH, XKB_KEY_hebrew_yod, FINISH)) test_simultaneous_group_latches(keymap); test_no_latch_to_lock(keymap); xkb_keymap_unref(keymap); /* Relative group (negative), no lock */ keymap = test_compile_rules( ctx, keymap_formats[f], "evdev", "pc104", "us,il,ru,de", ",,phonetic,neo", "grp:menu_latch_negative_lock,grp:sclk_toggle,grp:lctrl_rctrl_switch"); assert(keymap); test_set_only(keymap); test_latch_only(keymap); test_latch_not_broken_by_modifier(keymap); test_simultaneous_group_latches(keymap); /* Lock */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, /* Lock the fourth group via latch-to-lock */ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_H, BOTH, XKB_KEY_s, NEXT, KEY_E, BOTH, XKB_KEY_l, NEXT, /* Lock the third group via usual lock */ KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_SCROLLLOCK, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_ha, NEXT, KEY_E, BOTH, XKB_KEY_Cyrillic_ie, NEXT, /* Lock the second group via latch-to-lock */ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Group_Latch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_E, BOTH, XKB_KEY_hebrew_qoph, FINISH)); xkb_keymap_unref(keymap); #undef test_set_only #undef test_latch_only #undef test_latch_not_broken_by_modifier #undef test_simultaneous_group_latches #undef test_no_latch_to_lock } } static void test_mod_set(struct xkb_context *ctx) { struct xkb_keymap *keymap; /* Shift break caps: unlockOnPress=false */ keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "pc105", "us", "", "shift:breaks_caps"); assert(test_key_seq(keymap, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_A, BOTH, XKB_KEY_A, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_A, BOTH, XKB_KEY_a, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, /* Caps still locked: key was operated before Shift release */ KEY_A, BOTH, XKB_KEY_A, FINISH )); assert(keymap); xkb_keymap_unref(keymap); /* Shift break caps: unlockOnPress=true (XKB extension) */ keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "pc105", "us", "", "shift:breaks_caps-v2"); assert(keymap); assert(test_key_seq(keymap, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_A, BOTH, XKB_KEY_A, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_A, BOTH, XKB_KEY_A, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_A, BOTH, XKB_KEY_a, FINISH )); xkb_keymap_unref(keymap); } static void test_mod_lock(struct xkb_context *ctx) { struct xkb_keymap *keymap; /* * Caps unlocks on release (all formats) * Implicit unlockOnPress=false (XKB spec) */ for (unsigned int f = 0; f < ARRAY_SIZE(keymap_formats); f++) { keymap = test_compile_rules(ctx, keymap_formats[f], "evdev", "pc105", "us", "", ""); assert(keymap); #define test_caps_unlocks_on_release(keymap) assert( \ test_key_seq((keymap), \ KEY_Y, BOTH, XKB_KEY_y, NEXT, \ /* Lock on press */ \ KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, \ KEY_Y, BOTH, XKB_KEY_Y, NEXT, \ KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, \ /* No unlock on press */ \ KEY_Y, BOTH, XKB_KEY_Y, NEXT, \ KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, \ /* Unlock on release */ \ KEY_Y, BOTH, XKB_KEY_y, FINISH)\ ) test_caps_unlocks_on_release(keymap); xkb_keymap_unref(keymap); } /* * Caps unlocks on press for format V2 * Explicit unlockOnPress=false (XKB spec) */ keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "pc105", "us", "", "caps:unlock-on-release"); assert(keymap); test_caps_unlocks_on_release(keymap); xkb_keymap_unref(keymap); #undef test_caps_unlocks_on_release /* * Caps unlocks on press for format V2 * Explicit unlockOnPress=true (XKB extension) */ keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "pc105", "us", "", "caps:unlock-on-press"); assert(keymap); test_key_seq((keymap), KEY_Y, BOTH, XKB_KEY_y, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, /* Lock on press */ KEY_Y, BOTH, XKB_KEY_Y, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, /* Unlock on press */ KEY_Y, BOTH, XKB_KEY_y, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_Y, BOTH, XKB_KEY_y, FINISH); xkb_keymap_unref(keymap); } static void test_mod_latch(struct xkb_context *context) { struct xkb_keymap *keymap; for (unsigned int f = 0; f < ARRAY_SIZE(keymap_formats); f++) { fprintf(stderr, "=== %s, format %u ===\n", __func__, keymap_formats[f]); keymap = test_compile_rules(context, keymap_formats[f], "evdev", "pc104", "latch", "", ""); assert(keymap); /* Set: basic */ assert(test_key_seq(keymap, KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Empty level */ KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, KEY_YEN , BOTH, XKB_KEY_NoSymbol, NEXT, /* Prevent latch */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, KEY_Q , BOTH, XKB_KEY_q , NEXT, /* Unknown key */ KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, UINT32_MAX , BOTH, XKB_KEY_NoSymbol, NEXT, /* Does not prevent latch */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, KEY_1 , BOTH, XKB_KEY_exclam , NEXT, KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L, NEXT, KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Prevent latch */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L, NEXT, KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L, NEXT, KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Prevent latch */ KEY_1 , BOTH, XKB_KEY_exclam , NEXT, /* Set is still active */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L, NEXT, KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, KEY_F1 , BOTH, XKB_KEY_XF86Switch_VT_1, NEXT, /* Prevent latch */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, KEY_LVL3 , BOTH, XKB_KEY_ISO_Level3_Shift, NEXT, /* v1: Prevent latch */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, KEY_Q , BOTH, get_keysym(keymap, XKB_KEY_q, XKB_KEY_Q), NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, KEY_CAPSLOCK , BOTH, XKB_KEY_ISO_Group_Latch , NEXT, /* v1: Prevent latch */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, KEY_Q , BOTH, get_keysym(keymap, XKB_KEY_q, XKB_KEY_Q), FINISH )); /* Set: mix with regular set */ assert(test_key_seq(keymap, KEY_LVL3 , DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, /* Set Level3 (regular) */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift (latch) */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Prevent Shift latch */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* State unchanged */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_LVL3 , UP, XKB_KEY_ISO_Level3_Shift, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift (latch) */ KEY_LVL3 , DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, /* Set Level3 (regular) */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Prevent Shift latch */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* State unchanged */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_LVL3 , UP, XKB_KEY_ISO_Level3_Shift, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_1 , FINISH )); /* Set: mix with regular lock */ assert(test_key_seq(keymap, /* Only Lock */ KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock , NEXT, /* Lock Level3 */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift (latch) */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Prevent Shift latch */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* State unchanged */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, /* Unset shift (latch) */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock , NEXT, /* Unlock Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift (latch) */ KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock , NEXT, /* Lock Level3 */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Prevent Shift latch */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* State unchanged */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, /* Unset shift (latch) */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock , NEXT, /* Unlock Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Set, then Lock */ KEY_102ND , DOWN, XKB_KEY_ISO_Level3_Lock , NEXT, /* Set Level3 (lock) */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift (latch) */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Prevent Shift latch */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* State unchanged */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, /* Unset shift (latch) */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , UP, XKB_KEY_ISO_Level3_Lock , NEXT, /* Unset and lock Level3 */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock , NEXT, /* Unlock Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift (latch) */ KEY_102ND , DOWN, XKB_KEY_ISO_Level3_Lock , NEXT, /* Set Level3 (lock) */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Prevent Shift latch */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* State unchanged */ KEY_LEFTSHIFT , UP, XKB_KEY_Shift_L , NEXT, /* Unset shift (latch) */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , UP, XKB_KEY_ISO_Level3_Lock , NEXT, /* Unset and lock Level3 */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock , NEXT, /* Unlock Level3 */ KEY_1 , BOTH, XKB_KEY_1 , FINISH )); /* Basic latch/unlatch: breaking/preventing latch */ assert(test_key_seq(keymap, /* Latch break: sequential */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L, NEXT, /* Latch Shift */ KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* No action: unlatch Shift */ KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_F1 , BOTH, XKB_KEY_XF86Switch_VT_1, NEXT, /* VT action: unlatch Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_CAPSLOCK , BOTH, XKB_KEY_ISO_Group_Latch, NEXT, /* Group actions do not break latches */ KEY_1 , BOTH, XKB_KEY_exclam , NEXT, KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Latch prevented (DOWN/UP events) */ KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L, NEXT, /* Set Shift */ KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Prevent latch on DOWN event */ KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L, NEXT, /* Unset Shift */ KEY_Q , BOTH, XKB_KEY_q , NEXT, /* Latch prevented (DOWN event) */ KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L, NEXT, /* Set Shift */ KEY_Q , DOWN, XKB_KEY_Q , NEXT, /* Prevent latch */ KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L, NEXT, /* Unset Shift */ KEY_Q , UP , XKB_KEY_q , NEXT, /* Latch not prevented (UP event) */ KEY_Q , DOWN, XKB_KEY_q , NEXT, /* Prevent latch */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L, NEXT, /* Latch Shift */ KEY_Q , UP , XKB_KEY_Q , NEXT, /* Do not prevent latch */ KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Unlatch Shift */ KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_Q , DOWN, XKB_KEY_q , NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L, NEXT, /* Set Shift */ KEY_Q , UP , XKB_KEY_Q , NEXT, /* Do not prevent latch */ KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L, NEXT, /* Latch Shift */ KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Unlatch Shift */ KEY_Q , BOTH, XKB_KEY_q , FINISH )); /* Basic latch/unlatch: not breaking nor preventing latch */ assert(test_key_seq(keymap, /* No latch break: sequential */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_RIGHTCTRL , BOTH, XKB_KEY_Control_R , NEXT, /* Modifier action does not break latches */ KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Unlatch Shift */ KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock, NEXT, /* Modifier action does not break latches */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Shift */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_F2 , BOTH, XKB_KEY_ISO_Group_Shift, NEXT, /* Group action does not break latches */ KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Unlatch Shift */ KEY_Q , BOTH, XKB_KEY_q , NEXT, /* Latch not prevented (DOWN/UP events) */ KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift */ KEY_RIGHTCTRL , BOTH, XKB_KEY_Control_R, NEXT, KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L , NEXT, /* v2: Latch Shift */ KEY_Q , BOTH, get_keysym(keymap, XKB_KEY_q, XKB_KEY_Q), NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift */ KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L , NEXT, /* v2: Latch Shift */ KEY_1 , BOTH, get_keysym(keymap, XKB_KEY_onesuperior, XKB_KEY_exclamdown), NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Latch not prevented (DOWN event) */ KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift */ KEY_RIGHTCTRL , DOWN, XKB_KEY_Control_R, NEXT, KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L , NEXT, /* v2: Latch Shift */ KEY_RIGHTCTRL , UP , XKB_KEY_Control_R, NEXT, KEY_Q , BOTH, get_keysym(keymap, XKB_KEY_q, XKB_KEY_Q), NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift */ KEY_102ND , DOWN, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L , NEXT, /* v2: Latch Shift */ KEY_102ND , UP , XKB_KEY_ISO_Level3_Lock, NEXT, KEY_1 , BOTH, get_keysym(keymap, XKB_KEY_onesuperior, XKB_KEY_exclamdown), NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Latch not prevented (UP event) */ KEY_RIGHTCTRL , DOWN, XKB_KEY_Control_R, NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_RIGHTCTRL , UP , XKB_KEY_Control_R, NEXT, KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Unlatch Shift */ KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_RIGHTCTRL , DOWN, XKB_KEY_Control_R, NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift */ KEY_RIGHTCTRL , UP , XKB_KEY_Control_R, NEXT, KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_Q , BOTH, XKB_KEY_Q , NEXT, /* Unlatch Shift */ KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_102ND , DOWN, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_102ND , UP , XKB_KEY_ISO_Level3_Lock, NEXT, KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Shift */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_102ND , DOWN, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_102ND , UP , XKB_KEY_ISO_Level3_Lock, NEXT, KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Shift */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_102ND , BOTH, XKB_KEY_ISO_Level3_Lock, NEXT, KEY_1 , BOTH, XKB_KEY_1 , FINISH )); /* Latch-to-lock */ assert(test_key_seq(keymap, /* Lock */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L, NEXT, /* Latch Shift */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L, NEXT, /* Lock Shift */ KEY_Q , BOTH, XKB_KEY_Q , NEXT, KEY_Q , BOTH, XKB_KEY_Q , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L, NEXT, /* Unlock Shift */ KEY_Q , BOTH, XKB_KEY_q , NEXT, KEY_Q , BOTH, XKB_KEY_q , NEXT, /* No lock; cancel latch */ KEY_RIGHTSHIFT, BOTH, XKB_KEY_Shift_R, NEXT, /* Latch Shift */ KEY_RIGHTSHIFT, BOTH, XKB_KEY_Shift_R, NEXT, /* Unlatch Shift */ KEY_Q , BOTH, XKB_KEY_q , FINISH // TODO: mix with regular set and lock )); /* Sequential (at most one key down at a time) */ assert(test_key_seq(keymap, /* Latch */ KEY_LEFTCTRL , BOTH, XKB_KEY_Control_L, NEXT, /* Latch Control */ KEY_LEFTALT , BOTH, XKB_KEY_Alt_L , NEXT, /* Latch Alt */ KEY_1 , BOTH, XKB_KEY_plus , NEXT, /* Unlatch Control, Unlatch Alt */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Latch (repeat, no latch-to-lock) */ KEY_RIGHTSHIFT, BOTH, XKB_KEY_Shift_R , NEXT, /* Latch Shift */ KEY_RIGHTSHIFT, BOTH, XKB_KEY_Shift_R , NEXT, /* Unlatch Shift (no lock) */ KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, /* Unlatch all */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_RIGHTSHIFT, BOTH, XKB_KEY_Shift_R , NEXT, /* Latch Shift */ KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_RIGHTSHIFT, BOTH, XKB_KEY_Shift_R , NEXT, /* Unlatch Shift (no lock) */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, /* Unlatch all */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Lock one, latch the other */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Lock Shift */ KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Level3 */ KEY_1 , BOTH, XKB_KEY_exclam , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Unlock Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Lock Shift */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Level3 */ KEY_1 , BOTH, XKB_KEY_exclam , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Unlock Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Lock both */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Lock Shift */ KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Lock Level3 */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Unlock Level3 */ KEY_1 , BOTH, XKB_KEY_exclam , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Unlock Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Lock Shift */ KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Lock Level3 */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, KEY_RIGHTALT , BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Unlock Level3 */ KEY_1 , BOTH, XKB_KEY_exclam , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Unlock Shift */ KEY_1 , BOTH, XKB_KEY_1 , FINISH )); // TODO: Sequential with regular set & lock /* Simultaneous (multiple keys down) */ assert(test_key_seq(keymap, /* Set */ KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Prevent latches */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_exclam , NEXT, /* Shift still active */ KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L , NEXT, /* Unset Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Set one, latch the other */ KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Shift, prevent Level3 latch */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Shift, prevent Level3 latch */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, /* Level 3 still active */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Set both, latch both */ KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , DOWN, XKB_KEY_Shift_L , NEXT, /* Set Shift */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* v2: Latch Level3 */ KEY_LEFTSHIFT , UP , XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_1 , BOTH, get_keysym(keymap, XKB_KEY_exclam, XKB_KEY_exclamdown), NEXT, /* Unlatch Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* v2: Latch Level3 */ KEY_1 , BOTH, get_keysym(keymap, XKB_KEY_exclam, XKB_KEY_exclamdown), NEXT, /* Unlatch Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Set one, lock the other */ KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Lock Shift */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Unlock Shift */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Lock Shift */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_exclam , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Unlock Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Latch one, set the other */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Shift, prevent Level3 latch */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_1 , BOTH, XKB_KEY_exclamdown , NEXT, /* Unlatch Shift, prevent Level3 latch */ KEY_1 , BOTH, XKB_KEY_onesuperior , NEXT, /* Level3 still active */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* Unset Level3 */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, /* Latch one, lock the other */ KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Lock Shift */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* v2: Latch Level3 */ KEY_1 , BOTH, get_keysym(keymap, XKB_KEY_exclam, XKB_KEY_exclamdown), NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Unlock Shift */ KEY_1 , BOTH, XKB_KEY_1 , NEXT, KEY_RIGHTALT , DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, /* Set Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Latch Shift */ KEY_RIGHTALT , UP , XKB_KEY_ISO_Level3_Latch, NEXT, /* v2: Latch Level3 */ KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Lock Shift */ KEY_1 , BOTH, get_keysym(keymap, XKB_KEY_exclam, XKB_KEY_exclamdown), NEXT, KEY_LEFTSHIFT , BOTH, XKB_KEY_Shift_L , NEXT, /* Unlock Shift */ KEY_1 , BOTH, XKB_KEY_1 , FINISH )); xkb_keymap_unref(keymap); } /* * Mod latch on release (all formats) * Implicit latchOnPress=false (XKB spec) */ for (unsigned int f = 0; f < ARRAY_SIZE(keymap_formats); f++) { keymap = test_compile_rules(context, keymap_formats[f], "evdev", "pc104", "de", "", "lv3:ralt_latch"); assert(keymap); #define test_mod_latch_on_release(keymap) assert( \ test_key_seq((keymap), \ KEY_A , BOTH, XKB_KEY_a, NEXT, \ /* Regular latch */ \ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, \ KEY_A , BOTH, XKB_KEY_ae, NEXT, \ KEY_A , BOTH, XKB_KEY_a, NEXT, \ /* Latch to lock */ \ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, \ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, \ KEY_A , BOTH, XKB_KEY_ae, NEXT, \ KEY_A , BOTH, XKB_KEY_ae, NEXT, \ /* Unlock on release */ \ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, \ KEY_A , BOTH, XKB_KEY_ae, NEXT, \ KEY_A , BOTH, XKB_KEY_ae, NEXT, \ KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Latch, NEXT, \ KEY_A , BOTH, XKB_KEY_a, NEXT, \ /* Maintained pressed */ \ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, \ /* Degrade to set */ \ KEY_A , BOTH, XKB_KEY_ae, NEXT, \ KEY_A , BOTH, XKB_KEY_ae, NEXT, \ KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Latch, NEXT, \ KEY_A , BOTH, XKB_KEY_a, FINISH)\ ) test_mod_latch_on_release(keymap); xkb_keymap_unref(keymap); } /* * Mod latch on release for format V2 * Explicit latchOnPress=false (XKB spec) */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "pc104", "de", "", "lv3:ralt_latch,lv3:latchOnRelease"); assert(keymap); test_mod_latch_on_release(keymap); xkb_keymap_unref(keymap); #undef test_mod_latch_on_release /* * Mod latch on press for format V2 * Explicit latchOnPress=true (XKB extension) */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "pc104", "de", "", "lv3:ralt_latch,lv3:latchOnPress"); assert(keymap); assert(test_key_seq(keymap, KEY_A , BOTH, XKB_KEY_a, NEXT, /* Regular latch */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, KEY_A , BOTH, XKB_KEY_ae, NEXT, KEY_A , BOTH, XKB_KEY_a, NEXT, /* Latch to lock */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, KEY_A , BOTH, XKB_KEY_ae, NEXT, KEY_A , BOTH, XKB_KEY_ae, NEXT, /* Unlock on press */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, KEY_A , BOTH, XKB_KEY_a, NEXT, KEY_A , BOTH, XKB_KEY_a, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Latch, NEXT, KEY_A , BOTH, XKB_KEY_a, NEXT, /* Maintained pressed: latched on press */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level3_Latch, NEXT, KEY_A , BOTH, XKB_KEY_ae, NEXT, /* Broken latch */ KEY_A , BOTH, XKB_KEY_a, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Latch, NEXT, KEY_A , BOTH, XKB_KEY_a, FINISH)); xkb_keymap_unref(keymap); /* * If `Caps_Lock` is on the second level of some key, and `Shift` is * latched, pressing the key locks `Caps` while also breaking the `Shift` * latch, ensuring that the next character is properly uppercase. * * Implemented using: multiple actions per level + VoidAction() */ const char lock_breaks_latch[] = "xkb_keymap {\n" " xkb_keycodes { = 50; = 38; };\n" " xkb_types { include \"basic\" };\n" " xkb_compat {\n" " interpret ISO_Level2_Latch {\n" " action = LatchMods(modifiers=Shift,latchToLock,clearLocks);\n" " };\n" /* Activating CapsLock will break all latches */ " interpret Caps_Lock {\n" " action = {LockMods(modifiers=Lock), VoidAction()};\n" " };\n" " };\n" " xkb_symbols {\n" " key { [ISO_Level2_Latch, Caps_Lock], type=\"ALPHABETIC\" };\n" " key { [a, A] };\n" " };\n" "};"; keymap = test_compile_buffer(context, XKB_KEYMAP_FORMAT_TEXT_V2, lock_breaks_latch, sizeof(lock_breaks_latch)); assert(keymap); assert(test_key_seq(keymap, KEY_A , BOTH, XKB_KEY_a, NEXT, /* Regular latch */ KEY_LEFTSHIFT, BOTH, XKB_KEY_ISO_Level2_Latch, NEXT, KEY_A , BOTH, XKB_KEY_A, NEXT, KEY_A , BOTH, XKB_KEY_a, NEXT, /* Trigger CapsLock */ KEY_LEFTSHIFT, BOTH, XKB_KEY_ISO_Level2_Latch, NEXT, KEY_LEFTSHIFT, BOTH, XKB_KEY_Caps_Lock, NEXT, /* CapsLock active, latch broken */ KEY_A , BOTH, XKB_KEY_A, NEXT, KEY_A , BOTH, XKB_KEY_A, NEXT, /* Unlock Caps */ KEY_LEFTSHIFT, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_A , BOTH, XKB_KEY_a, NEXT, KEY_A , BOTH, XKB_KEY_a, FINISH)); xkb_keymap_unref(keymap); /* * Make a latch break a previous latch on the German E1 layout. * * Implemented using: multiple actions per level + VoidAction() */ const char lv5_latch_breaks_lv3_latch[] = "xkb_keymap {\n" " xkb_keycodes { = 50; = 108; = 26; = 41; };\n" " xkb_types { include \"complete\" };\n" " xkb_compat { include \"complete\" };\n" " xkb_symbols {\n" " virtual_modifiers LevelFive;\n" " key { [ISO_Level2_Latch], [LatchMods(modifiers=Shift)]};\n" " key { [ISO_Level3_Latch] };\n" /* Excerpt from the German E1 `de(e1)` layout */ " key.type = \"EIGHT_LEVEL_SEMIALPHABETIC\";\n" " key { [e, E, EuroSign, any, schwa, SCHWA] };\n" " key { [f, F, ISO_Level5_Latch, any, any, any ],\n" /* Use VoidAction() to break previous latches */ " [NoAction(), NoAction(), {VoidAction(), LatchMods(modifiers=LevelFive)}] };\n" " };\n" "};"; keymap = test_compile_buffer(context, XKB_KEYMAP_FORMAT_TEXT_V2, lv5_latch_breaks_lv3_latch, sizeof(lv5_latch_breaks_lv3_latch)); assert(keymap); assert(test_key_seq(keymap, KEY_E , BOTH, XKB_KEY_e, NEXT, /* Level 3 latch */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, KEY_E , BOTH, XKB_KEY_EuroSign, NEXT, KEY_E , BOTH, XKB_KEY_e, NEXT, /* Level 3 latch */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Level 5 latch */ KEY_F, BOTH, XKB_KEY_ISO_Level5_Latch, NEXT, /* Level 3 latch broken, level 5 latch active */ KEY_E , BOTH, XKB_KEY_schwa, NEXT, KEY_E , BOTH, XKB_KEY_e, NEXT, /* Level 3 latch */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Level 5 latch */ KEY_F, BOTH, XKB_KEY_ISO_Level5_Latch, NEXT, /* Level 3 latch broken, level 5 latch active */ KEY_LEFTSHIFT, BOTH, XKB_KEY_ISO_Level2_Latch, NEXT, /* Shift + level 5 latches */ KEY_E , BOTH, XKB_KEY_SCHWA, NEXT, KEY_E , BOTH, XKB_KEY_e, FINISH)); xkb_keymap_unref(keymap); } struct key_properties { const char *name; bool repeats; xkb_mod_mask_t vmodmap; }; static void test_explicit_actions(struct xkb_context *ctx) { struct xkb_keymap *original = test_compile_file( ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "keymaps/explicit-actions.xkb" ); assert(original); /* Reload keymap from its dump */ char *dump = xkb_keymap_get_as_string(original, XKB_KEYMAP_USE_ORIGINAL_FORMAT); assert(dump); struct xkb_keymap *roundtrip = test_compile_string(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, dump); free(dump); struct xkb_keymap *keymaps[] = { original, roundtrip }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { assert(keymaps[k]); /* * : Groups 1 & 3 have no explicit actions while group 2 does. * We expect that groups 1 & 3 will have the corresponding interpret run * to set their actions. * * has explicit actions on group 2; dumping the keymap forces * explicit actions as well as the essential virtualMods=LevelThree field. * * has explicit actions on group 2; dumping the keymap forces * explicit actions as well as repeat=Yes. */ const struct key_properties keys[] = { { .name = "LALT", .repeats = false, .vmodmap = 0 }, { .name = "LVL3", .repeats = false, .vmodmap = UINT32_C(1) << 10 }, { .name = "AD05", .repeats = true , .vmodmap = 0 }, /* No explicit actions, check defaults */ { .name = "AD06", .repeats = true , .vmodmap = 0 }, }; for (unsigned int i = 0; i < ARRAY_SIZE(keys); i++) { xkb_keycode_t kc = xkb_keymap_key_by_name(keymaps[k], keys[i].name); assert(kc != XKB_KEYCODE_INVALID); assert(keys[i].repeats == xkb_keymap_key_repeats(keymaps[k], kc)); assert(keys[i].vmodmap == keymaps[k]->keys[kc].vmodmap); } assert(test_key_seq( keymaps[k], KEY_Y, BOTH, XKB_KEY_y, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_Y, BOTH, XKB_KEY_Y, NEXT, KEY_LEFTALT, UP, XKB_KEY_Shift_L, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_Y, BOTH, XKB_KEY_z, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_Y, BOTH, XKB_KEY_leftarrow, NEXT, KEY_LEFTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_Y, BOTH, XKB_KEY_k, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_Y, BOTH, XKB_KEY_exclamdown, NEXT, KEY_LEFTALT, UP, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_Y, BOTH, XKB_KEY_Greek_kappa, NEXT, KEY_LEFTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_Y, BOTH, XKB_KEY_k, FINISH )); xkb_keymap_unref(keymaps[k]); } } static void test_simultaneous_modifier_clear(struct xkb_context *context) { struct xkb_keymap *keymap; keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "simultaneous-mods-latches", "", ""); assert(keymap); /* * Github issue #583: simultaneous latches of *different* modifiers should * not affect each other when clearing their mods. */ /* Original key sequence reported in the issue */ assert(test_key_seq(keymap, KEY_LEFTCTRL, DOWN, XKB_KEY_Control_L , NEXT, /* Set Control */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level5_Latch, NEXT, /* Latch Level5 */ KEY_LEFTCTRL, UP , XKB_KEY_Control_L , NEXT, /* Unset Control */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_Z , BOTH, XKB_KEY_ydiaeresis , NEXT, /* Unlatch Level3, unlatch Level5 */ KEY_Z , BOTH, XKB_KEY_z , NEXT, KEY_Z , BOTH, XKB_KEY_z , FINISH )); /* Alternative key sequence with only mod latches */ assert(test_key_seq(keymap, KEY_RIGHTCTRL, BOTH, XKB_KEY_Control_R , NEXT, /* Latch Control */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level5_Latch, NEXT, /* Latch Level5 */ KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_Z , BOTH, XKB_KEY_ydiaeresis , NEXT, /* Unlatch Control, Level3 and Level5 */ KEY_Z , BOTH, XKB_KEY_z , NEXT, KEY_Z , BOTH, XKB_KEY_z , NEXT, KEY_X , BOTH, XKB_KEY_x , FINISH )); /* Alternative simplier key sequence */ assert(test_key_seq(keymap, KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_RIGHTMETA, BOTH, XKB_KEY_ISO_Level5_Latch, NEXT, /* Latch Level5 */ KEY_Z , BOTH, XKB_KEY_ydiaeresis , NEXT, /* Unlatch Level3, unlatch Level5 */ KEY_Z , BOTH, XKB_KEY_z , NEXT, KEY_Z , BOTH, XKB_KEY_z , FINISH )); /* * Test same modifier latch but on a different key */ /* Level 3 */ assert(test_key_seq(keymap, KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Latch Level3 */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Lock Level3 via latch */ KEY_Z , BOTH, XKB_KEY_y , NEXT, /* Locked Level3 */ KEY_Z , BOTH, XKB_KEY_y , NEXT, KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level3_Latch, NEXT, /* Unlock Level3 via latch */ KEY_Z , BOTH, XKB_KEY_z , NEXT, KEY_Z , BOTH, XKB_KEY_z , FINISH )); /* Level 5, via Control latch */ assert(test_key_seq(keymap, KEY_RIGHTCTRL, BOTH, XKB_KEY_Control_R , NEXT, /* Latch Control */ KEY_RIGHTALT, BOTH, XKB_KEY_ISO_Level5_Latch, NEXT, /* Lock Level5 via latch */ KEY_RIGHTMETA, BOTH, XKB_KEY_ISO_Level5_Latch, NEXT, /* Latch Level5 */ KEY_Z , BOTH, XKB_KEY_ezh , NEXT, /* Locked Level5 */ KEY_Z , BOTH, XKB_KEY_ezh , NEXT, KEY_RIGHTMETA, BOTH, XKB_KEY_ISO_Level5_Latch, NEXT, /* Unlock Level5 via latch */ KEY_Z , BOTH, XKB_KEY_z , NEXT, KEY_Z , BOTH, XKB_KEY_z , NEXT, KEY_X , BOTH, XKB_KEY_x , FINISH )); xkb_keymap_unref(keymap); } static void test_keymaps(struct xkb_context *ctx, const char* rules) { struct xkb_keymap *keymap; assert(ctx); keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "evdev", "us,il,ru,de", ",,phonetic,neo", "grp:alt_shift_toggle,grp:menu_toggle"); assert(keymap); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_E, BOTH, XKB_KEY_e, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); /* Simple shifted level. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); /* Key repeat shifted and unshifted in the middle. */ assert(test_key_seq(keymap, KEY_H, DOWN, XKB_KEY_h, NEXT, KEY_H, REPEAT, XKB_KEY_h, NEXT, KEY_H, REPEAT, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_H, REPEAT, XKB_KEY_H, NEXT, KEY_H, REPEAT, XKB_KEY_H, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, REPEAT, XKB_KEY_h, NEXT, KEY_H, REPEAT, XKB_KEY_h, NEXT, KEY_H, UP, XKB_KEY_h, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); /* Base modifier cleared on key release... */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_O, BOTH, XKB_KEY_O, FINISH)); /* ... But only by the keycode that set it. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_O, BOTH, XKB_KEY_O, FINISH)); /* * A base modifier should only be cleared when no other key affecting * the modifier is down. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); /* * Two key presses from the same key (e.g. if two keyboards use the * same xkb_state) should only be released after two releases. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); /* Same as above with locked modifiers. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); /* Group switching / locking. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_E, BOTH, XKB_KEY_e, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_K, BOTH, XKB_KEY_hebrew_lamed, NEXT, KEY_F, BOTH, XKB_KEY_hebrew_kaph, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); assert(test_key_seq(keymap, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, FINISH)); assert(test_key_seq(keymap, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, FINISH)); /* Locked modifiers. */ assert(test_key_seq(keymap, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_H, BOTH, XKB_KEY_H, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_O, BOTH, XKB_KEY_O, FINISH)); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_E, BOTH, XKB_KEY_e, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, KEY_E, BOTH, XKB_KEY_E, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_L, BOTH, XKB_KEY_L, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_O, BOTH, XKB_KEY_O, FINISH)); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_E, BOTH, XKB_KEY_e, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_L, BOTH, XKB_KEY_l, NEXT, KEY_O, BOTH, XKB_KEY_o, FINISH)); /* * A key release affecting a locked modifier should clear it * regardless of the key press. */ /* assert(test_key_seq(keymap, */ /* KEY_H, BOTH, XKB_KEY_h, NEXT, */ /* KEY_CAPSLOCK, DOWN, XKB_KEY_Caps_Lock, NEXT, */ /* KEY_E, BOTH, XKB_KEY_E, NEXT, */ /* KEY_L, BOTH, XKB_KEY_L, NEXT, */ /* KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, */ /* KEY_L, BOTH, XKB_KEY_L, NEXT, */ /* KEY_CAPSLOCK, UP, XKB_KEY_Caps_Lock, NEXT, */ /* KEY_O, BOTH, XKB_KEY_o, FINISH)); */ /* Simple Num Lock sanity check. */ assert(test_key_seq(keymap, KEY_KP1, BOTH, XKB_KEY_KP_End, NEXT, KEY_NUMLOCK, BOTH, XKB_KEY_Num_Lock, NEXT, KEY_KP1, BOTH, XKB_KEY_KP_1, NEXT, KEY_KP2, BOTH, XKB_KEY_KP_2, NEXT, KEY_NUMLOCK, BOTH, XKB_KEY_Num_Lock, NEXT, KEY_KP2, BOTH, XKB_KEY_KP_Down, FINISH)); /* Test that the aliases in the ru(phonetic) symbols map work. */ assert(test_key_seq(keymap, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_1, BOTH, XKB_KEY_1, NEXT, KEY_Q, BOTH, XKB_KEY_Cyrillic_ya, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_1, BOTH, XKB_KEY_exclam, NEXT, KEY_Q, BOTH, XKB_KEY_Cyrillic_YA, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_V, BOTH, XKB_KEY_Cyrillic_zhe, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_1, BOTH, XKB_KEY_1, NEXT, KEY_V, BOTH, XKB_KEY_Cyrillic_ZHE, NEXT, KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT, KEY_V, BOTH, XKB_KEY_Cyrillic_zhe, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Shift_R, NEXT, KEY_V, BOTH, XKB_KEY_Cyrillic_ZHE, FINISH)); #define KS(name) xkb_keysym_from_name(name, 0) /* Test that levels (1-5) in de(neo) symbols map work. */ assert(test_key_seq(keymap, /* Switch to the group. */ KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, /* Level 1. */ KEY_1, BOTH, XKB_KEY_1, NEXT, KEY_Q, BOTH, XKB_KEY_x, NEXT, KEY_KP7, BOTH, XKB_KEY_KP_7, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, /* Level 2 with Shift. */ KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_1, BOTH, XKB_KEY_degree, NEXT, KEY_Q, BOTH, XKB_KEY_X, NEXT, KEY_KP7, BOTH, KS("U2714"), NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, /* * XXX: de(neo) uses shift(both_capslock) which causes * the interesting result in the next line. Since it's * a key release, it doesn't actually lock the modifier, * and applications by-and-large ignore the keysym on * release(?). Is this a problem? */ KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, /* Level 2 with the Lock modifier. */ KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_RIGHTSHIFT, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_6, BOTH, XKB_KEY_6, NEXT, KEY_H, BOTH, XKB_KEY_S, NEXT, KEY_KP3, BOTH, XKB_KEY_KP_3, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_RIGHTSHIFT, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, /* Level 3. */ KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_6, BOTH, XKB_KEY_cent, NEXT, KEY_Q, BOTH, XKB_KEY_ellipsis, NEXT, KEY_KP7, BOTH, KS("U2195"), NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT, /* Level 4. */ KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_5, BOTH, XKB_KEY_malesymbol, NEXT, KEY_E, BOTH, XKB_KEY_Greek_lambda, NEXT, KEY_SPACE, BOTH, XKB_KEY_nobreakspace, NEXT, KEY_KP8, BOTH, XKB_KEY_intersection, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT, /* Level 5. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, /* XXX: xkeyboard-config is borked when de(neo) is * not the first group - not our fault. We test * Level5 separately below with only de(neo). */ /* KEY_5, BOTH, XKB_KEY_periodcentered, NEXT, */ /* KEY_E, BOTH, XKB_KEY_Up, NEXT, */ /* KEY_SPACE, BOTH, XKB_KEY_KP_0, NEXT, */ /* KEY_KP8, BOTH, XKB_KEY_KP_Up, NEXT, */ KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_V, BOTH, XKB_KEY_p, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, rules, "", "de", "neo", ""); assert(keymap); assert(test_key_seq(keymap, /* Level 5. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_5, BOTH, XKB_KEY_periodcentered, NEXT, KEY_E, BOTH, XKB_KEY_Up, NEXT, KEY_SPACE, BOTH, XKB_KEY_KP_0, NEXT, KEY_KP8, BOTH, XKB_KEY_KP_Up, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Lock, NEXT, /* Level 6. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT, KEY_5, BOTH, XKB_KEY_NoSymbol, NEXT, KEY_8, BOTH, XKB_KEY_ISO_Left_Tab, NEXT, KEY_E, BOTH, XKB_KEY_Up, NEXT, KEY_SPACE, BOTH, XKB_KEY_KP_0, NEXT, KEY_KP8, BOTH, XKB_KEY_KP_Up, NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Lock, NEXT, /* Level 7. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_5, BOTH, KS("U2221"), NEXT, KEY_E, BOTH, XKB_KEY_Greek_LAMBDA, NEXT, KEY_SPACE, BOTH, KS("U202F"), NEXT, KEY_KP8, BOTH, KS("U22C2"), NEXT, KEY_ESC, BOTH, XKB_KEY_Escape, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Lock, NEXT, /* Level 8. */ KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level5_Shift, NEXT, KEY_CAPSLOCK, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_RIGHTSHIFT, DOWN, XKB_KEY_Shift_R, NEXT, KEY_TAB, BOTH, XKB_KEY_ISO_Level5_Lock, NEXT, KEY_V, BOTH, XKB_KEY_Greek_pi, NEXT, KEY_RIGHTSHIFT, UP, XKB_KEY_Caps_Lock, NEXT, KEY_V, BOTH, XKB_KEY_asciitilde, NEXT, KEY_CAPSLOCK, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_V, BOTH, XKB_KEY_p, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level5_Lock, NEXT, /* Locks Level 5. */ KEY_V, BOTH, XKB_KEY_Return, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, rules, "", "us,il,ru", "", "grp:alt_shift_toggle_bidir,grp:menu_toggle"); assert(keymap); assert(test_key_seq(keymap, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, FINISH)); assert(test_key_seq(keymap, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, FINISH)); /* Check backwards (negative) group switching and wrapping. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_LEFTALT, BOTH, XKB_KEY_ISO_Prev_Group, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, rules, "", "us,il,ru", "", "grp:switch,grp:lswitch,grp:menu_toggle"); assert(keymap); /* Test depressed group works (Mode_switch). */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); /* Test locked+depressed group works, with wrapping and accumulation. */ assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT, /* Should wrap back to first group. */ KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_H, BOTH, XKB_KEY_h, NEXT, /* Two SetGroup(+1)'s should add up. */ KEY_RIGHTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_Cyrillic_er, NEXT, KEY_LEFTALT, UP, XKB_KEY_Mode_switch, NEXT, KEY_H, BOTH, XKB_KEY_hebrew_yod, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_H, BOTH, XKB_KEY_h, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, rules, "", "us", "euro", ""); assert(keymap); assert(test_key_seq(keymap, KEY_5, BOTH, XKB_KEY_5, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_5, BOTH, XKB_KEY_EuroSign, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_file( ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "keymaps/unbound-vmod.xkb" ); assert(keymap); assert(test_key_seq(keymap, KEY_H, BOTH, XKB_KEY_h, NEXT, KEY_Z, BOTH, XKB_KEY_y, NEXT, KEY_MINUS, BOTH, XKB_KEY_ssharp, NEXT, KEY_Z, BOTH, XKB_KEY_y, FINISH)); xkb_keymap_unref(keymap); keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, rules, "applealu_ansi", "us", "", "terminate:ctrl_alt_bksp"); assert(keymap); assert(test_key_seq(keymap, KEY_5, BOTH, XKB_KEY_5, NEXT, KEY_KP1, BOTH, XKB_KEY_KP_1, NEXT, KEY_NUMLOCK, BOTH, XKB_KEY_Clear, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_KP1, BOTH, XKB_KEY_KP_1, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_KP1, BOTH, XKB_KEY_KP_1, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_KP1, BOTH, XKB_KEY_KP_1, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock, NEXT, KEY_A, BOTH, XKB_KEY_a, FINISH)); xkb_keymap_unref(keymap); } int main(void) { test_init(); struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); /* Usual rules */ test_keymaps(ctx, "evdev"); /* Special rules to make no use of modmaps */ test_keymaps(ctx, "evdev-pure-virtual-mods"); test_simultaneous_modifier_clear(ctx); test_group_lock(ctx); test_group_latch(ctx); test_mod_set(ctx); test_mod_lock(ctx); test_mod_latch(ctx); test_explicit_actions(ctx); xkb_context_unref(ctx); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/keysym-case-mapping.h000066400000000000000000000013421510033435100236760ustar00rootroot00000000000000// WARNING: This file is automatically generated by: scripts/update-keysyms-case-mappings.py #pragma once #include "config.h" #include #include /* Unicode code points used in case mapping exceptions */ #define LATIN_SMALL_LETTER_SHARP_S 0x00df // ß #define LATIN_CAPITAL_LETTER_SHARP_S 0x1e9e // ẞ static inline uint32_t to_simple_lower(uint32_t cp) { return (uint32_t)u_tolower((UChar32) cp); } static inline uint32_t to_simple_upper(uint32_t cp) { switch (cp) { /* Some exceptions */ case LATIN_SMALL_LETTER_SHARP_S: return LATIN_CAPITAL_LETTER_SHARP_S; /* Default to the Unicode simple mapping */ default: return (uint32_t)u_toupper((UChar32) cp); } } xkbcommon-libxkbcommon-54ee7ac/test/keysym-case-mapping.h.jinja000066400000000000000000000017061510033435100247740ustar00rootroot00000000000000// WARNING: This file is automatically generated by: {{ script }} #pragma once #include "config.h" #include #include /* Unicode code points used in case mapping exceptions */ {% for lower, upper in upper_exceptions.items() %} #define {{ lower | code_point_name_constant(padding=28) }} {{ lower | code_point }} // {{ lower }} #define {{ upper | code_point_name_constant(padding=28) }} {{ upper | code_point }} // {{ upper }} {% endfor %} static inline uint32_t to_simple_lower(uint32_t cp) { return (uint32_t)u_tolower((UChar32) cp); } static inline uint32_t to_simple_upper(uint32_t cp) { switch (cp) { /* Some exceptions */ {% for lower, upper in upper_exceptions.items() %} case {{ lower | code_point_name_constant }}: return {{ upper | code_point_name_constant }}; {% endfor %} /* Default to the Unicode simple mapping */ default: return (uint32_t)u_toupper((UChar32) cp); } } xkbcommon-libxkbcommon-54ee7ac/test/keysym-unicode.c000066400000000000000000000155471510033435100227670ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include "test.h" #ifdef _WIN32 int main(void) { test_init(); return SKIP_TEST; } #else #include #include #include #include #include #include "xkbcommon/xkbcommon-keysyms.h" #include "xkbcommon/xkbcommon.h" #include "test.h" #include "utils.h" #include "src/keysym.h" static void test_unicode_keysyms_consistency(uint32_t start, uint32_t end) { static_assert(XKB_KEYSYM_NAME_MAX_SIZE > XKB_KEYSYM_UTF8_MAX_SIZE, "Buffer too small"); char buffer[XKB_KEYSYM_NAME_MAX_SIZE] = {0}; char utf8[XKB_KEYSYM_UTF8_MAX_SIZE] = {0}; for (uint32_t cp = start; cp <= end; cp++) { xkb_keysym_t unicode = XKB_KEYSYM_UNICODE_OFFSET + cp; xkb_keysym_t canonical = xkb_utf32_to_keysym(cp); int count = xkb_keysym_get_name(unicode, buffer, sizeof(buffer)); assert(count > 0); if (cp == 0 || is_surrogate(cp)) { /* * Invalid code points */ /* No conversion from code point */ assert(canonical == XKB_KEY_NoSymbol); /* No conversion to code point */ assert(xkb_keysym_to_utf32(unicode) == 0); char *end_ptr = NULL; if (cp == 0) { /* Corresponding name hexadecimal format, unchanged */ assert(strtoull(buffer, &end_ptr, 16) == unicode); } else { /* Unicode notation */ assert(count == 5 && buffer[0] == 'U'); assert(strtoull(buffer + 1, &end_ptr, 16) == cp); } assert(*end_ptr == '\0'); /* Roundtrip hexadecimal name */ xkb_keysym_t ks = xkb_keysym_from_name(buffer, XKB_KEYSYM_NO_FLAGS); assert(ks == unicode); /* Check Unicode format */ snprintf(buffer, sizeof(buffer), "U%"PRIX32, cp); ks = xkb_keysym_from_name(buffer, XKB_KEYSYM_NO_FLAGS); assert((cp == 0 && ks == XKB_KEY_NoSymbol) ^ (is_surrogate(cp) && ks == unicode)); /* Cannot convert to UTF-8 */ count = xkb_keysym_to_utf8(unicode, buffer, sizeof(buffer)); assert(count == 0); } else { /* * Valid code points */ /* Canonical keysym may be different but is set */ assert_printf((canonical == unicode) ^ ((0x20 <= cp && cp <= 0x100 && cp != 0x7f && canonical == cp) || (canonical != unicode && canonical != XKB_KEY_NoSymbol && (canonical != cp || canonical == XKB_KEY_EuroSign))), "Code point: U+%04"PRIX32", Unicode: %#"PRIx32", " "canonical: %#"PRIx32"\n", cp, unicode, canonical); /* Conversion to code point has the same expected result */ assert(xkb_keysym_to_utf32(unicode) == cp); assert(xkb_keysym_to_utf32(canonical) == cp); /* roundtrip */ /* Check name roundtrip */ xkb_keysym_t ks = xkb_keysym_from_name(buffer, XKB_KEYSYM_NO_FLAGS); assert((unicode != canonical && ks == canonical) ^ (ks == unicode)); /* Can use Unicode format */ if (buffer[0] == 'U' && count > 4 && is_digit(buffer[1])) { /* Name already a Unicode notation: skip. * Note that the heuristic may fail to detect a Unicode notation, * but it is only meant to make the overall test faster. */ } else { snprintf(buffer, sizeof(buffer), "U%"PRIX32, cp); ks = xkb_keysym_from_name(buffer, XKB_KEYSYM_NO_FLAGS); assert((unicode != canonical && ks == canonical) ^ (ks == unicode)); } /* Roundtrip: numeric hexadecimal format for Unicode keysym */ assert(snprintf(buffer, sizeof(buffer), "%#"PRIx32, unicode) == 9); ks = xkb_keysym_from_name(buffer, XKB_KEYSYM_NO_FLAGS); assert(ks == unicode); /* Can convert to UTF-8 (Unicode keysym) */ count = xkb_keysym_to_utf8(unicode, buffer, sizeof(buffer)); assert(count > 0); if (canonical != unicode) { /* Canonical keysym convert to same UTF-8 */ const int count2 = xkb_keysym_to_utf8(canonical, utf8, sizeof(utf8)); assert(count2 == count); assert(strcmp(buffer, utf8) == 0); /* Roundtrip: numeric hexadecimal format for canonical keysym */ count = xkb_keysym_get_name(canonical, buffer, sizeof(buffer)); assert(count > 0); assert(xkb_keysym_from_name(buffer, XKB_KEYSYM_NO_FLAGS) == canonical); assert(snprintf(buffer, sizeof(buffer), "%#"PRIx32, canonical) > 2); assert(xkb_keysym_from_name(buffer, XKB_KEYSYM_NO_FLAGS) == canonical); } } } } int main(int argc, char *argv[]) { test_init(); unsigned long int NUM_PROCESSES = 0; if (argc > 1) { NUM_PROCESSES = strtoul(argv[1], NULL, 10); } if (NUM_PROCESSES == 0 || NUM_PROCESSES > 32) NUM_PROCESSES = 4; const uint32_t max_codepoint = 0x10ffff; const uint32_t chunk = max_codepoint / NUM_PROCESSES; pid_t pids[NUM_PROCESSES]; for (unsigned long int i = 0; i < NUM_PROCESSES; i++) { pid_t pid = fork(); if (pid == 0) { /* Child */ const uint32_t start = i * chunk; const uint32_t end = (i == NUM_PROCESSES - 1) ? max_codepoint : start + chunk; test_unicode_keysyms_consistency(start, end); exit(EXIT_SUCCESS); } else if (pid > 0) { /* Parent */ pids[i] = pid; } else { perror("fork"); return TEST_SETUP_FAILURE; } } /* Wait for children */ int exit_code = EXIT_SUCCESS; for (unsigned long int i = 0; i < NUM_PROCESSES; i++) { int status; if (waitpid(pids[i], &status, 0) == -1) { perror("waitpid"); exit_code = EXIT_FAILURE; } else if (WIFEXITED(status)) { int code = WEXITSTATUS(status); if (code != EXIT_SUCCESS) { fprintf(stderr, "Child PID %d exited with code %d\n", pids[i], code); exit_code = EXIT_FAILURE; } } else if (WIFSIGNALED(status)) { fprintf(stderr, "Child PID %d terminated by signal %d\n", pids[i], WTERMSIG(status)); exit_code = EXIT_FAILURE; } } return exit_code; } #endif xkbcommon-libxkbcommon-54ee7ac/test/keysym.c000066400000000000000000001343151510033435100213360ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #if HAVE_ICU #include #include #include #include "test/keysym-case-mapping.h" #endif #include "xkbcommon/xkbcommon-keysyms.h" #include "xkbcommon/xkbcommon.h" #include "test.h" #include "utils.h" #include "utils-numbers.h" #include "src/keysym.h" /* For unexported is_lower/upper/keypad() */ #include "test/keysym.h" #include "utils.h" /* Explicit ordered list of modifier keysyms */ static const xkb_keysym_t modifier_keysyms[] = { XKB_KEY_ISO_Lock, XKB_KEY_ISO_Level2_Latch, XKB_KEY_ISO_Level3_Shift, XKB_KEY_ISO_Level3_Latch, XKB_KEY_ISO_Level3_Lock, /* XKB_KEY_ISO_Group_Shift == XKB_KEY_Mode_switch */ XKB_KEY_ISO_Group_Latch, XKB_KEY_ISO_Group_Lock, XKB_KEY_ISO_Next_Group, XKB_KEY_ISO_Next_Group_Lock, XKB_KEY_ISO_Prev_Group, XKB_KEY_ISO_Prev_Group_Lock, XKB_KEY_ISO_First_Group, XKB_KEY_ISO_First_Group_Lock, XKB_KEY_ISO_Last_Group, XKB_KEY_ISO_Last_Group_Lock, 0xfe10, /* Currently unassigned, but xkb_keysym_is_modifier returns true */ XKB_KEY_ISO_Level5_Shift, XKB_KEY_ISO_Level5_Latch, XKB_KEY_ISO_Level5_Lock, XKB_KEY_Mode_switch, XKB_KEY_Num_Lock, XKB_KEY_Shift_L, XKB_KEY_Shift_R, XKB_KEY_Control_L, XKB_KEY_Control_R, XKB_KEY_Caps_Lock, XKB_KEY_Shift_Lock, XKB_KEY_Meta_L, XKB_KEY_Meta_R, XKB_KEY_Alt_L, XKB_KEY_Alt_R, XKB_KEY_Super_L, XKB_KEY_Super_R, XKB_KEY_Hyper_L, XKB_KEY_Hyper_R }; #define MIN_MODIFIER_KEYSYM modifier_keysyms[0] #define MAX_MODIFIER_KEYSYM modifier_keysyms[ARRAY_SIZE(modifier_keysyms) - 1] static void test_modifiers_table(void) { xkb_keysym_t ks = XKB_KEY_NoSymbol; /* Ensure ordered array */ for (size_t k = 0; k < ARRAY_SIZE(modifier_keysyms); k++) { assert_printf(ks < modifier_keysyms[k], "modifier_keysyms[] is not ordered: 0x%04"PRIx32">=0x%04"PRIx32"\n", ks, modifier_keysyms[k]); ks = modifier_keysyms[k]; } /* Unassigned keysym */ assert(!xkb_keysym_is_assigned(0xfe10)); } static bool test_modifier(xkb_keysym_t ks) { if (ks < MIN_MODIFIER_KEYSYM || ks > MAX_MODIFIER_KEYSYM) return false; for (size_t k = 0; k < ARRAY_SIZE(modifier_keysyms); k++) { if (ks == modifier_keysyms[k]) return true; } return false; } static bool test_keypad(xkb_keysym_t ks, char *name) { const char prefix[] = "KP_"; return strncmp(prefix, name, sizeof(prefix) - 1) == 0; } static int test_string(const char *string, xkb_keysym_t expected) { xkb_keysym_t keysym; keysym = xkb_keysym_from_name(string, XKB_KEYSYM_NO_FLAGS); fprintf(stderr, "Expected string %s -> %x\n", string, expected); fprintf(stderr, "Received string %s -> %x\n\n", string, keysym); return keysym == expected; } static int test_casestring(const char *string, xkb_keysym_t expected) { xkb_keysym_t keysym; keysym = xkb_keysym_from_name(string, XKB_KEYSYM_CASE_INSENSITIVE); fprintf(stderr, "Expected casestring %s -> %x\n", string, expected); fprintf(stderr, "Received casestring %s -> %x\n\n", string, keysym); return keysym == expected; } static void test_ambiguous_icase_names(const struct ambiguous_icase_ks_names_entry *entry) { for (int k = 0; k < entry->count; k++) { /* Check expected result */ assert(test_casestring(entry->names[k], entry->keysym)); /* If the keysym is cased, then check the resulting keysym is lower-cased */ xkb_keysym_t keysym = xkb_keysym_from_name(entry->names[k], 0); if (xkb_keysym_is_lower(keysym) || xkb_keysym_is_upper_or_title(keysym)) { assert(xkb_keysym_is_lower(entry->keysym)); } } } static int test_keysym(xkb_keysym_t keysym, const char *expected) { char s[XKB_KEYSYM_NAME_MAX_SIZE]; xkb_keysym_get_name(keysym, s, sizeof(s)); fprintf(stderr, "Expected keysym %#06"PRIx32" -> %s\n", keysym, expected); fprintf(stderr, "Received keysym %#06"PRIx32" -> %s\n\n", keysym, s); return streq(s, expected); } static bool test_deprecated(xkb_keysym_t keysym, const char *name, bool expected_deprecated, const char *expected_reference) { const char *reference; bool deprecated = xkb_keysym_is_deprecated(keysym, name, &reference); fprintf(stderr, "Expected keysym %#06"PRIx32" -> deprecated: %d, reference: %s\n", keysym, expected_deprecated, expected_reference); fprintf(stderr, "Received keysym %#06"PRIx32" -> deprecated: %d, reference: %s\n", keysym, deprecated, reference); return deprecated == expected_deprecated && ( (reference == NULL && expected_reference == NULL) || (reference != NULL && expected_reference != NULL && strcmp(reference, expected_reference) == 0) ); } static int test_utf8(xkb_keysym_t keysym, const char *expected) { char s[XKB_KEYSYM_UTF8_MAX_SIZE]; int ret; ret = xkb_keysym_to_utf8(keysym, s, sizeof(s)); if (ret <= 0) return ret; assert(expected != NULL); fprintf(stderr, "Expected keysym %#06"PRIx32" -> %s (%zu bytes)\n", keysym, expected, strlen(expected)); fprintf(stderr, "Received keysym %#06"PRIx32" -> %s (%zu bytes)\n\n", keysym, s, strlen(s)); return streq(s, expected); } #if HAVE_ICU static UVersionInfo xkb_unicode_version = XKB_KEYSYM_UNICODE_VERSION; static UVersionInfo icu_unicode_version; static inline int compare_unicode_version(const UVersionInfo v1, const UVersionInfo v2) { return memcmp(v1,v2,sizeof(UVersionInfo)); } /* Unicode assertion * In case the test fails, do not raise an exception if there is * an ICU version mismatch with our Unicode version. */ #define uassert_printf(cp, cond, ...) \ if (!(cond)) { \ fprintf(stderr, "Assertion failure: " __VA_ARGS__); \ UVersionInfo char_age; \ u_charAge((UChar32)cp, char_age); \ if (compare_unicode_version(char_age, xkb_unicode_version) > 0) { \ fprintf(stderr, \ "[WARNING] ICU version mismatch: " \ "too recent for code point: "CODE_POINT"\n", cp); \ } else if (compare_unicode_version(icu_unicode_version, xkb_unicode_version) < 0) { \ fprintf(stderr, \ "[WARNING] ICU version mismatch: " \ "too old for code point: "CODE_POINT"\n", cp); \ } else { \ assert(cond); \ } \ } #define KEYSYM "0x%04"PRIx32 #define CODE_POINT "U+%04"PRIX32 static void test_icu_case_mappings(xkb_keysym_t ks) { uint32_t cp = xkb_keysym_to_utf32(ks); /* Check predicates */ bool is_lower = xkb_keysym_is_lower(ks); uint32_t expected = !!u_isULowercase((UChar32) cp); uassert_printf(cp, is_lower == expected, "Invalid xkb_keysym_is_lower("KEYSYM") ("CODE_POINT"): " "expected %d, got: %d\n", ks, cp, expected, is_lower); bool is_upper_or_title = xkb_keysym_is_upper_or_title(ks); expected = !!(u_isUUppercase((UChar32) cp) || u_istitle((UChar32) cp)); uassert_printf(cp, is_upper_or_title == expected, "Invalid xkb_keysym_is_upper_or_title("KEYSYM") ("CODE_POINT"): " "expected %d, got: %d\n", ks, cp, expected, is_upper_or_title); assert(is_lower != is_upper_or_title || !is_lower); /* Check lower case mapping */ xkb_keysym_t ks_mapped = xkb_keysym_to_lower(ks); expected = to_simple_lower(cp); if (u_istitle((UChar32) cp)) { /* Check that title case letter have simple lower case mappings */ uassert_printf(cp, ks_mapped != ks && expected != cp, "Invalid title case lower transformation. " "Expected keysym: "KEYSYM" != "KEYSYM" " "and code point "CODE_POINT" != "CODE_POINT"\n", ks_mapped, ks, expected, cp); } if (ks_mapped && ks_mapped != ks) { /* Given keysym has been transformed to lower-case */ uint32_t cp_mapped = xkb_keysym_to_utf32(ks_mapped); uint32_t got = cp_mapped; uassert_printf(cp, got == expected, "Invalid xkb_keysym_to_lower("KEYSYM") == "KEYSYM": " "expected "CODE_POINT", got: "CODE_POINT"\n", ks, ks_mapped, expected, got); uassert_printf(cp, is_upper_or_title, "Expected upper case for keysym "KEYSYM" ("CODE_POINT")\n", ks, cp); got = !!xkb_keysym_is_lower(ks_mapped); expected = !!u_isULowercase((UChar32) cp_mapped); uassert_printf(cp_mapped, got == expected, "Invalid xkb_keysym_is_lower("KEYSYM") ("CODE_POINT"): " "expected %d, got: %d (tested keysym: "KEYSYM")\n", ks_mapped, cp_mapped, expected, got, ks); } else if (expected != cp) { /* Missing case mapping; the corresponding predicate must be consistent. */ fprintf(stderr, "[WARNING] Missing lower case mapping for "KEYSYM": " "expected "CODE_POINT", got: "CODE_POINT"\n", ks, expected, cp); uassert_printf(cp, !xkb_keysym_is_upper_or_title(ks), "Invalid xkb_keysym_is_upper_or_title("KEYSYM") ("CODE_POINT"): " "expected false, got: true\n", ks, cp); } /* Check upper case mapping */ ks_mapped = xkb_keysym_to_upper(ks); expected = to_simple_upper(cp); if (u_istitle((UChar32) cp)) { /* Check title case upper mapping; may be: * • simple: 1 code point, or * • special: muliple code points */ UChar cp_string[2] = {0}; UChar cp_expected_string[8] = {0}; UBool isError = false; int32_t offset = 0; /* Convert code point to UTF-16 string */ U16_APPEND(cp_string, offset, (int32_t) ARRAY_SIZE(cp_string), cp, isError); UErrorCode pErrorCode = U_ZERO_ERROR; /* Unicode full upper mapping */ int32_t length = u_strToUpper(cp_expected_string, ARRAY_SIZE(cp_expected_string), cp_string, offset, "C", &pErrorCode); length = u_countChar32(cp_expected_string, length); if (length == 1) { /* Simple upper case mapping: one-to-one. */ uint32_t cp_mapped = xkb_keysym_to_utf32(ks_mapped); uassert_printf(cp, !isError && pErrorCode == U_ZERO_ERROR && ks_mapped != ks && expected != cp && u_isUUppercase(cp_mapped), "Invalid title case simple upper transformation. " "Expected keysym: "KEYSYM" != "KEYSYM" " "and code point "CODE_POINT" != "CODE_POINT"\n", ks_mapped, ks, expected, cp); } else { /* Special upper case mapping: maps to multiple code points. * We do not handle those, so our mapping is the original. */ uassert_printf(cp, !isError && pErrorCode == U_ZERO_ERROR && ks_mapped == ks && expected == cp && length > 1, "Invalid title case special upper transformation. " "Expected keysym: "KEYSYM" == "KEYSYM" " "and code point "CODE_POINT" == "CODE_POINT"\n", ks_mapped, ks, expected, cp); } } if (ks_mapped && ks_mapped != ks) { /* Given keysym has been transformed to upper-case */ uint32_t cp_mapped = xkb_keysym_to_utf32(ks_mapped); uint32_t got = cp_mapped; uassert_printf(cp, got == expected, "Invalid xkb_keysym_to_upper("KEYSYM") == "KEYSYM": " "expected "CODE_POINT", got: "CODE_POINT"\n", ks, ks_mapped, expected, got); uassert_printf(cp, is_lower || u_istitle(cp), "Expected lower or title case for keysym "KEYSYM" ("CODE_POINT")\n", ks, cp); got = !!xkb_keysym_is_upper_or_title(ks_mapped); expected = !!(u_isUUppercase((UChar32)cp_mapped) || u_istitle((UChar32)cp_mapped)); uassert_printf(cp_mapped, got == expected, "Invalid xkb_keysym_is_upper_or_title("KEYSYM") ("CODE_POINT"): " "expected %d, got: %d (tested keysym: "KEYSYM")\n", ks_mapped, cp_mapped, expected, got, ks); } else if (expected != cp) { /* Missing case mapping; the corresponding predicate must be consistent. */ fprintf(stderr, "[WARNING] Missing upper case mapping for "KEYSYM": " "expected "CODE_POINT", got: "CODE_POINT"\n", ks, expected, cp); uassert_printf(cp, !xkb_keysym_is_lower(ks), "Invalid xkb_keysym_is_lower("KEYSYM") ("CODE_POINT"): " "expected false, got: true\n", ks, cp); } } #endif static void test_github_issue_42(void) { // Verify we are not dependent on locale, Turkish-i problem in particular. if (setlocale(LC_CTYPE, "tr_TR.UTF-8") == NULL) { // The locale is not available, probably; skip. return; } assert(test_string("i", XKB_KEY_i)); assert(test_string("I", XKB_KEY_I)); assert(test_casestring("i", XKB_KEY_i)); assert(test_casestring("I", XKB_KEY_i)); assert(xkb_keysym_to_upper(XKB_KEY_i) == XKB_KEY_I); assert(xkb_keysym_to_lower(XKB_KEY_I) == XKB_KEY_i); setlocale(LC_CTYPE, "C"); } static void get_keysym_name(xkb_keysym_t keysym, char *buffer, size_t size) { int name_length = xkb_keysym_get_name(keysym, buffer, size); if (name_length < 0) { snprintf(buffer, size, "(unknown: %#06"PRIx32")", keysym); } } static int test_utf32_to_keysym(uint32_t ucs, xkb_keysym_t expected) { char expected_name[XKB_KEYSYM_NAME_MAX_SIZE]; char actual_name[XKB_KEYSYM_NAME_MAX_SIZE]; xkb_keysym_t actual = xkb_utf32_to_keysym(ucs); get_keysym_name(expected, expected_name, XKB_KEYSYM_NAME_MAX_SIZE); get_keysym_name(actual, actual_name, XKB_KEYSYM_NAME_MAX_SIZE); fprintf(stderr, "Code point %#"PRIx32": expected keysym: %s, actual: %s\n\n", ucs, expected_name, actual_name); return expected == actual; } int main(void) { test_init(); #if HAVE_ICU u_getUnicodeVersion(icu_unicode_version); #endif /* Bounds */ assert(XKB_KEYSYM_MIN == 0); assert(XKB_KEYSYM_MIN < XKB_KEYSYM_MAX); assert(XKB_KEYSYM_MAX <= UINT32_MAX); /* Ensure it fits in xkb_keysym_t */ assert(XKB_KEYSYM_MAX <= INT32_MAX); /* Ensure correct cast to int32_t */ assert(XKB_KEYSYM_MIN_ASSIGNED == XKB_KEYSYM_MIN); assert(XKB_KEYSYM_MIN_ASSIGNED < XKB_KEYSYM_MAX_ASSIGNED); assert(XKB_KEYSYM_MAX_ASSIGNED <= XKB_KEYSYM_MAX); assert(XKB_KEYSYM_MIN_EXPLICIT == XKB_KEYSYM_MIN_ASSIGNED); assert(XKB_KEYSYM_MIN_EXPLICIT < XKB_KEYSYM_MAX_EXPLICIT); assert(XKB_KEYSYM_MAX_EXPLICIT <= XKB_KEYSYM_MAX_ASSIGNED); assert(XKB_KEYSYM_COUNT_EXPLICIT <= XKB_KEYSYM_MAX_EXPLICIT - XKB_KEYSYM_MIN_EXPLICIT + 1); assert(XKB_KEYSYM_UNICODE_MIN >= XKB_KEYSYM_MIN_EXPLICIT); assert(XKB_KEYSYM_UNICODE_MIN < XKB_KEYSYM_UNICODE_MAX); assert(XKB_KEYSYM_UNICODE_MAX <= XKB_KEYSYM_MAX_EXPLICIT); /* Assigned keysyms */ assert(xkb_keysym_is_assigned(XKB_KEYSYM_MIN)); assert(xkb_keysym_is_assigned(XKB_KEYSYM_MIN_ASSIGNED)); assert(xkb_keysym_is_assigned(XKB_KEY_space)); assert(xkb_keysym_is_assigned(XKB_KEY_nobreakspace)); assert(xkb_keysym_is_assigned(XKB_KEY_Aogonek)); assert(xkb_keysym_is_assigned(XKB_KEY_Hstroke)); assert(xkb_keysym_is_assigned(XKB_KEY_kra)); assert(xkb_keysym_is_assigned(XKB_KEY_braille_dot_1)); assert(xkb_keysym_is_assigned(XKB_KEY_XF86KbdLcdMenu5)); assert(xkb_keysym_is_assigned(XKB_KEY_Shift_L)); assert(xkb_keysym_is_assigned(XKB_KEY_XF86MonBrightnessUp)); assert(xkb_keysym_is_assigned(XKB_KEY_VoidSymbol)); assert(xkb_keysym_is_assigned(XKB_KEYSYM_UNICODE_MIN)); assert(xkb_keysym_is_assigned((XKB_KEYSYM_UNICODE_MIN + XKB_KEYSYM_UNICODE_MAX) / 2)); assert(xkb_keysym_is_assigned(XKB_KEYSYM_UNICODE_MAX)); assert(xkb_keysym_is_assigned(XKB_KEYSYM_MAX_ASSIGNED)); assert(!xkb_keysym_is_assigned(XKB_KEYSYM_MAX)); test_modifiers_table(); /* Check xkb_keysym_get_explicit_names works */ const char* aliases[XKB_KEYSYM_EXPLICIT_ALIASES_MAX] = {0}; int aliases_count = xkb_keysym_get_explicit_names(XKB_KEY_a, aliases, ARRAY_SIZE(aliases)); assert(aliases_count == 1); assert_streq_not_null("", "a", aliases[0]); aliases_count = xkb_keysym_get_explicit_names(XKB_KEY_ISO_Group_Shift, aliases, ARRAY_SIZE(aliases)); assert(aliases_count == XKB_KEYSYM_EXPLICIT_ALIASES_MAX); assert_streq_not_null("", "Mode_switch", aliases[0]); assert_streq_not_null("", "Arabic_switch", aliases[1]); assert_streq_not_null("", "Greek_switch", aliases[2]); assert_streq_not_null("", "Hangul_switch", aliases[3]); assert_streq_not_null("", "Hebrew_switch", aliases[4]); assert_streq_not_null("", "ISO_Group_Shift", aliases[5]); assert_streq_not_null("", "kana_switch", aliases[6]); assert_streq_not_null("", "script_switch", aliases[7]); assert_streq_not_null("", "SunAltGraph", aliases[8]); struct xkb_keysym_iterator *iter = xkb_keysym_iterator_new(false); xkb_keysym_t ks_prev = XKB_KEYSYM_MIN; uint32_t count = 0; uint32_t count_non_unicode = 0; while (xkb_keysym_iterator_next(iter)) { count++; xkb_keysym_t ks = xkb_keysym_iterator_get_keysym(iter); if (ks < XKB_KEYSYM_UNICODE_MIN || ks > XKB_KEYSYM_UNICODE_MAX) { count_non_unicode++; } else { const uint32_t cp = ks - XKB_KEYSYM_UNICODE_OFFSET; assert(cp); const xkb_keysym_t ks2 = xkb_utf32_to_keysym(cp); const char *ref; assert_printf(!xkb_keysym_is_deprecated(ks2, NULL, &ref), "Unexpected deprecated keysym 0x%04"PRIx32" " "corresponding to code point U+%04"PRIX32"\n", ks2, cp); const uint32_t cp2 = xkb_keysym_to_utf32(ks2); assert_printf((ks2 == XKB_KEY_NoSymbol && cp2 == 0) ^ (ks2 != XKB_KEY_NoSymbol && cp2 == cp), "Unexpected U+%04"PRIX32" != U+%04"PRIX32" " "for keysym 0x%04"PRIx32"\n", cp2, cp, ks2); } assert(ks > ks_prev || count == 1); ks_prev = ks; /* Check assigned keysyms bounds */ assert((int32_t)XKB_KEYSYM_MIN_ASSIGNED <= (int32_t)ks && ks <= XKB_KEYSYM_MAX_ASSIGNED); /* Check that we do not convert UTF-32 into a deprecated keysyms */ const char *ref = NULL; if (xkb_keysym_is_deprecated(ks, NULL, &ref)) { const uint32_t cp = xkb_keysym_to_utf32(ks); if (cp != 0) { assert_printf(xkb_utf32_to_keysym(cp) != ks, "Unexpected xkb_utf32_to_keysym(0x%04"PRIX32") == 0x%04"PRIx32"\n", cp, ks); } } /* Check utf8 */ /* Older implementation required 7 bytes for old UTF-8 (see RFC 2279) */ char utf8[7]; int needed = xkb_keysym_to_utf8(ks, utf8, sizeof(utf8)); assert(0 <= needed && needed <= XKB_KEYSYM_UTF8_MAX_SIZE); /* Check maximum name length (`needed` does not include the ending NULL) */ char name[XKB_KEYSYM_NAME_MAX_SIZE]; needed = xkb_keysym_iterator_get_name(iter, name, sizeof(name)); assert(0 < needed && (size_t)needed <= sizeof(name) - 1); /* Test modifier keysyms */ bool expected = test_modifier(ks); bool got = xkb_keysym_is_modifier(ks); assert_printf(got == expected, "xkb_keysym_is_modifier(0x%04"PRIx32"): expected %d, got: %d\n", ks, expected, got); /* Test keypad keysyms */ expected = test_keypad(ks, name); got = xkb_keysym_is_keypad(ks); assert_printf(got == expected, "xkb_keysym_is_keypad(0x%04"PRIx32") \"%s\": " "expected %d, got: %d\n", ks, name, expected, got); /* Ensure no explicit name would clash with the Unicode notation */ if (xkb_keysym_iterator_is_explicitly_named(iter)) { const int n = xkb_keysym_get_explicit_names(ks, aliases, ARRAY_SIZE(aliases)); assert(n > 0); for (int k = 0; k < n; k++) { const char* const alias = aliases[k]; if (alias[0] != 'U') continue; uint32_t cp = 0; const int r = parse_hex_to_uint32_t(name + 1, SIZE_MAX, &cp); /* Either none or incomplete parsing */ assert((r == 0) ^ (r > 0 && name[r + 1] != '\0')); } } #if HAVE_ICU /* Check case mappings */ test_icu_case_mappings(ks); #endif } xkb_keysym_iterator_unref(iter); assert(ks_prev == XKB_KEYSYM_MAX_ASSIGNED); assert(count == XKB_KEYSYM_UNICODE_MAX - XKB_KEYSYM_UNICODE_MIN + 1 + count_non_unicode); /* Named keysyms */ assert(test_string("NoSymbol", XKB_KEY_NoSymbol)); assert(test_string("Undo", 0xFF65)); assert(test_string("UNDO", XKB_KEY_NoSymbol)); /* Require XKB_KEYSYM_CASE_INSENSITIVE */ assert(test_string("ThisKeyShouldNotExist", XKB_KEY_NoSymbol)); assert(test_string("XF86_Switch_VT_5", 0x1008FE05)); assert(test_string("VoidSymbol", 0xFFFFFF)); assert(test_string("0", 0x30)); assert(test_string("9", 0x39)); assert(test_string("a", 0x61)); assert(test_string("A", 0x41)); assert(test_string("ch", 0xfea0)); assert(test_string("Ch", 0xfea1)); assert(test_string("CH", 0xfea2)); assert(test_string("THORN", 0x00de)); assert(test_string("Thorn", 0x00de)); assert(test_string("thorn", 0x00fe)); assert(test_string(" thorn", XKB_KEY_NoSymbol)); assert(test_string("thorn ", XKB_KEY_NoSymbol)); #define LONGEST_NAME STRINGIFY2(XKB_KEYSYM_LONGEST_NAME) #define XKB_KEY_LONGEST_NAME CONCAT2(XKB_KEY_, XKB_KEYSYM_LONGEST_NAME) assert(test_string(LONGEST_NAME, XKB_KEY_LONGEST_NAME)); #define LONGEST_CANONICAL_NAME STRINGIFY2(XKB_KEYSYM_LONGEST_CANONICAL_NAME) #define XKB_KEY_LONGEST_CANONICAL_NAME CONCAT2(XKB_KEY_, XKB_KEYSYM_LONGEST_CANONICAL_NAME) assert(test_string(LONGEST_CANONICAL_NAME, XKB_KEY_LONGEST_CANONICAL_NAME)); /* Decimal keysyms are not supported (digits are special cases) */ assert(test_string("-1", XKB_KEY_NoSymbol)); assert(test_string("10", XKB_KEY_NoSymbol)); assert(test_string("010", XKB_KEY_NoSymbol)); assert(test_string("4567", XKB_KEY_NoSymbol)); /* Unicode: test various ranges */ assert(test_string("U0000", XKB_KEY_NoSymbol)); /* Min Unicode, first ASCII ctrl */ assert(test_string("U0001", 0x01000001)); /* ASCII ctrl without named keysym */ assert(test_string("U000A", 0x0000ff0a)); /* ASCII ctrl mapping to function keysym */ assert(test_string("U001F", 0x0100001f)); /* Last ASCII ctrl before first printable */ assert(test_string("U0020", 0x00000020)); /* First ASCII printable */ assert(test_string("U007E", 0x0000007e)); assert(test_string("U007F", 0x0000ffff)); /* Last ASCII code point */ assert(test_string("U0080", 0x01000080)); /* First non-ASCII code point */ assert(test_string("U009F", 0x0100009f)); assert(test_string("U00A0", 0x000000a0)); assert(test_string("U00FF", 0x000000ff)); /* Last Latin-1 code point */ assert(test_string("U0100", 0x01000100)); assert(test_string("U4567", 0x01004567)); assert(test_string("UD7FF", 0x0100d7ff)); assert(test_string("UD800", 0x0100d800)); /* Surrogates */ assert(test_string("UDFFF", 0x0100dfff)); /* Surrogates */ assert(test_string("UE000", 0x0100e000)); assert(test_string("UFDCF", 0x0100fdcf)); assert(test_string("UFDD0", 0x0100fdd0)); /* Noncharacter */ assert(test_string("UFDEF", 0x0100fdef)); /* Noncharacter */ assert(test_string("UFDF0", 0x0100fdf0)); assert(test_string("UFFFD", 0x0100fffd)); assert(test_string("UFFFE", 0x0100fffe)); /* Noncharacter */ assert(test_string("UFFFF", 0x0100ffff)); /* Noncharacter */ assert(test_string("U10000", 0x01010000)); assert(test_string("U1F4A9", 0x0101F4A9)); assert(test_string("U10FFFF", XKB_KEYSYM_UNICODE_MAX)); /* Max Unicode */ assert(test_string("U110000", XKB_KEY_NoSymbol)); /* Unicode: test syntax */ assert(test_string("U00004567", 0x01004567)); /* OK: 8 digits */ assert(test_string("U000004567", XKB_KEY_NoSymbol)); /* ERR: 9 digits */ assert(test_string("U+4567", XKB_KEY_NoSymbol)); /* ERR: Standard Unicode notation */ assert(test_string("U+4567ffff", XKB_KEY_NoSymbol)); assert(test_string("U+4567ffffff", XKB_KEY_NoSymbol)); assert(test_string("U-456", XKB_KEY_NoSymbol)); /* No negative number */ assert(test_string("U456w", XKB_KEY_NoSymbol)); /* Not hexadecimal digit */ assert(test_string("U4567 ", XKB_KEY_NoSymbol)); assert(test_string(" U4567", XKB_KEY_NoSymbol)); assert(test_string("U 4567", XKB_KEY_NoSymbol)); assert(test_string("U +4567", XKB_KEY_NoSymbol)); assert(test_string("u4567", XKB_KEY_NoSymbol)); /* Require XKB_KEYSYM_CASE_INSENSITIVE */ /* Hexadecimal: test ranges */ assert(test_string(STRINGIFY2(XKB_KEYSYM_MIN), XKB_KEY_NoSymbol)); /* Min keysym */ assert(test_string("0x1", 0x00000001)); assert(test_string("0x01234567", 0x01234567)); assert(test_string("0x09abcdef", 0x09abcdef)); assert(test_string(STRINGIFY2(XKB_KEYSYM_UNICODE_OFFSET), XKB_KEYSYM_UNICODE_OFFSET)); assert(test_string("0x01000001", 0x01000001)); assert(test_string("0x0100000a", 0x0100000a)); assert(test_string("0x0100001f", 0x0100001f)); assert(test_string("0x01000020", 0x01000020)); assert(test_string("0x0100007e", 0x0100007e)); assert(test_string("0x0100007f", 0x0100007f)); assert(test_string("0x01000080", 0x01000080)); assert(test_string("0x0100009f", 0x0100009f)); assert(test_string("0x010000a0", 0x010000a0)); assert(test_string("0x010000ff", 0x010000ff)); assert(test_string(STRINGIFY2(XKB_KEYSYM_UNICODE_MIN), XKB_KEYSYM_UNICODE_MIN)); assert(test_string("0x0100d7ff", 0x0100d7ff)); assert(test_string(STRINGIFY2(XKB_KEYSYM_UNICODE_SURROGATE_MIN), XKB_KEYSYM_UNICODE_SURROGATE_MIN)); assert(test_string(STRINGIFY2(XKB_KEYSYM_UNICODE_SURROGATE_MAX), XKB_KEYSYM_UNICODE_SURROGATE_MAX)); assert(test_string("0x0100e000", 0x0100e000)); assert(test_string("0x0100fdcf", 0x0100fdcf)); assert(test_string("0x0100fdd0", 0x0100fdd0)); /* Noncharacter */ assert(test_string("0x0100fdef", 0x0100fdef)); /* Noncharacter */ assert(test_string("0x0100fdf0", 0x0100fdf0)); assert(test_string("0x0100fffd", 0x0100fffd)); assert(test_string("0x0100fffe", 0x0100fffe)); /* Noncharacter */ assert(test_string("0x0100ffff", 0x0100ffff)); /* Noncharacter */ assert(test_string("0x01010000", 0x01010000)); assert(test_string("0x0101fffe", 0x0101fffe)); /* Noncharacter */ assert(test_string("0x0101ffff", 0x0101ffff)); /* Noncharacter */ assert(test_string(STRINGIFY2(XKB_KEYSYM_UNICODE_MAX), XKB_KEYSYM_UNICODE_MAX)); assert(test_string("0x01110000", 0x1110000)); /* XKB_KEYSYM_UNICODE_MAX + 1 */ assert(test_string(STRINGIFY2(XKB_KEYSYM_MAX), XKB_KEYSYM_MAX)); /* Max keysym */ assert(test_string("0x20000000", XKB_KEY_NoSymbol)); assert(test_string("0xffffffff", XKB_KEY_NoSymbol)); assert(test_string("0x100000000", XKB_KEY_NoSymbol)); /* Hexadecimal: test syntax */ assert(test_string("0x10203040", 0x10203040)); /* OK: 8 digits */ assert(test_string("0x102030400", XKB_KEY_NoSymbol)); /* ERR: 9 digits */ assert(test_string("0x01020304", 0x1020304)); /* OK: 8 digits, starts with 0 */ assert(test_string("0x010203040", XKB_KEY_NoSymbol)); /* ERR: 9 digits, starts with 0 */ assert(test_string("0x+10203040", XKB_KEY_NoSymbol)); assert(test_string("0x01020304w", XKB_KEY_NoSymbol)); /* Not hexadecimal digit */ assert(test_string("0x102030 ", XKB_KEY_NoSymbol)); assert(test_string("0x 102030", XKB_KEY_NoSymbol)); assert(test_string(" 0x102030", XKB_KEY_NoSymbol)); assert(test_string("0x +10203040", XKB_KEY_NoSymbol)); assert(test_string("0x-10203040", XKB_KEY_NoSymbol)); assert(test_string("0X10203040", XKB_KEY_NoSymbol)); /* Require XKB_KEYSYM_CASE_INSENSITIVE */ assert(test_string("10203040", XKB_KEY_NoSymbol)); /* Missing prefix/decimal not implemented */ assert(test_string("0b0101", XKB_KEY_NoSymbol)); /* Wrong prefix: binary not implemented */ assert(test_string("0o0701", XKB_KEY_NoSymbol)); /* Wrong prefix: octal not implemented */ assert(test_keysym(0x1008FF56, "XF86Close")); assert(test_keysym(0x0, "NoSymbol")); assert(test_keysym(0x1008FE20, "XF86Ungrab")); assert(test_keysym(XKB_KEYSYM_UNICODE_OFFSET, "0x01000000")); /* Longest names */ assert(test_keysym(XKB_KEY_LONGEST_NAME, LONGEST_NAME)); assert(test_keysym(XKB_KEY_LONGEST_CANONICAL_NAME, LONGEST_CANONICAL_NAME)); /* Canonical names */ assert(test_keysym(XKB_KEY_Henkan, "Henkan_Mode")); assert(test_keysym(XKB_KEY_ISO_Group_Shift, "Mode_switch")); assert(test_keysym(XKB_KEY_dead_perispomeni, "dead_tilde")); assert(test_keysym(XKB_KEY_guillemetleft, "guillemotleft")); assert(test_keysym(XKB_KEY_ordmasculine, "masculine")); assert(test_keysym(XKB_KEY_Greek_lambda, "Greek_lamda")); /* Unicode: ISO-8859-1 (Latin-1 + C0 and C1 control code) */ assert(test_keysym(XKB_KEYSYM_UNICODE_OFFSET, STRINGIFY2(XKB_KEYSYM_UNICODE_OFFSET))); assert(test_keysym(0x01000001, "0x01000001")); assert(test_keysym(0x0100000a, "0x0100000a")); assert(test_keysym(0x0100001f, "0x0100001f")); assert(test_keysym(0x01000020, "0x01000020")); assert(test_keysym(0x0100007e, "0x0100007e")); assert(test_keysym(0x0100007f, "0x0100007f")); assert(test_keysym(0x01000080, "0x01000080")); assert(test_keysym(0x0100009f, "0x0100009f")); assert(test_keysym(0x010000a0, "0x010000a0")); assert(test_keysym(0x010000ff, "0x010000ff")); /* Min Unicode */ assert(test_keysym(XKB_KEYSYM_UNICODE_MIN, "U0100")); assert(test_keysym(0x01001234, "U1234")); /* 16-bit unicode padded to width 4. */ assert(test_keysym(0x010002DE, "U02DE")); /* 32-bit unicode padded to width 8. */ assert(test_keysym(0x0101F4A9, "U1F4A9")); /* Surrogates */ assert(test_keysym(0x0100d7ff, "UD7FF")); assert(test_keysym(XKB_KEYSYM_UNICODE_SURROGATE_MIN, "UD800")); assert(test_keysym(XKB_KEYSYM_UNICODE_SURROGATE_MAX, "UDFFF")); assert(test_keysym(0x0100e000, "UE000")); /* Misc. */ assert(test_keysym(0x0100fdcf, "UFDCF")); /* Noncharacters */ assert(test_keysym(0x0100fdd0, "UFDD0")); assert(test_keysym(0x0100fdef, "UFDEF")); /* Misc */ assert(test_keysym(0x0100fdf0, "UFDF0")); assert(test_keysym(0x0100fffd, "UFFFD")); /* Noncharacters */ assert(test_keysym(0x0100fffe, "UFFFE")); assert(test_keysym(0x0100ffff, "UFFFF")); /* Misc */ assert(test_keysym(0x01010000, "U10000")); /* Max Unicode */ assert(test_keysym(XKB_KEYSYM_UNICODE_MAX, "U10FFFF")); /* Max Unicode + 1 */ assert(test_keysym(0x01110000, "0x01110000")); /* Min keysym. */ assert(test_keysym(XKB_KEYSYM_MIN, "NoSymbol")); /* Max keysym. */ assert(test_keysym(XKB_KEYSYM_MAX, STRINGIFY2(XKB_KEYSYM_MAX))); /* Outside range. */ assert(test_keysym(XKB_KEYSYM_MAX + 1, "Invalid")); assert(test_keysym(0xffffffff, "Invalid")); /* Name is assumed to be correct but we provide garbage */ const char garbage_name[] = "bla bla bla"; assert(test_deprecated(XKB_KEY_NoSymbol, NULL, false, NULL)); assert(test_deprecated(XKB_KEY_NoSymbol, "NoSymbol", false, NULL)); assert(test_deprecated(XKB_KEY_A, "A", false, NULL)); assert(test_deprecated(XKB_KEY_A, NULL, false, NULL)); assert(test_deprecated(XKB_KEY_A, garbage_name, false, NULL)); assert(test_deprecated(XKB_KEY_ETH, "ETH", false, "ETH")); assert(test_deprecated(XKB_KEY_ETH, "Eth", true, "ETH")); assert(test_deprecated(XKB_KEY_ETH, garbage_name, true, "ETH")); assert(test_deprecated(XKB_KEY_topleftradical, NULL, true, NULL)); assert(test_deprecated(XKB_KEY_topleftradical, "topleftradical", true, NULL)); assert(test_deprecated(XKB_KEY_topleftradical, garbage_name, true, NULL)); assert(test_deprecated(XKB_KEY_downcaret, NULL, true, NULL)); assert(test_deprecated(XKB_KEY_downcaret, "downcaret", true, NULL)); /* Mixed deprecated and not deprecated aliases */ assert(test_deprecated(XKB_KEY_Mode_switch, NULL, false, "Mode_switch")); assert(test_deprecated(XKB_KEY_Mode_switch, "Mode_switch", false, "Mode_switch")); assert(test_deprecated(XKB_KEY_Mode_switch, garbage_name, false, "Mode_switch")); assert(test_deprecated(XKB_KEY_ISO_Group_Shift, NULL, false, "Mode_switch")); assert(test_deprecated(XKB_KEY_ISO_Group_Shift, "ISO_Group_Shift", false, "Mode_switch")); assert(test_deprecated(XKB_KEY_ISO_Group_Shift, garbage_name, false, "Mode_switch")); assert(test_deprecated(XKB_KEY_SunAltGraph, NULL, false, "Mode_switch")); assert(test_deprecated(XKB_KEY_SunAltGraph, "SunAltGraph", true, "Mode_switch")); assert(test_deprecated(XKB_KEY_SunAltGraph, garbage_name, false, "Mode_switch")); assert(test_deprecated(XKB_KEY_notapproxeq, "notapproxeq", true, NULL)); assert(test_deprecated(XKB_KEY_approxeq, "approxeq", true, NULL)); /* Unicode is never deprecated */ assert(test_deprecated(0x01002247, "U2247", false, NULL)); assert(test_deprecated(0x01002248, "U2248", false, NULL)); assert(test_deprecated(0x0100250C, "U250C", false, NULL)); assert(test_deprecated(0x0100250C, "0x0100250C", false, NULL)); assert(test_deprecated(XKB_KEYSYM_MAX, NULL, false, NULL)); assert(test_deprecated(XKB_KEYSYM_MAX, NULL, false, NULL)); /* Invalid keysym */ assert(test_deprecated(0xffffffff, NULL, false, NULL)); assert(test_deprecated(0xffffffff, NULL, false, NULL)); assert(test_casestring("Undo", 0xFF65)); assert(test_casestring("UNDO", 0xFF65)); assert(test_casestring("A", 0x61)); assert(test_casestring("a", 0x61)); assert(test_casestring("ThisKeyShouldNotExist", XKB_KEY_NoSymbol)); assert(test_casestring("XF86_Switch_vT_5", 0x1008FE05)); assert(test_casestring("xF86_SwitcH_VT_5", 0x1008FE05)); assert(test_casestring("xF86SwiTch_VT_5", 0x1008FE05)); assert(test_casestring("xF86Switch_vt_5", 0x1008FE05)); assert(test_casestring("VoidSymbol", 0xFFFFFF)); assert(test_casestring("vOIDsymBol", 0xFFFFFF)); assert(test_casestring("U4567", 0x1004567)); assert(test_casestring("u4567", 0x1004567)); assert(test_casestring("0x10203040", 0x10203040)); assert(test_casestring("0X10203040", 0x10203040)); assert(test_casestring("THORN", 0x00fe)); assert(test_casestring("Thorn", 0x00fe)); assert(test_casestring("thorn", 0x00fe)); for (size_t k = 0; k < ARRAY_SIZE(ambiguous_icase_ks_names); k++) { test_ambiguous_icase_names(&ambiguous_icase_ks_names[k]); } assert(test_string("", XKB_KEY_NoSymbol)); assert(test_casestring("", XKB_KEY_NoSymbol)); /* Latin-1 keysyms (1:1 mapping in UTF-32) */ assert(test_utf8(0x0020, "\x20")); assert(test_utf8(0x007e, "\x7e")); assert(test_utf8(0x00a0, "\xc2\xa0")); assert(test_utf8(0x00ff, "\xc3\xbf")); assert(test_utf8(XKB_KEY_y, "y")); assert(test_utf8(XKB_KEY_u, "u")); assert(test_utf8(XKB_KEY_m, "m")); assert(test_utf8(XKB_KEY_Cyrillic_em, "м")); assert(test_utf8(XKB_KEY_Cyrillic_u, "у")); assert(test_utf8(XKB_KEY_exclam, "!")); assert(test_utf8(XKB_KEY_oslash, "ø")); assert(test_utf8(XKB_KEY_hebrew_aleph, "א")); assert(test_utf8(XKB_KEY_Arabic_sheen, "ش")); /* Keysyms with special handling */ assert(test_utf8(XKB_KEY_space, " ")); assert(test_utf8(XKB_KEY_KP_Space, " ")); assert(test_utf8(XKB_KEY_BackSpace, "\b")); assert(test_utf8(XKB_KEY_Escape, "\033")); assert(test_utf8(XKB_KEY_KP_Separator, ",")); assert(test_utf8(XKB_KEY_KP_Decimal, ".")); assert(test_utf8(XKB_KEY_Tab, "\t")); assert(test_utf8(XKB_KEY_KP_Tab, "\t")); assert(test_utf8(XKB_KEY_hyphen, "­")); assert(test_utf8(XKB_KEY_Linefeed, "\n")); assert(test_utf8(XKB_KEY_Return, "\r")); assert(test_utf8(XKB_KEY_KP_Enter, "\r")); assert(test_utf8(XKB_KEY_KP_Equal, "=")); assert(test_utf8(XKB_KEY_9, "9")); assert(test_utf8(XKB_KEY_KP_9, "9")); assert(test_utf8(XKB_KEY_KP_Multiply, "*")); assert(test_utf8(XKB_KEY_KP_Subtract, "-")); /* Unicode keysyms */ assert(test_utf8(XKB_KEYSYM_UNICODE_OFFSET, NULL) == 0); /* Min Unicode codepoint */ assert(test_utf8(0x1000001, "\x01")); /* Currently accepted, but not intended (< 0x100100) */ assert(test_utf8(0x1000020, " ")); /* Currently accepted, but not intended (< 0x100100) */ assert(test_utf8(0x100007f, "\x7f")); /* Currently accepted, but not intended (< 0x100100) */ assert(test_utf8(0x10000a0, "\xc2\xa0")); /* Currently accepted, but not intended (< 0x100100) */ assert(test_utf8(XKB_KEYSYM_UNICODE_MIN, "Ā")); /* Min Unicode keysym */ assert(test_utf8(0x10005d0, "א")); assert(test_utf8(XKB_KEYSYM_UNICODE_MAX, "\xf4\x8f\xbf\xbf")); /* Max Unicode */ assert(test_utf8(XKB_KEYSYM_UNICODE_SURROGATE_MIN, NULL) == 0); assert(test_utf8(XKB_KEYSYM_UNICODE_SURROGATE_MAX, NULL) == 0); assert(test_utf8(XKB_KEYSYM_UNICODE_MAX + 1, NULL) == 0); assert(test_utf32_to_keysym('y', XKB_KEY_y)); assert(test_utf32_to_keysym('u', XKB_KEY_u)); assert(test_utf32_to_keysym('m', XKB_KEY_m)); assert(test_utf32_to_keysym(0x43c, XKB_KEY_Cyrillic_em)); assert(test_utf32_to_keysym(0x443, XKB_KEY_Cyrillic_u)); assert(test_utf32_to_keysym('!', XKB_KEY_exclam)); assert(test_utf32_to_keysym(0xF8, XKB_KEY_oslash)); assert(test_utf32_to_keysym(0x5D0, XKB_KEY_hebrew_aleph)); assert(test_utf32_to_keysym(0x634, XKB_KEY_Arabic_sheen)); assert(test_utf32_to_keysym(0x1F609, 0x0101F609)); // ;) emoji assert(test_utf32_to_keysym('\b', XKB_KEY_BackSpace)); assert(test_utf32_to_keysym('\t', XKB_KEY_Tab)); assert(test_utf32_to_keysym('\n', XKB_KEY_Linefeed)); assert(test_utf32_to_keysym(0x0b, XKB_KEY_Clear)); assert(test_utf32_to_keysym('\r', XKB_KEY_Return)); assert(test_utf32_to_keysym(0x1b, XKB_KEY_Escape)); assert(test_utf32_to_keysym(0x7f, XKB_KEY_Delete)); assert(test_utf32_to_keysym(' ', XKB_KEY_space)); assert(test_utf32_to_keysym(',', XKB_KEY_comma)); assert(test_utf32_to_keysym('.', XKB_KEY_period)); assert(test_utf32_to_keysym('=', XKB_KEY_equal)); assert(test_utf32_to_keysym('9', XKB_KEY_9)); assert(test_utf32_to_keysym('*', XKB_KEY_asterisk)); assert(test_utf32_to_keysym(0xd7, XKB_KEY_multiply)); assert(test_utf32_to_keysym('-', XKB_KEY_minus)); assert(test_utf32_to_keysym(0x10fffd, 0x110fffd)); assert(test_utf32_to_keysym(0x20ac, XKB_KEY_EuroSign)); // Unicode noncharacters assert(test_utf32_to_keysym(0xd800, XKB_KEY_NoSymbol)); // Unicode first surrogate assert(test_utf32_to_keysym(0xdfff, XKB_KEY_NoSymbol)); // Unicode last surrogate assert(test_utf32_to_keysym(0xfdd0, 0x100fdd0)); assert(test_utf32_to_keysym(0xfdef, 0x100fdef)); assert(test_utf32_to_keysym(0xfffe, 0x100fffe)); assert(test_utf32_to_keysym(0xffff, 0x100ffff)); assert(test_utf32_to_keysym(0x7fffe, 0x107fffe)); assert(test_utf32_to_keysym(0x7ffff, 0x107ffff)); assert(test_utf32_to_keysym(0xafffe, 0x10afffe)); assert(test_utf32_to_keysym(0xaffff, 0x10affff)); // Codepoints outside the Unicode planes assert(test_utf32_to_keysym(0x110000, XKB_KEY_NoSymbol)); assert(test_utf32_to_keysym(0xdeadbeef, XKB_KEY_NoSymbol)); assert(xkb_keysym_is_lower(XKB_KEY_a)); assert(xkb_keysym_is_lower(XKB_KEY_Greek_lambda)); assert(xkb_keysym_is_lower(xkb_keysym_from_name("U03b1", 0))); /* GREEK SMALL LETTER ALPHA */ assert(xkb_keysym_is_lower(xkb_keysym_from_name("U03af", 0))); /* GREEK SMALL LETTER IOTA WITH TONOS */ assert(xkb_keysym_is_upper_or_title(XKB_KEY_A)); assert(xkb_keysym_is_upper_or_title(XKB_KEY_Greek_LAMBDA)); assert(xkb_keysym_is_upper_or_title(xkb_keysym_from_name("U0391", 0))); /* GREEK CAPITAL LETTER ALPHA */ assert(xkb_keysym_is_upper_or_title(xkb_keysym_from_name("U0388", 0))); /* GREEK CAPITAL LETTER EPSILON WITH TONOS */ assert(!xkb_keysym_is_upper_or_title(XKB_KEY_a)); assert(!xkb_keysym_is_lower(XKB_KEY_A)); assert(!xkb_keysym_is_lower(XKB_KEY_Return)); assert(!xkb_keysym_is_upper_or_title(XKB_KEY_Return)); assert(!xkb_keysym_is_lower(XKB_KEY_hebrew_aleph)); assert(!xkb_keysym_is_upper_or_title(XKB_KEY_hebrew_aleph)); assert(!xkb_keysym_is_upper_or_title(xkb_keysym_from_name("U05D0", 0))); /* HEBREW LETTER ALEF */ assert(!xkb_keysym_is_lower(xkb_keysym_from_name("U05D0", 0))); /* HEBREW LETTER ALEF */ assert(!xkb_keysym_is_lower(XKB_KEY_8)); assert(!xkb_keysym_is_upper_or_title(XKB_KEY_8)); assert(xkb_keysym_is_keypad(XKB_KEY_KP_Enter)); assert(xkb_keysym_is_keypad(XKB_KEY_KP_6)); assert(xkb_keysym_is_keypad(XKB_KEY_KP_Add)); assert(!xkb_keysym_is_keypad(XKB_KEY_Num_Lock)); assert(!xkb_keysym_is_keypad(XKB_KEY_1)); assert(!xkb_keysym_is_keypad(XKB_KEY_Return)); assert(xkb_keysym_to_upper(XKB_KEY_a) == XKB_KEY_A); assert(xkb_keysym_to_upper(XKB_KEY_A) == XKB_KEY_A); assert(xkb_keysym_to_lower(XKB_KEY_a) == XKB_KEY_a); assert(xkb_keysym_to_lower(XKB_KEY_A) == XKB_KEY_a); assert(xkb_keysym_to_upper(XKB_KEY_Return) == XKB_KEY_Return); assert(xkb_keysym_to_lower(XKB_KEY_Return) == XKB_KEY_Return); assert(xkb_keysym_to_upper(XKB_KEY_Greek_lambda) == XKB_KEY_Greek_LAMBDA); assert(xkb_keysym_to_upper(XKB_KEY_Greek_LAMBDA) == XKB_KEY_Greek_LAMBDA); assert(xkb_keysym_to_lower(XKB_KEY_Greek_lambda) == XKB_KEY_Greek_lambda); assert(xkb_keysym_to_lower(XKB_KEY_Greek_LAMBDA) == XKB_KEY_Greek_lambda); assert(xkb_keysym_to_upper(XKB_KEY_eacute) == XKB_KEY_Eacute); assert(xkb_keysym_to_lower(XKB_KEY_Eacute) == XKB_KEY_eacute); /* S sharp * • U+00DF ß: lower case * • SS: upper case (special mapping, not handled by us) * • U+1E9E ẞ: upper case, only for capitals */ #ifndef XKB_KEY_Ssharp #define XKB_KEY_Ssharp (XKB_KEYSYM_UNICODE_OFFSET + 0x1E9E) #endif assert(!xkb_keysym_is_upper_or_title(XKB_KEY_ssharp)); assert(xkb_keysym_is_upper_or_title(XKB_KEY_Ssharp)); assert(xkb_keysym_is_lower(XKB_KEY_ssharp)); assert(!xkb_keysym_is_lower(XKB_KEY_Ssharp)); assert(xkb_keysym_to_upper(XKB_KEY_ssharp) == XKB_KEY_Ssharp); assert(xkb_keysym_to_lower(XKB_KEY_ssharp) == XKB_KEY_ssharp); assert(xkb_keysym_to_upper(XKB_KEY_Ssharp) == XKB_KEY_Ssharp); assert(xkb_keysym_to_lower(XKB_KEY_Ssharp) == XKB_KEY_ssharp); /* Title case: simple mappings * • U+01F1 DZ: upper case * • U+01F2 Dz: title case * • U+01F3 dz: lower case */ #ifndef XKB_KEY_DZ #define XKB_KEY_DZ (XKB_KEYSYM_UNICODE_OFFSET + 0x01F1) #endif #ifndef XKB_KEY_Dz #define XKB_KEY_Dz (XKB_KEYSYM_UNICODE_OFFSET + 0x01F2) #endif #ifndef XKB_KEY_dz #define XKB_KEY_dz (XKB_KEYSYM_UNICODE_OFFSET + 0x01F3) #endif assert(xkb_keysym_is_upper_or_title(XKB_KEY_DZ)); assert(xkb_keysym_is_upper_or_title(XKB_KEY_Dz)); assert(!xkb_keysym_is_upper_or_title(XKB_KEY_dz)); assert(!xkb_keysym_is_lower(XKB_KEY_DZ)); assert(!xkb_keysym_is_lower(XKB_KEY_Dz)); assert(xkb_keysym_is_lower(XKB_KEY_dz)); assert(xkb_keysym_to_upper(XKB_KEY_DZ) == XKB_KEY_DZ); assert(xkb_keysym_to_lower(XKB_KEY_DZ) == XKB_KEY_dz); assert(xkb_keysym_to_upper(XKB_KEY_Dz) == XKB_KEY_DZ); assert(xkb_keysym_to_lower(XKB_KEY_Dz) == XKB_KEY_dz); assert(xkb_keysym_to_upper(XKB_KEY_dz) == XKB_KEY_DZ); assert(xkb_keysym_to_lower(XKB_KEY_dz) == XKB_KEY_dz); /* Title case: special mappings * • U+1F80 ᾀ: lower case * • U+1F88 ᾈ: title case * • U+1F88 ᾈ: upper case (simple) * • U+1F08 U+0399 ἈΙ: upper case (full) * * We do not handle special upper mapping */ assert(!xkb_keysym_is_upper_or_title(XKB_KEYSYM_UNICODE_OFFSET + 0x1F80)); assert(xkb_keysym_is_upper_or_title(XKB_KEYSYM_UNICODE_OFFSET + 0x1F88)); assert(xkb_keysym_is_lower(XKB_KEYSYM_UNICODE_OFFSET + 0x1F80)); assert(!xkb_keysym_is_lower(XKB_KEYSYM_UNICODE_OFFSET + 0x1F88)); assert(xkb_keysym_to_upper(XKB_KEYSYM_UNICODE_OFFSET + 0x1F80) == XKB_KEYSYM_UNICODE_OFFSET + 0x1F88); assert(xkb_keysym_to_lower(XKB_KEYSYM_UNICODE_OFFSET + 0x1F80) == XKB_KEYSYM_UNICODE_OFFSET + 0x1F80); assert(xkb_keysym_to_upper(XKB_KEYSYM_UNICODE_OFFSET + 0x1F88) == XKB_KEYSYM_UNICODE_OFFSET + 0x1F88); assert(xkb_keysym_to_lower(XKB_KEYSYM_UNICODE_OFFSET + 0x1F88) == XKB_KEYSYM_UNICODE_OFFSET + 0x1F80); test_github_issue_42(); return 0; } xkbcommon-libxkbcommon-54ee7ac/test/keysym.h000066400000000000000000000520731510033435100213430ustar00rootroot00000000000000/* * NOTE: This file has been generated automatically by “scripts/update-keysyms-derived-headers.py”. * Do not edit manually! */ /* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-keysyms.h" struct ambiguous_icase_ks_names_entry { xkb_keysym_t keysym; const int count; const char *names[3]; }; static const struct ambiguous_icase_ks_names_entry ambiguous_icase_ks_names[] = { { XKB_KEY_dead_a, 2, { "dead_A", "dead_a" } }, { XKB_KEY_dead_e, 2, { "dead_E", "dead_e" } }, { XKB_KEY_dead_i, 2, { "dead_I", "dead_i" } }, { XKB_KEY_dead_o, 2, { "dead_O", "dead_o" } }, { XKB_KEY_dead_u, 2, { "dead_U", "dead_u" } }, { XKB_KEY_dead_schwa, 2, { "dead_SCHWA", "dead_schwa" } }, { XKB_KEY_ch, 3, { "CH", "Ch", "ch" } }, { XKB_KEY_c_h, 3, { "C_H", "C_h", "c_h" } }, { XKB_KEY_a, 2, { "A", "a" } }, { XKB_KEY_b, 2, { "B", "b" } }, { XKB_KEY_c, 2, { "C", "c" } }, { XKB_KEY_d, 2, { "D", "d" } }, { XKB_KEY_e, 2, { "E", "e" } }, { XKB_KEY_f, 2, { "F", "f" } }, { XKB_KEY_g, 2, { "G", "g" } }, { XKB_KEY_h, 2, { "H", "h" } }, { XKB_KEY_i, 2, { "I", "i" } }, { XKB_KEY_j, 2, { "J", "j" } }, { XKB_KEY_k, 2, { "K", "k" } }, { XKB_KEY_l, 2, { "L", "l" } }, { XKB_KEY_m, 2, { "M", "m" } }, { XKB_KEY_n, 2, { "N", "n" } }, { XKB_KEY_o, 2, { "O", "o" } }, { XKB_KEY_p, 2, { "P", "p" } }, { XKB_KEY_q, 2, { "Q", "q" } }, { XKB_KEY_r, 2, { "R", "r" } }, { XKB_KEY_s, 2, { "S", "s" } }, { XKB_KEY_t, 2, { "T", "t" } }, { XKB_KEY_u, 2, { "U", "u" } }, { XKB_KEY_v, 2, { "V", "v" } }, { XKB_KEY_w, 2, { "W", "w" } }, { XKB_KEY_x, 2, { "X", "x" } }, { XKB_KEY_y, 2, { "Y", "y" } }, { XKB_KEY_z, 2, { "Z", "z" } }, { XKB_KEY_agrave, 2, { "Agrave", "agrave" } }, { XKB_KEY_aacute, 2, { "Aacute", "aacute" } }, { XKB_KEY_acircumflex, 2, { "Acircumflex", "acircumflex" } }, { XKB_KEY_atilde, 2, { "Atilde", "atilde" } }, { XKB_KEY_adiaeresis, 2, { "Adiaeresis", "adiaeresis" } }, { XKB_KEY_aring, 2, { "Aring", "aring" } }, { XKB_KEY_ae, 2, { "AE", "ae" } }, { XKB_KEY_ccedilla, 2, { "Ccedilla", "ccedilla" } }, { XKB_KEY_egrave, 2, { "Egrave", "egrave" } }, { XKB_KEY_eacute, 2, { "Eacute", "eacute" } }, { XKB_KEY_ecircumflex, 2, { "Ecircumflex", "ecircumflex" } }, { XKB_KEY_ediaeresis, 2, { "Ediaeresis", "ediaeresis" } }, { XKB_KEY_igrave, 2, { "Igrave", "igrave" } }, { XKB_KEY_iacute, 2, { "Iacute", "iacute" } }, { XKB_KEY_icircumflex, 2, { "Icircumflex", "icircumflex" } }, { XKB_KEY_idiaeresis, 2, { "Idiaeresis", "idiaeresis" } }, { XKB_KEY_eth, 3, { "ETH", "Eth", "eth" } }, { XKB_KEY_ntilde, 2, { "Ntilde", "ntilde" } }, { XKB_KEY_ograve, 2, { "Ograve", "ograve" } }, { XKB_KEY_oacute, 2, { "Oacute", "oacute" } }, { XKB_KEY_ocircumflex, 2, { "Ocircumflex", "ocircumflex" } }, { XKB_KEY_otilde, 2, { "Otilde", "otilde" } }, { XKB_KEY_odiaeresis, 2, { "Odiaeresis", "odiaeresis" } }, { XKB_KEY_oslash, 2, { "Oslash", "oslash" } }, { XKB_KEY_ooblique, 2, { "Ooblique", "ooblique" } }, { XKB_KEY_ugrave, 2, { "Ugrave", "ugrave" } }, { XKB_KEY_uacute, 2, { "Uacute", "uacute" } }, { XKB_KEY_ucircumflex, 2, { "Ucircumflex", "ucircumflex" } }, { XKB_KEY_udiaeresis, 2, { "Udiaeresis", "udiaeresis" } }, { XKB_KEY_yacute, 2, { "Yacute", "yacute" } }, { XKB_KEY_thorn, 3, { "THORN", "Thorn", "thorn" } }, { XKB_KEY_ydiaeresis, 2, { "Ydiaeresis", "ydiaeresis" } }, { XKB_KEY_aogonek, 2, { "Aogonek", "aogonek" } }, { XKB_KEY_lstroke, 2, { "Lstroke", "lstroke" } }, { XKB_KEY_lcaron, 2, { "Lcaron", "lcaron" } }, { XKB_KEY_sacute, 2, { "Sacute", "sacute" } }, { XKB_KEY_scaron, 2, { "Scaron", "scaron" } }, { XKB_KEY_scedilla, 2, { "Scedilla", "scedilla" } }, { XKB_KEY_tcaron, 2, { "Tcaron", "tcaron" } }, { XKB_KEY_zacute, 2, { "Zacute", "zacute" } }, { XKB_KEY_zcaron, 2, { "Zcaron", "zcaron" } }, { XKB_KEY_zabovedot, 2, { "Zabovedot", "zabovedot" } }, { XKB_KEY_racute, 2, { "Racute", "racute" } }, { XKB_KEY_abreve, 2, { "Abreve", "abreve" } }, { XKB_KEY_lacute, 2, { "Lacute", "lacute" } }, { XKB_KEY_cacute, 2, { "Cacute", "cacute" } }, { XKB_KEY_ccaron, 2, { "Ccaron", "ccaron" } }, { XKB_KEY_eogonek, 2, { "Eogonek", "eogonek" } }, { XKB_KEY_ecaron, 2, { "Ecaron", "ecaron" } }, { XKB_KEY_dcaron, 2, { "Dcaron", "dcaron" } }, { XKB_KEY_dstroke, 2, { "Dstroke", "dstroke" } }, { XKB_KEY_nacute, 2, { "Nacute", "nacute" } }, { XKB_KEY_ncaron, 2, { "Ncaron", "ncaron" } }, { XKB_KEY_odoubleacute, 2, { "Odoubleacute", "odoubleacute" } }, { XKB_KEY_rcaron, 2, { "Rcaron", "rcaron" } }, { XKB_KEY_uring, 2, { "Uring", "uring" } }, { XKB_KEY_udoubleacute, 2, { "Udoubleacute", "udoubleacute" } }, { XKB_KEY_tcedilla, 2, { "Tcedilla", "tcedilla" } }, { XKB_KEY_hstroke, 2, { "Hstroke", "hstroke" } }, { XKB_KEY_hcircumflex, 2, { "Hcircumflex", "hcircumflex" } }, { XKB_KEY_gbreve, 2, { "Gbreve", "gbreve" } }, { XKB_KEY_jcircumflex, 2, { "Jcircumflex", "jcircumflex" } }, { XKB_KEY_cabovedot, 2, { "Cabovedot", "cabovedot" } }, { XKB_KEY_ccircumflex, 2, { "Ccircumflex", "ccircumflex" } }, { XKB_KEY_gabovedot, 2, { "Gabovedot", "gabovedot" } }, { XKB_KEY_gcircumflex, 2, { "Gcircumflex", "gcircumflex" } }, { XKB_KEY_ubreve, 2, { "Ubreve", "ubreve" } }, { XKB_KEY_scircumflex, 2, { "Scircumflex", "scircumflex" } }, { XKB_KEY_rcedilla, 2, { "Rcedilla", "rcedilla" } }, { XKB_KEY_itilde, 2, { "Itilde", "itilde" } }, { XKB_KEY_lcedilla, 2, { "Lcedilla", "lcedilla" } }, { XKB_KEY_emacron, 2, { "Emacron", "emacron" } }, { XKB_KEY_gcedilla, 2, { "Gcedilla", "gcedilla" } }, { XKB_KEY_tslash, 2, { "Tslash", "tslash" } }, { XKB_KEY_eng, 2, { "ENG", "eng" } }, { XKB_KEY_amacron, 2, { "Amacron", "amacron" } }, { XKB_KEY_iogonek, 2, { "Iogonek", "iogonek" } }, { XKB_KEY_eabovedot, 2, { "Eabovedot", "eabovedot" } }, { XKB_KEY_imacron, 2, { "Imacron", "imacron" } }, { XKB_KEY_ncedilla, 2, { "Ncedilla", "ncedilla" } }, { XKB_KEY_omacron, 2, { "Omacron", "omacron" } }, { XKB_KEY_kcedilla, 2, { "Kcedilla", "kcedilla" } }, { XKB_KEY_uogonek, 2, { "Uogonek", "uogonek" } }, { XKB_KEY_utilde, 2, { "Utilde", "utilde" } }, { XKB_KEY_umacron, 2, { "Umacron", "umacron" } }, { XKB_KEY_wcircumflex, 2, { "Wcircumflex", "wcircumflex" } }, { XKB_KEY_ycircumflex, 2, { "Ycircumflex", "ycircumflex" } }, { XKB_KEY_babovedot, 2, { "Babovedot", "babovedot" } }, { XKB_KEY_dabovedot, 2, { "Dabovedot", "dabovedot" } }, { XKB_KEY_fabovedot, 2, { "Fabovedot", "fabovedot" } }, { XKB_KEY_mabovedot, 2, { "Mabovedot", "mabovedot" } }, { XKB_KEY_pabovedot, 2, { "Pabovedot", "pabovedot" } }, { XKB_KEY_sabovedot, 2, { "Sabovedot", "sabovedot" } }, { XKB_KEY_tabovedot, 2, { "Tabovedot", "tabovedot" } }, { XKB_KEY_wgrave, 2, { "Wgrave", "wgrave" } }, { XKB_KEY_wacute, 2, { "Wacute", "wacute" } }, { XKB_KEY_wdiaeresis, 2, { "Wdiaeresis", "wdiaeresis" } }, { XKB_KEY_ygrave, 2, { "Ygrave", "ygrave" } }, { XKB_KEY_oe, 2, { "OE", "oe" } }, { XKB_KEY_kana_a, 2, { "kana_A", "kana_a" } }, { XKB_KEY_kana_i, 2, { "kana_I", "kana_i" } }, { XKB_KEY_kana_u, 2, { "kana_U", "kana_u" } }, { XKB_KEY_kana_e, 2, { "kana_E", "kana_e" } }, { XKB_KEY_kana_o, 2, { "kana_O", "kana_o" } }, { XKB_KEY_kana_ya, 2, { "kana_YA", "kana_ya" } }, { XKB_KEY_kana_yu, 2, { "kana_YU", "kana_yu" } }, { XKB_KEY_kana_yo, 2, { "kana_YO", "kana_yo" } }, { XKB_KEY_kana_tsu, 2, { "kana_TSU", "kana_tsu" } }, { XKB_KEY_kana_tu, 2, { "kana_TU", "kana_tu" } }, { XKB_KEY_Cyrillic_ghe_bar, 2, { "Cyrillic_GHE_bar", "Cyrillic_ghe_bar" } }, { XKB_KEY_Cyrillic_zhe_descender, 2, { "Cyrillic_ZHE_descender", "Cyrillic_zhe_descender" } }, { XKB_KEY_Cyrillic_ka_descender, 2, { "Cyrillic_KA_descender", "Cyrillic_ka_descender" } }, { XKB_KEY_Cyrillic_ka_vertstroke, 2, { "Cyrillic_KA_vertstroke", "Cyrillic_ka_vertstroke" } }, { XKB_KEY_Cyrillic_en_descender, 2, { "Cyrillic_EN_descender", "Cyrillic_en_descender" } }, { XKB_KEY_Cyrillic_u_straight, 2, { "Cyrillic_U_straight", "Cyrillic_u_straight" } }, { XKB_KEY_Cyrillic_u_straight_bar, 2, { "Cyrillic_U_straight_bar", "Cyrillic_u_straight_bar" } }, { XKB_KEY_Cyrillic_ha_descender, 2, { "Cyrillic_HA_descender", "Cyrillic_ha_descender" } }, { XKB_KEY_Cyrillic_che_descender, 2, { "Cyrillic_CHE_descender", "Cyrillic_che_descender" } }, { XKB_KEY_Cyrillic_che_vertstroke, 2, { "Cyrillic_CHE_vertstroke", "Cyrillic_che_vertstroke" } }, { XKB_KEY_Cyrillic_shha, 2, { "Cyrillic_SHHA", "Cyrillic_shha" } }, { XKB_KEY_Cyrillic_schwa, 2, { "Cyrillic_SCHWA", "Cyrillic_schwa" } }, { XKB_KEY_Cyrillic_i_macron, 2, { "Cyrillic_I_macron", "Cyrillic_i_macron" } }, { XKB_KEY_Cyrillic_o_bar, 2, { "Cyrillic_O_bar", "Cyrillic_o_bar" } }, { XKB_KEY_Cyrillic_u_macron, 2, { "Cyrillic_U_macron", "Cyrillic_u_macron" } }, { XKB_KEY_Serbian_dje, 2, { "Serbian_DJE", "Serbian_dje" } }, { XKB_KEY_Macedonia_gje, 2, { "Macedonia_GJE", "Macedonia_gje" } }, { XKB_KEY_Cyrillic_io, 2, { "Cyrillic_IO", "Cyrillic_io" } }, { XKB_KEY_Ukrainian_ie, 2, { "Ukrainian_IE", "Ukrainian_ie" } }, { XKB_KEY_Ukranian_je, 2, { "Ukranian_JE", "Ukranian_je" } }, { XKB_KEY_Macedonia_dse, 2, { "Macedonia_DSE", "Macedonia_dse" } }, { XKB_KEY_Ukrainian_i, 2, { "Ukrainian_I", "Ukrainian_i" } }, { XKB_KEY_Ukranian_i, 2, { "Ukranian_I", "Ukranian_i" } }, { XKB_KEY_Ukrainian_yi, 2, { "Ukrainian_YI", "Ukrainian_yi" } }, { XKB_KEY_Ukranian_yi, 2, { "Ukranian_YI", "Ukranian_yi" } }, { XKB_KEY_Cyrillic_je, 2, { "Cyrillic_JE", "Cyrillic_je" } }, { XKB_KEY_Serbian_je, 2, { "Serbian_JE", "Serbian_je" } }, { XKB_KEY_Cyrillic_lje, 2, { "Cyrillic_LJE", "Cyrillic_lje" } }, { XKB_KEY_Serbian_lje, 2, { "Serbian_LJE", "Serbian_lje" } }, { XKB_KEY_Cyrillic_nje, 2, { "Cyrillic_NJE", "Cyrillic_nje" } }, { XKB_KEY_Serbian_nje, 2, { "Serbian_NJE", "Serbian_nje" } }, { XKB_KEY_Serbian_tshe, 2, { "Serbian_TSHE", "Serbian_tshe" } }, { XKB_KEY_Macedonia_kje, 2, { "Macedonia_KJE", "Macedonia_kje" } }, { XKB_KEY_Ukrainian_ghe_with_upturn, 2, { "Ukrainian_GHE_WITH_UPTURN", "Ukrainian_ghe_with_upturn" } }, { XKB_KEY_Byelorussian_shortu, 2, { "Byelorussian_SHORTU", "Byelorussian_shortu" } }, { XKB_KEY_Cyrillic_dzhe, 2, { "Cyrillic_DZHE", "Cyrillic_dzhe" } }, { XKB_KEY_Serbian_dze, 2, { "Serbian_DZE", "Serbian_dze" } }, { XKB_KEY_Cyrillic_yu, 2, { "Cyrillic_YU", "Cyrillic_yu" } }, { XKB_KEY_Cyrillic_a, 2, { "Cyrillic_A", "Cyrillic_a" } }, { XKB_KEY_Cyrillic_be, 2, { "Cyrillic_BE", "Cyrillic_be" } }, { XKB_KEY_Cyrillic_tse, 2, { "Cyrillic_TSE", "Cyrillic_tse" } }, { XKB_KEY_Cyrillic_de, 2, { "Cyrillic_DE", "Cyrillic_de" } }, { XKB_KEY_Cyrillic_ie, 2, { "Cyrillic_IE", "Cyrillic_ie" } }, { XKB_KEY_Cyrillic_ef, 2, { "Cyrillic_EF", "Cyrillic_ef" } }, { XKB_KEY_Cyrillic_ghe, 2, { "Cyrillic_GHE", "Cyrillic_ghe" } }, { XKB_KEY_Cyrillic_ha, 2, { "Cyrillic_HA", "Cyrillic_ha" } }, { XKB_KEY_Cyrillic_i, 2, { "Cyrillic_I", "Cyrillic_i" } }, { XKB_KEY_Cyrillic_shorti, 2, { "Cyrillic_SHORTI", "Cyrillic_shorti" } }, { XKB_KEY_Cyrillic_ka, 2, { "Cyrillic_KA", "Cyrillic_ka" } }, { XKB_KEY_Cyrillic_el, 2, { "Cyrillic_EL", "Cyrillic_el" } }, { XKB_KEY_Cyrillic_em, 2, { "Cyrillic_EM", "Cyrillic_em" } }, { XKB_KEY_Cyrillic_en, 2, { "Cyrillic_EN", "Cyrillic_en" } }, { XKB_KEY_Cyrillic_o, 2, { "Cyrillic_O", "Cyrillic_o" } }, { XKB_KEY_Cyrillic_pe, 2, { "Cyrillic_PE", "Cyrillic_pe" } }, { XKB_KEY_Cyrillic_ya, 2, { "Cyrillic_YA", "Cyrillic_ya" } }, { XKB_KEY_Cyrillic_er, 2, { "Cyrillic_ER", "Cyrillic_er" } }, { XKB_KEY_Cyrillic_es, 2, { "Cyrillic_ES", "Cyrillic_es" } }, { XKB_KEY_Cyrillic_te, 2, { "Cyrillic_TE", "Cyrillic_te" } }, { XKB_KEY_Cyrillic_u, 2, { "Cyrillic_U", "Cyrillic_u" } }, { XKB_KEY_Cyrillic_zhe, 2, { "Cyrillic_ZHE", "Cyrillic_zhe" } }, { XKB_KEY_Cyrillic_ve, 2, { "Cyrillic_VE", "Cyrillic_ve" } }, { XKB_KEY_Cyrillic_softsign, 2, { "Cyrillic_SOFTSIGN", "Cyrillic_softsign" } }, { XKB_KEY_Cyrillic_yeru, 2, { "Cyrillic_YERU", "Cyrillic_yeru" } }, { XKB_KEY_Cyrillic_ze, 2, { "Cyrillic_ZE", "Cyrillic_ze" } }, { XKB_KEY_Cyrillic_sha, 2, { "Cyrillic_SHA", "Cyrillic_sha" } }, { XKB_KEY_Cyrillic_e, 2, { "Cyrillic_E", "Cyrillic_e" } }, { XKB_KEY_Cyrillic_shcha, 2, { "Cyrillic_SHCHA", "Cyrillic_shcha" } }, { XKB_KEY_Cyrillic_che, 2, { "Cyrillic_CHE", "Cyrillic_che" } }, { XKB_KEY_Cyrillic_hardsign, 2, { "Cyrillic_HARDSIGN", "Cyrillic_hardsign" } }, { XKB_KEY_Greek_alphaaccent, 2, { "Greek_ALPHAaccent", "Greek_alphaaccent" } }, { XKB_KEY_Greek_epsilonaccent, 2, { "Greek_EPSILONaccent", "Greek_epsilonaccent" } }, { XKB_KEY_Greek_etaaccent, 2, { "Greek_ETAaccent", "Greek_etaaccent" } }, { XKB_KEY_Greek_iotaaccent, 2, { "Greek_IOTAaccent", "Greek_iotaaccent" } }, { XKB_KEY_Greek_iotadieresis, 2, { "Greek_IOTAdieresis", "Greek_iotadieresis" } }, { XKB_KEY_Greek_omicronaccent, 2, { "Greek_OMICRONaccent", "Greek_omicronaccent" } }, { XKB_KEY_Greek_upsilonaccent, 2, { "Greek_UPSILONaccent", "Greek_upsilonaccent" } }, { XKB_KEY_Greek_upsilondieresis, 2, { "Greek_UPSILONdieresis", "Greek_upsilondieresis" } }, { XKB_KEY_Greek_omegaaccent, 2, { "Greek_OMEGAaccent", "Greek_omegaaccent" } }, { XKB_KEY_Greek_alpha, 2, { "Greek_ALPHA", "Greek_alpha" } }, { XKB_KEY_Greek_beta, 2, { "Greek_BETA", "Greek_beta" } }, { XKB_KEY_Greek_gamma, 2, { "Greek_GAMMA", "Greek_gamma" } }, { XKB_KEY_Greek_delta, 2, { "Greek_DELTA", "Greek_delta" } }, { XKB_KEY_Greek_epsilon, 2, { "Greek_EPSILON", "Greek_epsilon" } }, { XKB_KEY_Greek_zeta, 2, { "Greek_ZETA", "Greek_zeta" } }, { XKB_KEY_Greek_eta, 2, { "Greek_ETA", "Greek_eta" } }, { XKB_KEY_Greek_theta, 2, { "Greek_THETA", "Greek_theta" } }, { XKB_KEY_Greek_iota, 2, { "Greek_IOTA", "Greek_iota" } }, { XKB_KEY_Greek_kappa, 2, { "Greek_KAPPA", "Greek_kappa" } }, { XKB_KEY_Greek_lamda, 2, { "Greek_LAMDA", "Greek_lamda" } }, { XKB_KEY_Greek_lambda, 2, { "Greek_LAMBDA", "Greek_lambda" } }, { XKB_KEY_Greek_mu, 2, { "Greek_MU", "Greek_mu" } }, { XKB_KEY_Greek_nu, 2, { "Greek_NU", "Greek_nu" } }, { XKB_KEY_Greek_xi, 2, { "Greek_XI", "Greek_xi" } }, { XKB_KEY_Greek_omicron, 2, { "Greek_OMICRON", "Greek_omicron" } }, { XKB_KEY_Greek_pi, 2, { "Greek_PI", "Greek_pi" } }, { XKB_KEY_Greek_rho, 2, { "Greek_RHO", "Greek_rho" } }, { XKB_KEY_Greek_sigma, 2, { "Greek_SIGMA", "Greek_sigma" } }, { XKB_KEY_Greek_tau, 2, { "Greek_TAU", "Greek_tau" } }, { XKB_KEY_Greek_upsilon, 2, { "Greek_UPSILON", "Greek_upsilon" } }, { XKB_KEY_Greek_phi, 2, { "Greek_PHI", "Greek_phi" } }, { XKB_KEY_Greek_chi, 2, { "Greek_CHI", "Greek_chi" } }, { XKB_KEY_Greek_psi, 2, { "Greek_PSI", "Greek_psi" } }, { XKB_KEY_Greek_omega, 2, { "Greek_OMEGA", "Greek_omega" } }, { XKB_KEY_Armenian_ayb, 2, { "Armenian_AYB", "Armenian_ayb" } }, { XKB_KEY_Armenian_ben, 2, { "Armenian_BEN", "Armenian_ben" } }, { XKB_KEY_Armenian_gim, 2, { "Armenian_GIM", "Armenian_gim" } }, { XKB_KEY_Armenian_da, 2, { "Armenian_DA", "Armenian_da" } }, { XKB_KEY_Armenian_yech, 2, { "Armenian_YECH", "Armenian_yech" } }, { XKB_KEY_Armenian_za, 2, { "Armenian_ZA", "Armenian_za" } }, { XKB_KEY_Armenian_e, 2, { "Armenian_E", "Armenian_e" } }, { XKB_KEY_Armenian_at, 2, { "Armenian_AT", "Armenian_at" } }, { XKB_KEY_Armenian_to, 2, { "Armenian_TO", "Armenian_to" } }, { XKB_KEY_Armenian_zhe, 2, { "Armenian_ZHE", "Armenian_zhe" } }, { XKB_KEY_Armenian_ini, 2, { "Armenian_INI", "Armenian_ini" } }, { XKB_KEY_Armenian_lyun, 2, { "Armenian_LYUN", "Armenian_lyun" } }, { XKB_KEY_Armenian_khe, 2, { "Armenian_KHE", "Armenian_khe" } }, { XKB_KEY_Armenian_tsa, 2, { "Armenian_TSA", "Armenian_tsa" } }, { XKB_KEY_Armenian_ken, 2, { "Armenian_KEN", "Armenian_ken" } }, { XKB_KEY_Armenian_ho, 2, { "Armenian_HO", "Armenian_ho" } }, { XKB_KEY_Armenian_dza, 2, { "Armenian_DZA", "Armenian_dza" } }, { XKB_KEY_Armenian_ghat, 2, { "Armenian_GHAT", "Armenian_ghat" } }, { XKB_KEY_Armenian_tche, 2, { "Armenian_TCHE", "Armenian_tche" } }, { XKB_KEY_Armenian_men, 2, { "Armenian_MEN", "Armenian_men" } }, { XKB_KEY_Armenian_hi, 2, { "Armenian_HI", "Armenian_hi" } }, { XKB_KEY_Armenian_nu, 2, { "Armenian_NU", "Armenian_nu" } }, { XKB_KEY_Armenian_sha, 2, { "Armenian_SHA", "Armenian_sha" } }, { XKB_KEY_Armenian_vo, 2, { "Armenian_VO", "Armenian_vo" } }, { XKB_KEY_Armenian_cha, 2, { "Armenian_CHA", "Armenian_cha" } }, { XKB_KEY_Armenian_pe, 2, { "Armenian_PE", "Armenian_pe" } }, { XKB_KEY_Armenian_je, 2, { "Armenian_JE", "Armenian_je" } }, { XKB_KEY_Armenian_ra, 2, { "Armenian_RA", "Armenian_ra" } }, { XKB_KEY_Armenian_se, 2, { "Armenian_SE", "Armenian_se" } }, { XKB_KEY_Armenian_vev, 2, { "Armenian_VEV", "Armenian_vev" } }, { XKB_KEY_Armenian_tyun, 2, { "Armenian_TYUN", "Armenian_tyun" } }, { XKB_KEY_Armenian_re, 2, { "Armenian_RE", "Armenian_re" } }, { XKB_KEY_Armenian_tso, 2, { "Armenian_TSO", "Armenian_tso" } }, { XKB_KEY_Armenian_vyun, 2, { "Armenian_VYUN", "Armenian_vyun" } }, { XKB_KEY_Armenian_pyur, 2, { "Armenian_PYUR", "Armenian_pyur" } }, { XKB_KEY_Armenian_ke, 2, { "Armenian_KE", "Armenian_ke" } }, { XKB_KEY_Armenian_o, 2, { "Armenian_O", "Armenian_o" } }, { XKB_KEY_Armenian_fe, 2, { "Armenian_FE", "Armenian_fe" } }, { XKB_KEY_xabovedot, 2, { "Xabovedot", "xabovedot" } }, { XKB_KEY_ibreve, 2, { "Ibreve", "ibreve" } }, { XKB_KEY_zstroke, 2, { "Zstroke", "zstroke" } }, { XKB_KEY_gcaron, 2, { "Gcaron", "gcaron" } }, { XKB_KEY_ocaron, 2, { "Ocaron", "ocaron" } }, { XKB_KEY_obarred, 2, { "Obarred", "obarred" } }, { XKB_KEY_schwa, 2, { "SCHWA", "schwa" } }, { XKB_KEY_ezh, 2, { "EZH", "ezh" } }, { XKB_KEY_lbelowdot, 2, { "Lbelowdot", "lbelowdot" } }, { XKB_KEY_abelowdot, 2, { "Abelowdot", "abelowdot" } }, { XKB_KEY_ahook, 2, { "Ahook", "ahook" } }, { XKB_KEY_acircumflexacute, 2, { "Acircumflexacute", "acircumflexacute" } }, { XKB_KEY_acircumflexgrave, 2, { "Acircumflexgrave", "acircumflexgrave" } }, { XKB_KEY_acircumflexhook, 2, { "Acircumflexhook", "acircumflexhook" } }, { XKB_KEY_acircumflextilde, 2, { "Acircumflextilde", "acircumflextilde" } }, { XKB_KEY_acircumflexbelowdot, 2, { "Acircumflexbelowdot", "acircumflexbelowdot" } }, { XKB_KEY_abreveacute, 2, { "Abreveacute", "abreveacute" } }, { XKB_KEY_abrevegrave, 2, { "Abrevegrave", "abrevegrave" } }, { XKB_KEY_abrevehook, 2, { "Abrevehook", "abrevehook" } }, { XKB_KEY_abrevetilde, 2, { "Abrevetilde", "abrevetilde" } }, { XKB_KEY_abrevebelowdot, 2, { "Abrevebelowdot", "abrevebelowdot" } }, { XKB_KEY_ebelowdot, 2, { "Ebelowdot", "ebelowdot" } }, { XKB_KEY_ehook, 2, { "Ehook", "ehook" } }, { XKB_KEY_etilde, 2, { "Etilde", "etilde" } }, { XKB_KEY_ecircumflexacute, 2, { "Ecircumflexacute", "ecircumflexacute" } }, { XKB_KEY_ecircumflexgrave, 2, { "Ecircumflexgrave", "ecircumflexgrave" } }, { XKB_KEY_ecircumflexhook, 2, { "Ecircumflexhook", "ecircumflexhook" } }, { XKB_KEY_ecircumflextilde, 2, { "Ecircumflextilde", "ecircumflextilde" } }, { XKB_KEY_ecircumflexbelowdot, 2, { "Ecircumflexbelowdot", "ecircumflexbelowdot" } }, { XKB_KEY_ihook, 2, { "Ihook", "ihook" } }, { XKB_KEY_ibelowdot, 2, { "Ibelowdot", "ibelowdot" } }, { XKB_KEY_obelowdot, 2, { "Obelowdot", "obelowdot" } }, { XKB_KEY_ohook, 2, { "Ohook", "ohook" } }, { XKB_KEY_ocircumflexacute, 2, { "Ocircumflexacute", "ocircumflexacute" } }, { XKB_KEY_ocircumflexgrave, 2, { "Ocircumflexgrave", "ocircumflexgrave" } }, { XKB_KEY_ocircumflexhook, 2, { "Ocircumflexhook", "ocircumflexhook" } }, { XKB_KEY_ocircumflextilde, 2, { "Ocircumflextilde", "ocircumflextilde" } }, { XKB_KEY_ocircumflexbelowdot, 2, { "Ocircumflexbelowdot", "ocircumflexbelowdot" } }, { XKB_KEY_ohornacute, 2, { "Ohornacute", "ohornacute" } }, { XKB_KEY_ohorngrave, 2, { "Ohorngrave", "ohorngrave" } }, { XKB_KEY_ohornhook, 2, { "Ohornhook", "ohornhook" } }, { XKB_KEY_ohorntilde, 2, { "Ohorntilde", "ohorntilde" } }, { XKB_KEY_ohornbelowdot, 2, { "Ohornbelowdot", "ohornbelowdot" } }, { XKB_KEY_ubelowdot, 2, { "Ubelowdot", "ubelowdot" } }, { XKB_KEY_uhook, 2, { "Uhook", "uhook" } }, { XKB_KEY_uhornacute, 2, { "Uhornacute", "uhornacute" } }, { XKB_KEY_uhorngrave, 2, { "Uhorngrave", "uhorngrave" } }, { XKB_KEY_uhornhook, 2, { "Uhornhook", "uhornhook" } }, { XKB_KEY_uhorntilde, 2, { "Uhorntilde", "uhorntilde" } }, { XKB_KEY_uhornbelowdot, 2, { "Uhornbelowdot", "uhornbelowdot" } }, { XKB_KEY_ybelowdot, 2, { "Ybelowdot", "ybelowdot" } }, { XKB_KEY_yhook, 2, { "Yhook", "yhook" } }, { XKB_KEY_ytilde, 2, { "Ytilde", "ytilde" } }, { XKB_KEY_ohorn, 2, { "Ohorn", "ohorn" } }, { XKB_KEY_uhorn, 2, { "Uhorn", "uhorn" } }, { XKB_KEY_XF86Screensaver, 2, { "XF86ScreenSaver", "XF86Screensaver" } } }; xkbcommon-libxkbcommon-54ee7ac/test/keysym.h.jinja000066400000000000000000000015231510033435100224270ustar00rootroot00000000000000/* * NOTE: This file has been generated automatically by “{{script}}”. * Do not edit manually! */ /* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-keysyms.h" struct ambiguous_icase_ks_names_entry { xkb_keysym_t keysym; const int count; const char *names[{{ MAX_AMBIGUOUS_NAMES }}]; }; static const struct ambiguous_icase_ks_names_entry ambiguous_icase_ks_names[] = { {% for names in ambiguous_case_insensitive_names.values() %} { XKB_KEY_{{ names[-1] }}, {{ names | length }}, { {# -#} {% for name in names -%} "{{ name }}"{% if not loop.last %}, {% endif -%} {% endfor %} {#- #} } } {%- if not loop.last %},{% endif +%} {% endfor %} }; xkbcommon-libxkbcommon-54ee7ac/test/log.c000066400000000000000000000410111510033435100205640ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "test.h" #include "context.h" #include "messages-codes.h" #ifdef __GNUC__ #pragma GCC diagnostic ignored "-Wmissing-format-attribute" #endif static const char * log_level_to_string(enum xkb_log_level level) { switch (level) { case XKB_LOG_LEVEL_CRITICAL: return "critical"; case XKB_LOG_LEVEL_ERROR: return "error"; case XKB_LOG_LEVEL_WARNING: return "warning"; case XKB_LOG_LEVEL_INFO: return "info"; case XKB_LOG_LEVEL_DEBUG: return "debug"; } return "unknown"; } ATTR_PRINTF(3, 0) static void log_fn(struct xkb_context *ctx, enum xkb_log_level level, const char *fmt, va_list args) { char *s; int size; darray_char *ls = xkb_context_get_user_data(ctx); assert(ls); size = vasprintf(&s, fmt, args); assert(size != -1); darray_append_string(*ls, log_level_to_string(level)); darray_append_lit(*ls, ": "); darray_append_string(*ls, s); free(s); } static void test_basic(void) { int ret; ret = setenv("XKB_LOG_LEVEL", "warn", 1); assert(ret == 0); ret = setenv("XKB_LOG_VERBOSITY", "5", 1); assert(ret == 0); struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); darray_char log_string; darray_init(log_string); xkb_context_set_user_data(ctx, &log_string); xkb_context_set_log_fn(ctx, log_fn); log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "first warning: %d\n", 87); log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "first info\n"); log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "first debug: %s\n", "hello"); log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "first error: %lu\n", 115415UL); log_vrb(ctx, 5, XKB_LOG_MESSAGE_NO_ID, "first verbose 5\n"); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_DEBUG); log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "second warning: %d\n", 87); log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "second debug: %s %s\n", "hello", "world"); log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "second info\n"); log_err(ctx, XKB_ERROR_MALFORMED_NUMBER_LITERAL, "second error: %lu\n", 115415UL); log_vrb(ctx, 6, XKB_LOG_MESSAGE_NO_ID, "second verbose 6\n"); xkb_context_set_log_verbosity(ctx, XKB_LOG_VERBOSITY_MINIMAL); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); log_warn(ctx, XKB_LOG_MESSAGE_NO_ID, "third warning: %d\n", 87); log_dbg(ctx, XKB_LOG_MESSAGE_NO_ID, "third debug: %s %s\n", "hello", "world"); log_info(ctx, XKB_LOG_MESSAGE_NO_ID, "third info\n"); log_err(ctx, XKB_LOG_MESSAGE_NO_ID, "third error: %lu\n", 115415UL); log_vrb(ctx, 0, XKB_LOG_MESSAGE_NO_ID, "third verbose 0\n"); printf("%s", darray_items(log_string)); assert(streq(darray_items(log_string), "warning: first warning: 87\n" "error: first error: 115415\n" "warning: first verbose 5\n" "warning: second warning: 87\n" "debug: second debug: hello world\n" "info: second info\n" "error: [XKB-034] second error: 115415\n")); xkb_context_unref(ctx); darray_free(log_string); } struct test_data { const char * const input; const char * const log; bool error; }; static void test_keymaps(void) { struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); darray_char log_string; darray_init(log_string); xkb_context_set_user_data(ctx, &log_string); xkb_context_set_log_fn(ctx, log_fn); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_WARNING); xkb_context_set_log_verbosity(ctx, XKB_LOG_VERBOSITY_COMPREHENSIVE); const struct test_data keymaps[] = { { .input = "", .log = "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = " ", .log = "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = "\n", .log = "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = "xkb_keymap {\n", .log = "error: [XKB-769] (input string):1:12: syntax error, unexpected end of file\n" "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = "xkb_keymap \"\\j\"\n" " { xkb_symbols = {};\n" "};", .log = "warning: [XKB-645] (input string):1:12: unknown escape sequence \"\\j\" in string literal\n" "error: [XKB-769] (input string):2:16: syntax error, unexpected =, expecting {\n" "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, { .input = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { key <> { [\"\xC3\xBC\xff\"] }; };\n" "};", .log = "error: [XKB-542] (input string):3:26: Cannot convert string to keysyms: Invalid UTF-8 encoding starting at byte position 3 (code point position: 2).\n" "error: [XKB-822] Failed to parse input xkb string\n", .error = true }, /* Extra lines & spaces intented to check the file positions */ { .input = "xkb_keymap {\n" " xkb_keycodes {\n" " <> = 1;\n" "\n" " alias <1> = <>;\n" " alias <1> =\n" " <>;\n" " };\n" " xkb_types \"\\400x\\j\" { };\n" " xkb_compat {\n" " interpret invalidKeysym +\n" " Any { repeat = true; };\n" " };\n" " xkb_symbols { key <> {[0x30, leftshoe]}; };\n" "};", .log = "warning: [XKB-193] (input string):9:13: invalid octal escape sequence \"\\400\" in string literal\n" "warning: [XKB-645] (input string):9:13: unknown escape sequence \"\\j\" in string literal\n" "warning: [XKB-107] (input string):11:15: unrecognized keysym \"invalidKeysym\"\n" "warning: [XKB-489] (input string):14:26: numeric keysym \"0x0030\" (48)\n" "warning: [XKB-301] (input string):14:32: deprecated keysym \"leftshoe\".\n" "warning: [XKB-433] No map in include statement, but \"(input string)\" contains several; Using first defined map, \"(unnamed map)\"\n" "warning: [XKB-523] Alias of <1> for <> declared more than once; First definition ignored\n" "warning: [XKB-286] The type \"TWO_LEVEL\" for key '<>' group 1 was not previously defined; Using the default type\n" "warning: [XKB-516] Type \"ONE_LEVEL\" has 1 levels, but <> has 2 levels; Ignoring extra symbols\n", .error = false }, /* Invalid action fields */ { .input = "default xkb_keymap {\n" " xkb_compat {\n" " NoAction.data = 1;\n" " interpret VoidSymbol { action= VoidAction(data=); };\n" " };\n" "};", .log = "error: [XKB-563] The \"NoAction\" action takes no argument, but got \"data\" field; Action definition ignored\n" "error: [XKB-563] The \"VoidAction\" action takes no argument, but got \"data\" field; Action definition ignored\n" "error: Failed to compile xkb_compatibility\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, /* Invalid action fields */ { .input = "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols {\n" " NoAction.data = 1;\n" " key <> { [TerminateServer(data=)] };\n" " };\n" "};", .log = "error: [XKB-563] The \"NoAction\" action takes no argument, but got \"data\" field; Action definition ignored\n" "error: [XKB-563] The \"Terminate\" action takes no argument, but got \"data\" field; Action definition ignored\n" "error: [XKB-796] Illegal action definition for <>; Action for group 1/level 1 ignored\n" "error: Failed to compile xkb_symbols\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, /* Unsupported legacy X11 actions */ { .input = "default xkb_keymap {\n" " xkb_compat {\n" /* This is a valid entry */ " interpret ISO_Lock+AnyOf(all) {\n" " action= ISOLock(modifiers=modMapMods,affect=all);\n" " };\n" /* This uses invalid field, but we do not check fields of * legacy actions */ " interpret VoidSymbol+AnyOf(all) {\n" " action= RedirectKey(data=);\n" " };\n" " };\n" "};", .log = "warning: [XKB-362] Unsupported legacy action type \"ISOLock\".\n" "warning: [XKB-362] Unsupported legacy action type \"RedirectKey\".\n", .error = false }, /* Invalid global var */ { .input = "default xkb_keymap {\n" " xkb_keycodes { foobar; };\n" "};", .log = "error: [XKB-639] Default defined for unknown field \"foobar\"; Ignored\n" "error: Failed to compile xkb_keycodes\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, { .input = "default xkb_keymap {\n" " xkb_types { foobar; };\n" "};", .log = "error: [XKB-639] Default defined for unknown field \"foobar\"; Ignored\n" "error: Failed to compile xkb_types\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, { .input = "default xkb_keymap {\n" " xkb_compat { foobar; };\n" "};", .log = "error: [XKB-639] Default defined for unknown field \"foobar\"; Ignored\n" "error: Failed to compile xkb_compatibility\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, { .input = "default xkb_keymap {\n" " xkb_symbols { foobar; };\n" "};", .log = "error: [XKB-639] Default defined for unknown field \"foobar\"; Ignored\n" "error: Failed to compile xkb_symbols\n" "error: [XKB-822] Failed to compile keymap\n", .error = true }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymaps[k].input, strlen(keymaps[k].input)); assert_printf(keymaps[k].error ^ !!keymap, "%s\n", darray_items(log_string)); xkb_keymap_unref(keymap); assert_printf(streq_not_null(darray_items(log_string), keymaps[k].log), "Expected:\n%s\nGot:\n%s\n", keymaps[k].log, darray_items(log_string)); darray_free(log_string); } xkb_context_unref(ctx); } static void test_compose(void) { struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); darray_char log_string; darray_init(log_string); xkb_context_set_user_data(ctx, &log_string); xkb_context_set_log_fn(ctx, log_fn); xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_WARNING); xkb_context_set_log_verbosity(ctx, XKB_LOG_VERBOSITY_VERBOSE); const struct test_data composes[] = { { .input = "", .log = NULL, .error = false }, { .input = "\n", .log = NULL, .error = false }, { .input = "\xff\n", .log = "error: [XKB-542] (input string):1:1: unexpected non-ASCII character.\n" "error: [XKB-542] (input string):1:1: This could be a file encoding issue. Supported file encodings are ASCII and UTF-8.\n" "error: (input string):1:1: failed to parse file\n", .error = true }, { .input = " : x\n" "include \"x\"\n", .log = "warning: [XKB-301] (input string):1:1: deprecated keysym \"leftshoe\".\n" "error: (input string):2:9: failed to open included Compose file \"x\": No such file or directory\n" "error: (input string):2:9: failed to parse file\n", .error = true }, { .input = " : \"a\"\n" "\n" " : \"i\\j\\xk\n" "<0x30> : \"\\400\" invalidKeysym\n" "<0> <1> <2> <3> <4> <5> <6> <7> <8> <9> : \"\"\n", .log = "warning: [XKB-645] (input string):3:7: unknown escape sequence \"\\j\" in string literal\n" "warning: [XKB-193] (input string):3:7: illegal hexadecimal escape sequence \"\\x\" in string literal\n" "error: [XKB-685] (input string):3:7: unterminated string literal\n" "warning: [XKB-193] (input string):4:10: illegal octal escape sequence \"\\400\" in string literal\n" "error: (input string):4:17: unrecognized keysym \"invalidKeysym\" on right-hand side\n" "warning: [XKB-301] (input string):5:41: deprecated keysym \"leftshoe\".\n" "warning: [XKB-685] (input string):5:41: too many keysyms (11) on left-hand side; skipping line\n", .error = false }, { .input = ":\n" " :\n" "#\n" " : \"a\" \"b\"\n" " : a b\n", .log = "warning: (input string):1:1: expected at least one keysym on left-hand side; skipping line\n" "warning: [XKB-685] (input string):2:5: right-hand side must have at least one of string or keysym; skipping line\n" "warning: (input string):4:11: right-hand side can have at most one string; skipping line\n" "error: [XKB-685] (input string):5:9: unrecognized modifier \"b\"\n", .error = false }, { .input = " : a\n" " : a\n" " : b\n" " : x\n" " : y\n" " : c\n", .log = "warning: (input string):2:7: this compose sequence is a duplicate of another; skipping line\n" "warning: (input string):4:11: a sequence already exists which is a prefix of this sequence; overriding\n" "warning: (input string):6:11: this compose sequence is a prefix of another; overriding\n", .error = false } }; for (unsigned int k = 0; k < ARRAY_SIZE(composes); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); struct xkb_compose_table *table = xkb_compose_table_new_from_buffer( ctx, composes[k].input, strlen(composes[k].input), "", XKB_COMPOSE_FORMAT_TEXT_V1, XKB_COMPOSE_COMPILE_NO_FLAGS ); assert(composes[k].error ^ !!table); xkb_compose_table_unref(table); assert_printf(streq_null(darray_items(log_string), composes[k].log), "Expected:\n%s\nGot:\n%s\n", darray_items(log_string), composes[k].log); darray_free(log_string); } xkb_context_unref(ctx); } int main(void) { test_init(); /* We really need to be locale-independent here */ setlocale(LC_ALL, "C"); test_basic(); test_keymaps(); test_compose(); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/merge_modes.c.jinja000066400000000000000000000640371510033435100234000ustar00rootroot00000000000000/* * WARNING: This file is automatically generated by: {{ script }} * Do not edit manually! */ /* * Copyright © 2024-2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include "test.h" #include "utils.h" {% if not compiler.is_default %} #include "external_xkb_compilers.h" {% endif %} enum update_files { NO_UPDATE = 0, UPDATE_USING_TEST_INPUT, UPDATE_USING_TEST_OUTPUT }; #define GOLDEN_TESTS_OUTPUTS "keymaps/merge-modes/" {% if compiler.is_default %} /* xkbcommon buffer compiler */ static struct xkb_keymap * compile_buffer(struct xkb_context *context, enum xkb_keymap_format format, const char *buf, size_t len, void *private) { return test_compile_buffer(context, format, buf, len); } static bool test_compile(struct xkb_context *ctx, const char* xkb_root, const char *test_title, const char *keymap_str, size_t keymap_len, const char *path, bool update) { return test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, test_title, keymap_str, keymap_len, path, !!update); } {% else %} /* Third-party compiler: {{ compiler.name }} */ struct compile_buffer_{{ compiler.name }}_data { const char* xkb_root; }; static int compile_buffer_{{ compiler.name }}(const char *buf, size_t len, void *private, char* *out, size_t *out_size) { struct compile_buffer_{{ compiler.name }}_data *data = private; {% if compiler.name == "xkbcomp" %} /* Xorg xkbcomp */ return compile_with_xkbcomp(NULL, data->xkb_root, buf, len, out, out_size); {% elif compiler.name == "kbvm" %} /* kbvm */ return compile_with_kbvm(data->xkb_root, buf, len, out, out_size); {% else %} #error "Unsupported compiler: {{ compiler.name }}" {% endif %} } static bool test_compile(struct xkb_context *ctx, const char* xkb_root, const char *test_title, const char *keymap_str, size_t keymap_len, const char *path, bool update) { struct compile_buffer_{{ compiler.name }}_data data = { .xkb_root = xkb_root }; return test_third_pary_compile_output(compile_buffer_{{ compiler.name}}, &data, test_title, keymap_str, keymap_len, path, !!update); } {% endif %} struct keymap_test_data { const char* title; const char* file; const char* keymap; const char* expected; }; {% if compiler.extended_syntax %} static void test_vmods(struct xkb_context *ctx, const char* xkb_root, enum update_files update) { #define BASE_VMODS \ "virtual_modifiers U1, U2, U3, U4, U5, U6;\n" \ "virtual_modifiers Z1=none, Z2=none, Z3=none, Z4=none, Z5=none, Z6=none;\n"\ "virtual_modifiers M1=0x1000, M2=0x2000, M3=0x3000, " \ "M4=0x4000, M5=0x5000, M6=0x6000;\n" const struct keymap_test_data tests[] = { /* * Change virtual modifiers in same component */ { .title = "same-component-include-default-augment", .keymap = "xkb_keymap {\n" " xkb_types \"\" {\n" " include \"merge_modes_vmods(base)|merge_modes_vmods(new)\"\n" " };\n" " xkb_compat \"\" { interpret.repeat= True; };\n" "};", .file = "same-component-include-default-augment", }, { .title = "same-component-include-default-override", .keymap = "xkb_keymap {\n" " xkb_types \"\" {\n" " include \"merge_modes_vmods(base)+merge_modes_vmods(new)\"\n" " };\n" " xkb_compat \"\" { interpret.repeat= True; };\n" "};", .file = "same-component-include-default-override", }, /* * Change virtual modifiers in another component */ { .title = "other-component-direct", .keymap = "xkb_keymap {\n" " xkb_types {\n" BASE_VMODS " };\n" " xkb_compat \"\" {\n" " augment virtual_modifiers U1, U2=none, U3=0x300000;\n" " override virtual_modifiers U4, U5=none, U6=0x600000;\n" " augment virtual_modifiers Z1, Z2=none, Z3=0x310000;\n" " override virtual_modifiers Z4, Z5=none, Z6=0x610000;\n" " augment virtual_modifiers M1, M2=none, M3=0x320000;\n" " override virtual_modifiers M4, M5=none, M6=0x620000;\n" " };\n" "};", .file = "other-component-direct", }, { .title = "other-component-include-default", .keymap = "xkb_keymap {\n" " xkb_types \"\" {\n" BASE_VMODS " };\n" " xkb_compat \"\" { include \"merge_modes_vmods(new)\" };\n" "};", .file = "same-component-include-default-override", }, { .title = "other-component-include-augment", .keymap = "xkb_keymap {\n" " xkb_types \"\" {\n" BASE_VMODS " };\n" " xkb_compat \"\" { augment \"merge_modes_vmods(new)\" };\n" "};", .file = "same-component-include-default-augment", }, { .title = "other-component-include-override", .keymap = "xkb_keymap {\n" " xkb_types \"\" {\n" BASE_VMODS " };\n" " xkb_compat \"\" { override \"merge_modes_vmods(new)\" };\n" "};", .file = "same-component-include-default-override", }, { .title = "other-component-include-replace", .keymap = "xkb_keymap {\n" " xkb_types \"\" {\n" BASE_VMODS " };\n" " xkb_compat \"\" { replace \"merge_modes_vmods(new)\" };\n" "};", .file = "same-component-include-default-override", }, }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { const struct keymap_test_data* const test = &tests[k]; char title[1024] = { 0 }; snprintf(title, sizeof(title), "%s #%u: %s", __func__, k, test->title); char path[PATH_MAX] = { 0 }; snprintf(path, sizeof(path), GOLDEN_TESTS_OUTPUTS "vmods-%s{{ compiler.suffix }}.xkb", test->file); assert(test_compile(ctx, xkb_root, title, test->keymap, strlen(test->keymap), path, !!update)); } } {% endif %} static void test_compat(struct xkb_context *ctx, const char* xkb_root, enum update_files update) { // Github Issue #566 const char keymap_str[] = "xkb_keymap {\n" " xkb_keycodes { <> = 8; };\n" " xkb_compat {\n" " interpret A { repeat = true; };\n" " interpret A { repeat = true; };\n" " interpret A { action = SetMods(mods=Mod1); };\n" " interpret B { repeat = true; };\n" " interpret B { repeat = true; };\n" " augment interpret B { action = SetMods(mods=Mod1); };\n" " interpret C { repeat = true; };\n" " interpret C { repeat = true; };\n" " override interpret C { action = SetMods(mods=Mod1); };\n" " interpret D { repeat = true; };\n" " interpret D { repeat = true; };\n" " replace interpret D { action = SetMods(mods=Mod1); };\n" "\n" " indicator \"A\" { modifiers=Shift; };\n" " indicator \"A\" { modifiers=Lock; };\n" " indicator \"A\" { groups= Group1; };\n" " indicator \"B\" { modifiers=Shift; };\n" " indicator \"B\" { modifiers=Lock; };\n" " augment indicator \"B\" { groups=Group1; };\n" " indicator \"C\" { modifiers=Shift; };\n" " indicator \"C\" { modifiers=Lock; };\n" " override indicator \"C\" { groups=Group1; };\n" " indicator \"D\" { modifiers=Shift; };\n" " indicator \"D\" { modifiers=Lock; };\n" " replace indicator \"D\" { groups=Group1; };\n" " };\n" " xkb_symbols { key <> { }; };\n" "};\n"; assert(test_compile(ctx, xkb_root, "test_merge_mode: compat", keymap_str, ARRAY_SIZE(keymap_str) - 1, GOLDEN_TESTS_OUTPUTS "compat{{ compiler.suffix }}.xkb", !!update)); } static void test_merge_modes(struct xkb_context *ctx, const char* xkb_root, enum update_files update) { const struct keymap_test_data tests[] = { {% for group in tests %} /* * #{{ loop.index0 }}{{ " " + group.title if group.title else "" }} */ {% for test in group.tests %} { .title = "#{{ loop.index0 }} {{ test.title | escape_quotes }}", .file = "{{ test.file | string | escape_quotes }}", .keymap = {%- for line in test.content.splitlines() +%} "{{ line | escape_quotes }}\n" {%- endfor %}, .expected = {% for line in test.expected.splitlines() %} "{{ line | escape_quotes }}\n" {% endfor %} }, {% endfor %} {% endfor %} }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { const struct keymap_test_data* const test = &tests[k]; char title[1024] = { 0 }; snprintf(title, sizeof(title), "%s #%u: %s", __func__, k, test->title); char path[PATH_MAX] = { 0 }; {% if compiler.is_default %} snprintf(path, sizeof(path), GOLDEN_TESTS_OUTPUTS "%s.xkb", test->file); {% else %} snprintf(path, sizeof(path), GOLDEN_TESTS_OUTPUTS "%02u-%s{{ compiler.suffix }}.xkb", k, test->file); {% endif %} const char* const keymap = (update == UPDATE_USING_TEST_INPUT) ? test->expected : test->keymap; assert(test_compile(ctx, xkb_root, title, keymap, strlen(keymap), path, !!update)); } } static void test_defaults(struct xkb_context *ctx, const char* xkb_root, enum update_files update) { const struct keymap_test_data tests[] = { { .title = "plain", .file = "plain", .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 38;\n" " = 39;\n" " = 40;\n" " = 41;\n" " = 42;\n" "\n" " indicator 1 = \"A\";\n" " indicator 2 = \"B\";\n" " indicator 3 = \"C\";\n" " };\n" " xkb_types {\n" " type \"ONE_LEVEL\" {\n" " map[None] = 1;\n" " };\n" " type \"ALPHABETIC\" {\n" " modifiers = Shift + Lock;\n" " map[Shift] = 2;\n" " map[Lock] = 2;\n" " };\n" " };\n" " xkb_compat {\n" " virtual_modifiers M1=0x1000, M2=0x2000, M3=0x4000, M4=0x8000;\n" "\n" " interpret.repeat= False;\n" " // Effective: override\n" " interpret.repeat= True;\n" "\n" " interpret.virtualmod = M1;\n" " // Effective: override\n" " interpret.virtualmod = M2;\n" " // Ineffective: cannot augment previous value\n" " augment interpret.virtualmod = M3;\n" "\n" " SetGroup.group = 1;\n" " // Effective: override\n" " SetGroup.group = 2;\n" " // Ineffective: cannot augment previous value\n" " augment SetGroup.group = 3;\n" "\n" "\n" " // Effective: *override* every explicit field\n" " interpret a {\n" " virtualmod = M4;\n" " action=SetGroup(group=1);\n" " };\n" " interpret A {\n" " repeat = False;\n" " virtualmod = M1;\n" " action=SetMods(mods=M1);\n" " };\n" "\n" "\n" " // Effective: no previous interpret entry,\n" " // so *override* every explicit field\n" " augment interpret s {\n" " repeat = False;\n" " action=SetGroup();\n" " };\n" " // Only augment fields not set previously (explicit or implicit)\n" " augment interpret s {\n" " // Ineffective: cannot augment previous implicit value\n" " virtualmod = M4;\n" " // Ineffective: cannot augment previous explicit value\n" " action=SetGroup(group=4);\n" " // Effective: no previous value\n" " useModMapMods=level1;\n" " };\n" " augment interpret S {\n" " action=SetGroup(group=4);\n" " };\n" " interpret g {\n" " virtualmod = M3;\n" " repeat = False;" " action = SetGroup(group=3);\n" " };\n" " indicator \"C\" {\n" " modifiers = M3;\n" " whichmodstate = locked;\n" " };\n" "\n" "\n" " indicator.modifiers = M1;\n" " indicator.modifiers = M2;\n" " augment indicator.modifiers = M3;\n" " indicator.groups = All - 1;\n" " indicator.controls = AudibleBell;\n" "\n" " indicator \"A\" {\n" " modifiers = M4;\n" " whichmodstate = base;\n" " };\n" " indicator \"A\" {\n" " whichmodstate = locked;\n" " whichgroupstate = locked;\n" " controls = SlowKeys;\n" " };\n" " augment indicator \"B\" {\n" " modifiers = M4;\n" " whichmodstate = base;\n" " };\n" " augment indicator \"B\" {\n" " groups = 4;\n" " whichmodstate = locked;\n" " whichgroupstate = locked;\n" " };\n" " };\n" " xkb_symbols {\n" " name[1] = \"xxx\";\n" " name[1] = \"yyy\";\n" " augment name[1] = \"zzz\";\n" "\n" " key { [a, A] };\n" " key { [s, S] };\n" " modifier_map Shift { };\n" " modifier_map Control { };\n" "\n" " key { type = \"ONE_LEVEL\", repeat=true, [g] };" " modifier_map Mod3 { };\n" "\n" " key.repeat = false;\n" " key.vmods = M1;\n" " key.vmods = M2;\n" " augment key.vmods = M3;\n" "\n" " key { vmods = M4, [d, D] };\n" " augment key { vmods = M4, [f, F] };\n" " augment key { vmods = M1, repeat = true };\n" " };\n" "};\n", .expected = "xkb_keymap {\n" " xkb_keycodes {\n" " = 38;\n" " = 39;\n" " = 40;\n" " = 41;\n" " indicator 1 = \"A\";\n" " indicator 2 = \"B\";\n" " indicator 3 = \"C\";\n" " };\n" " xkb_types {\n" " type \"ONE_LEVEL\" {\n" " map[None] = 1;\n" " };\n" " type \"ALPHABETIC\" {\n" " modifiers = Shift + Lock;\n" " map[Shift] = 2;\n" " map[Lock] = 2;\n" " };\n" " };\n" " xkb_compat {\n" " virtual_modifiers M1=0x1000, M2=0x2000, M3=0x4000, M4=0x8000;\n" "\n" " interpret.repeat= True;\n" " interpret.virtualmod = M2;\n" " SetGroup.group = 2;\n" "\n" " interpret a {\n" " virtualmod = M4;\n" " action=SetGroup(group=1);\n" " };\n" " interpret A {\n" " repeat = False;\n" " virtualmod = M1;\n" " action=SetMods(mods=M1);\n" " };\n" " interpret s {\n" " repeat = False;\n" " action=SetGroup(group=2);\n" " useModMapMods=level1;\n" " };\n" " interpret S {\n" " action=SetGroup(group=4);" " };\n" "\n" " indicator.modifiers = M2;\n" " indicator.groups = All - 1;\n" " indicator.controls = AudibleBell;\n" "\n" " indicator \"A\" {\n" " modifiers = M4;\n" " whichmodstate = locked;\n" " whichgroupstate = locked;\n" " controls = SlowKeys;\n" " };\n" " indicator \"B\" {\n" " modifiers = M4;\n" " whichmodstate = base;\n" " whichgroupstate = locked;\n" " };\n" " };\n" " xkb_symbols {\n" " name[1] = \"yyy\";\n" "\n" " key { [a, A] };\n" " key { [s, S] };\n" " modifier_map Shift { };\n" " modifier_map Control { };\n" "\n" " key { vmods = M4, repeat = false, [d, D] };\n" " key { vmods = M4, repeat = true , [f, F] };\n" " key { type = \"ONE_LEVEL\", repeat=true, vmods=M3, [g] };" " };\n" "};\n" }, { .title = "include", .file = "include", .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 38;\n" " = 39;\n" " = 40;\n" " = 41;\n" " = 42;\n" "\n" " indicator 1 = \"A\";\n" " indicator 2 = \"B\";\n" " indicator 3 = \"C\";\n" " };\n" " xkb_types {\n" " type \"ONE_LEVEL\" {\n" " map[None] = 1;\n" " };\n" " type \"ALPHABETIC\" {\n" " modifiers = Shift + Lock;\n" " map[Shift] = 2;\n" " map[Lock] = 2;\n" " };\n" " };\n" " xkb_compat {\n" " virtual_modifiers M1,M2,M3;" " interpret.virtualmod = M3;\n" " indicator.modifiers = M3;\n" " SetGroup.group = 3;\n" "\n" " include \"merge_modes_defaults\"\n" "\n" " interpret g {\n" " action = SetGroup();\n" " };\n" " indicator \"C\" {\n" " whichmodstate = locked;\n" " };\n" " };\n" " xkb_symbols {\n" " name[1] = \"XXX\";\n" "\n" " key.type = \"ONE_LEVEL\";" "\n" " include \"merge_modes_defaults\"\n" "\n" " key { repeat = true, [g, G] };\n" " modifier_map Mod3 { };\n" " };\n" "};\n", .expected = "xkb_keymap {\n" " xkb_keycodes {\n" " = 38;\n" " = 39;\n" " = 40;\n" " = 41;\n" " indicator 1 = \"A\";\n" " indicator 2 = \"B\";\n" " indicator 3 = \"C\";\n" " };\n" " xkb_types {\n" " type \"ONE_LEVEL\" {\n" " map[None] = 1;\n" " };\n" " type \"ALPHABETIC\" {\n" " modifiers = Shift + Lock;\n" " map[Shift] = 2;\n" " map[Lock] = 2;\n" " };\n" " };\n" " xkb_compat {\n" " virtual_modifiers M1=0x1000, M2=0x2000, M3=0x4000, M4=0x8000;\n" "\n" " interpret.repeat= True;\n" " interpret.virtualmod = M2;\n" " SetGroup.group = 2;\n" "\n" " interpret a {\n" " virtualmod = M4;\n" " action=SetGroup(group=1);\n" " };\n" " interpret A {\n" " repeat = False;\n" " virtualmod = M1;\n" " action=SetMods(mods=M1);\n" " };\n" " interpret s {\n" " repeat = False;\n" " action=SetGroup(group=2);\n" " useModMapMods=level1;\n" " };\n" " interpret S {\n" " action=SetGroup(group=4);\n" " };\n" "\n" " indicator.modifiers = M2;\n" " indicator.groups = All - 1;\n" " indicator.controls = AudibleBell;\n" "\n" " indicator \"A\" {\n" " modifiers = M4;\n" " whichmodstate = locked;\n" " whichgroupstate = locked;\n" " controls = SlowKeys;\n" " };\n" " indicator \"B\" {\n" " modifiers = M4;\n" " whichmodstate = base;\n" " whichgroupstate = locked;\n" " };\n" " };\n" " xkb_symbols {\n" " name[1] = \"yyy\";\n" "\n" " key { [a, A] };\n" " key { [s, S] };\n" " modifier_map Shift { };\n" " modifier_map Control { };\n" "\n" " key { vmods = M4, repeat = false, [d, D] };\n" " key { vmods = M4, repeat = true , [f, F] };\n" " key { vmods = M3, [g] };\n" " };\n" "};\n" } }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { const struct keymap_test_data* const test = &tests[k]; char title[1024] = { 0 }; snprintf(title, sizeof(title), "%s #%u: %s", __func__, k, test->title); char path[PATH_MAX] = { 0 }; snprintf(path, sizeof(path), GOLDEN_TESTS_OUTPUTS "defaults-%s{{ compiler.suffix }}.xkb", test->file); assert(test_compile(ctx, xkb_root, title, test->keymap, strlen(test->keymap), path, !!update)); } } int main(int argc, char *argv[]) { test_init(); /* Check if we run the tests or just update their outputs */ enum update_files update_output_files = NO_UPDATE; if (argc > 1) { if (streq(argv[1], "update")) { /* Update files with *expected* results */ update_output_files = UPDATE_USING_TEST_INPUT; } else if (streq(argv[1], "update-obtained")) { /* Update files with *obtained* results */ update_output_files = UPDATE_USING_TEST_OUTPUT; } else { fprintf(stderr, "ERROR: unsupported argument: \"%s\".\n", argv[1]); exit(EXIT_FAILURE); } } struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); char* xkb_root = test_get_path(""); assert(xkb_root); {% if compiler.extended_syntax %} test_vmods(ctx, xkb_root, update_output_files); {% endif %} test_compat(ctx, xkb_root, update_output_files); test_merge_modes(ctx, xkb_root, update_output_files); test_defaults(ctx, xkb_root, update_output_files); free(xkb_root); xkb_context_unref(ctx); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/meson_test.map000066400000000000000000000000771510033435100225250ustar00rootroot00000000000000VERSION_1 { global: main; local: *; }; xkbcommon-libxkbcommon-54ee7ac/test/messages.c000066400000000000000000000021571510033435100216220ustar00rootroot00000000000000/* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "test.h" #include "messages-codes.h" #include "messages.h" static void test_message_get(void) { const struct xkb_message_entry* entry; /* Invalid codes */ /* NOTE: 0 must not be a valid message code */ entry = xkb_message_get(0); assert(entry == NULL); entry = xkb_message_get(_XKB_LOG_MESSAGE_MIN_CODE - 1); assert(entry == NULL); entry = xkb_message_get(_XKB_LOG_MESSAGE_MAX_CODE + 1); assert(entry == NULL); /* Valid codes */ entry = xkb_message_get(_XKB_LOG_MESSAGE_MIN_CODE); assert(entry != NULL); entry = xkb_message_get(XKB_WARNING_CANNOT_INFER_KEY_TYPE); assert(entry != NULL); entry = xkb_message_get(XKB_ERROR_INVALID_XKB_SYNTAX); assert(entry != NULL); entry = xkb_message_get(XKB_WARNING_CONFLICTING_KEY_FIELDS); assert(entry != NULL); entry = xkb_message_get(_XKB_LOG_MESSAGE_MAX_CODE); assert(entry != NULL); } int main(void) { test_init(); test_message_get(); } xkbcommon-libxkbcommon-54ee7ac/test/modifiers.c000066400000000000000000001002721510033435100217710ustar00rootroot00000000000000/* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-names.h" #include "evdev-scancodes.h" #include "test.h" #include "keymap.h" #include "utils.h" /* Standard real modifier masks */ enum real_mod_mask { ShiftMask = (UINT32_C(1) << XKB_MOD_INDEX_SHIFT), LockMask = (UINT32_C(1) << XKB_MOD_INDEX_CAPS), ControlMask = (UINT32_C(1) << XKB_MOD_INDEX_CTRL), Mod1Mask = (UINT32_C(1) << XKB_MOD_INDEX_MOD1), Mod2Mask = (UINT32_C(1) << XKB_MOD_INDEX_MOD2), Mod3Mask = (UINT32_C(1) << XKB_MOD_INDEX_MOD3), Mod4Mask = (UINT32_C(1) << XKB_MOD_INDEX_MOD4), Mod5Mask = (UINT32_C(1) << XKB_MOD_INDEX_MOD5), NoModifier = 0 }; static bool test_real_mod(struct xkb_keymap *keymap, const char* name, xkb_mod_index_t idx, xkb_mod_mask_t mapping) { return xkb_keymap_mod_get_index(keymap, name) == idx && (keymap->mods.mods[idx].type == MOD_REAL) && mapping == keymap->mods.mods[idx].mapping && mapping == (UINT32_C(1) << idx) && xkb_keymap_mod_get_mask(keymap, name) == mapping && xkb_keymap_mod_get_mask2(keymap, idx) == mapping; } static bool test_virtual_mod(struct xkb_keymap *keymap, const char* name, xkb_mod_index_t idx, xkb_mod_mask_t mapping) { return xkb_keymap_mod_get_index(keymap, name) == idx && (keymap->mods.mods[idx].type == MOD_VIRT) && mapping == keymap->mods.mods[idx].mapping && xkb_keymap_mod_get_mask(keymap, name) == mapping && xkb_keymap_mod_get_mask2(keymap, idx) == mapping; } /* Check that the provided modifier names work */ static void test_modifiers_names(struct xkb_context *context) { struct xkb_keymap *keymap; keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "us", NULL, NULL); assert(keymap); /* Real modifiers * The indices and masks are fixed and always valid */ assert(test_real_mod(keymap, XKB_MOD_NAME_SHIFT, XKB_MOD_INDEX_SHIFT, ShiftMask)); assert(test_real_mod(keymap, XKB_MOD_NAME_CAPS, XKB_MOD_INDEX_CAPS, LockMask)); assert(test_real_mod(keymap, XKB_MOD_NAME_CTRL, XKB_MOD_INDEX_CTRL, ControlMask)); assert(test_real_mod(keymap, XKB_MOD_NAME_MOD1, XKB_MOD_INDEX_MOD1, Mod1Mask)); assert(test_real_mod(keymap, XKB_MOD_NAME_MOD2, XKB_MOD_INDEX_MOD2, Mod2Mask)); assert(test_real_mod(keymap, XKB_MOD_NAME_MOD3, XKB_MOD_INDEX_MOD3, Mod3Mask)); assert(test_real_mod(keymap, XKB_MOD_NAME_MOD4, XKB_MOD_INDEX_MOD4, Mod4Mask)); assert(test_real_mod(keymap, XKB_MOD_NAME_MOD5, XKB_MOD_INDEX_MOD5, Mod5Mask)); /* Usual virtual mods mappings */ assert(test_real_mod(keymap, XKB_MOD_NAME_ALT, XKB_MOD_INDEX_MOD1, Mod1Mask)); assert(test_real_mod(keymap, XKB_MOD_NAME_NUM, XKB_MOD_INDEX_MOD2, Mod2Mask)); assert(test_real_mod(keymap, XKB_MOD_NAME_LOGO, XKB_MOD_INDEX_MOD4, Mod4Mask)); /* Virtual modifiers * The indices depends on the keymap files */ assert(test_virtual_mod(keymap, XKB_VMOD_NAME_ALT, XKB_MOD_INDEX_MOD5 + 2, Mod1Mask)); assert(test_virtual_mod(keymap, XKB_VMOD_NAME_META, XKB_MOD_INDEX_MOD5 + 11, Mod1Mask)); assert(test_virtual_mod(keymap, XKB_VMOD_NAME_NUM, XKB_MOD_INDEX_MOD5 + 1, Mod2Mask)); assert(test_virtual_mod(keymap, XKB_VMOD_NAME_SUPER, XKB_MOD_INDEX_MOD5 + 12, Mod4Mask)); assert(test_virtual_mod(keymap, XKB_VMOD_NAME_HYPER, XKB_MOD_INDEX_MOD5 + 13, Mod4Mask)); assert(test_virtual_mod(keymap, XKB_VMOD_NAME_LEVEL3, XKB_MOD_INDEX_MOD5 + 3, Mod5Mask)); assert(test_virtual_mod(keymap, XKB_VMOD_NAME_SCROLL, XKB_MOD_INDEX_MOD5 + 8, 0 )); /* TODO: current xkeyboard-config maps LevelFive to Nod3 by default */ assert(test_virtual_mod(keymap, XKB_VMOD_NAME_LEVEL5, XKB_MOD_INDEX_MOD5 + 9, 0)); /* Legacy stuff, removed from xkeyboard-config */ assert(keymap->mods.num_mods == 21); assert(test_virtual_mod(keymap, "LAlt", XKB_MOD_INDEX_MOD5 + 4, 0 )); assert(test_virtual_mod(keymap, "RAlt", XKB_MOD_INDEX_MOD5 + 5, 0 )); assert(test_virtual_mod(keymap, "LControl", XKB_MOD_INDEX_MOD5 + 7, 0 )); assert(test_virtual_mod(keymap, "RControl", XKB_MOD_INDEX_MOD5 + 6, 0 )); assert(test_virtual_mod(keymap, "AltGr", XKB_MOD_INDEX_MOD5 + 10, Mod5Mask)); xkb_keymap_unref(keymap); } static void test_modmap_none(struct xkb_context *context) { struct xkb_keymap *keymap; const struct xkb_key *key; xkb_keycode_t keycode; keymap = test_compile_file( context, XKB_KEYMAP_FORMAT_TEXT_V1, "keymaps/modmap-none.xkb" ); assert(keymap); keycode = xkb_keymap_key_by_name(keymap, "LVL3"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == NoModifier); keycode = xkb_keymap_key_by_name(keymap, "LFSH"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == NoModifier); keycode = xkb_keymap_key_by_name(keymap, "RTSH"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == NoModifier); keycode = xkb_keymap_key_by_name(keymap, "LWIN"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod4Mask); keycode = xkb_keymap_key_by_name(keymap, "RWIN"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod4Mask); keycode = xkb_keymap_key_by_name(keymap, "LCTL"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == ControlMask); keycode = xkb_keymap_key_by_name(keymap, "RCTL"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == ControlMask); keycode = xkb_keymap_key_by_name(keymap, "LALT"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod1Mask); keycode = xkb_keymap_key_by_name(keymap, "RALT"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == (Mod2Mask | Mod5Mask)); keycode = xkb_keymap_key_by_name(keymap, "CAPS"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == LockMask); keycode = xkb_keymap_key_by_name(keymap, "AD01"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod1Mask); keycode = xkb_keymap_key_by_name(keymap, "AD02"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == NoModifier); keycode = xkb_keymap_key_by_name(keymap, "AD03"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == NoModifier); keycode = xkb_keymap_key_by_name(keymap, "AD04"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod1Mask); keycode = xkb_keymap_key_by_name(keymap, "AD05"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod2Mask); keycode = xkb_keymap_key_by_name(keymap, "AD06"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod3Mask); keycode = xkb_keymap_key_by_name(keymap, "AD07"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod1Mask); keycode = xkb_keymap_key_by_name(keymap, "AD08"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod2Mask); keycode = xkb_keymap_key_by_name(keymap, "AD09"); assert(keycode != XKB_KEYCODE_INVALID); key = XkbKey(keymap, keycode); assert(key->modmap == Mod3Mask); xkb_keymap_unref(keymap); } static void test_explicit_virtual_modifiers(struct xkb_context *context) { const struct { const char* keymap; struct mod_props { enum mod_type type; xkb_mod_mask_t mapping; xkb_mod_mask_t mapping_effective; } m1; struct mod_props m2; } tests[] = { /* Test virtual modifiers with canonical mappings */ { .keymap = "xkb_keymap {\n" " xkb_compat {\n" /* Vmods map to themselves */ " virtual_modifiers M1 = 0x100, M2 = 0x200;\n" " };\n" "};", .m1 = { .type = MOD_VIRT, .mapping = 0x100, .mapping_effective = 0x100 }, .m2 = { .type = MOD_VIRT, .mapping = 0x200, .mapping_effective = 0x200 } }, /* Test virtual modifiers overlapping: identical */ { .keymap = "xkb_keymap {\n" " xkb_compat {\n" " virtual_modifiers M1 = 0x100, M2 = 0x100;\n" " };\n" "};", .m1 = { .type = MOD_VIRT, .mapping = 0x100, .mapping_effective = 0x100 }, .m2 = { .type = MOD_VIRT, .mapping = 0x100, .mapping_effective = 0x100 } }, /* Test virtual modifiers overlapping: non identical */ { .keymap = "xkb_keymap {\n" " xkb_compat {\n" " virtual_modifiers M1 = 0x100, M2 = 0x300;\n" " };\n" "};", .m1 = { .type = MOD_VIRT, .mapping = 0x100, .mapping_effective = 0x100 }, .m2 = { .type = MOD_VIRT, .mapping = 0x300, .mapping_effective = 0x300 } }, /* Test virtual modifiers with swapped mappings */ { .keymap = "xkb_keymap {\n" " xkb_compat {\n" /* The mapping of each modifier is the mask of the other */ " virtual_modifiers M1 = 0x200, M2 = 0x100;\n" " };\n" "};", .m1 = { .type = MOD_VIRT, .mapping = 0x200, .mapping_effective = 0x100 /* different from mapping! */ }, .m2 = { .type = MOD_VIRT, .mapping = 0x100, .mapping_effective = 0x200 /* different from mapping! */ } }, /* Test virtual modifiers mapping to undefined modifiers */ { .keymap = "xkb_keymap {\n" " xkb_compat {\n" " virtual_modifiers M1 = 0x400, M2 = 0x800;\n" " };\n" "};", .m1 = { .type = MOD_VIRT, .mapping = 0x400, .mapping_effective = 0 /* no mod entry */ }, .m2 = { .type = MOD_VIRT, .mapping = 0x800, .mapping_effective = 0 /* no mod entry */ } }, }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); struct xkb_keymap *keymap = test_compile_buffer( context, XKB_KEYMAP_FORMAT_TEXT_V1, tests[k].keymap, strlen(tests[k].keymap) ); assert(keymap); const xkb_mod_index_t m1_idx = xkb_keymap_mod_get_index(keymap, "M1"); const xkb_mod_index_t m2_idx = xkb_keymap_mod_get_index(keymap, "M2"); assert(m1_idx == 8); assert(m2_idx == 9); assert(keymap->mods.mods[m1_idx].type == tests[k].m1.type); assert(keymap->mods.mods[m2_idx].type == tests[k].m2.type); const xkb_mod_mask_t m1 = UINT32_C(1) << m1_idx; const xkb_mod_mask_t m2 = UINT32_C(1) << m2_idx; const xkb_mod_mask_t m1_mapping = mod_mask_get_effective(keymap, m1); const xkb_mod_mask_t m2_mapping = mod_mask_get_effective(keymap, m2); assert(m1_mapping == tests[k].m1.mapping); assert(m2_mapping == tests[k].m2.mapping); /* mod_mask_get_effective is not idempotent */ assert(mod_mask_get_effective(keymap, m1_mapping) == tests[k].m1.mapping_effective); assert(mod_mask_get_effective(keymap, m2_mapping) == tests[k].m2.mapping_effective); struct xkb_state *state = xkb_state_new(keymap); assert(state); /* Not in the canonical modifier mask nor denotes a *known* virtual * modifiers, so it will be discarded. */ const xkb_mod_mask_t noise = UINT32_C(0x8000); assert((keymap->canonical_state_mask & noise) == 0); /* Update the state, then check round-trip and mods state */ const xkb_mod_mask_t set_masks[] = {m1_mapping, m2_mapping}; for (unsigned int m = 0; m < ARRAY_SIZE(set_masks); m++) { const xkb_mod_mask_t expected = set_masks[m]; xkb_state_update_mask(state, expected | noise, 0, noise, 0, 0, 0); const xkb_mod_mask_t got = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); assert_printf(got == expected, /* round-trip */ "expected %#"PRIx32", got %#"PRIx32"\n", expected, got); assert( xkb_state_mod_index_is_active(state, m1_idx, XKB_STATE_MODS_EFFECTIVE) == ((expected & m1_mapping) == m1_mapping) ); assert( xkb_state_mod_index_is_active(state, m2_idx, XKB_STATE_MODS_EFFECTIVE) == ((expected & m2_mapping) == m2_mapping) ); } xkb_state_unref(state); xkb_keymap_unref(keymap); } } /* * Test the hack documented in the FAQ to get virtual modifiers mapping using * `xkb_state_update_mask`/`xkb_state_serialize_mods`. * * This should work without problem for keymap using only real mods to map * virtual modifiers. * * [NOTE] If the test requires an update, do not forget to update the FAQ as well! */ static void test_virtual_modifiers_mapping_hack(struct xkb_context *context) { struct xkb_keymap *keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "us", NULL, NULL); assert(keymap); struct xkb_state* state = xkb_state_new(keymap); assert(state); static const struct { const char* name; xkb_mod_index_t index; xkb_mod_mask_t mapping; } mods[] = { /* Real modifiers */ { .name = XKB_MOD_NAME_SHIFT, .index = XKB_MOD_INDEX_SHIFT, .mapping = UINT32_C(1) << XKB_MOD_INDEX_SHIFT }, { .name = XKB_MOD_NAME_CAPS, .index = XKB_MOD_INDEX_CAPS, .mapping = UINT32_C(1) << XKB_MOD_INDEX_CAPS }, { .name = XKB_MOD_NAME_CTRL, .index = XKB_MOD_INDEX_CTRL, .mapping = UINT32_C(1) << XKB_MOD_INDEX_CTRL }, { .name = XKB_MOD_NAME_MOD1, .index = XKB_MOD_INDEX_MOD1, .mapping = UINT32_C(1) << XKB_MOD_INDEX_MOD1 }, { .name = XKB_MOD_NAME_MOD2, .index = XKB_MOD_INDEX_MOD2, .mapping = UINT32_C(1) << XKB_MOD_INDEX_MOD2 }, { .name = XKB_MOD_NAME_MOD3, .index = XKB_MOD_INDEX_MOD3, .mapping = UINT32_C(1) << XKB_MOD_INDEX_MOD3 }, { .name = XKB_MOD_NAME_MOD4, .index = XKB_MOD_INDEX_MOD4, .mapping = UINT32_C(1) << XKB_MOD_INDEX_MOD4 }, { .name = XKB_MOD_NAME_MOD5, .index = XKB_MOD_INDEX_MOD5, .mapping = UINT32_C(1) << XKB_MOD_INDEX_MOD5 }, /* Virtual modifiers * The indices depends on the keymap files */ { .name = XKB_VMOD_NAME_ALT, .index = XKB_MOD_INDEX_MOD5 + 2, .mapping = Mod1Mask }, { .name = XKB_VMOD_NAME_META, .index = XKB_MOD_INDEX_MOD5 + 11, .mapping = Mod1Mask }, { .name = XKB_VMOD_NAME_NUM, .index = XKB_MOD_INDEX_MOD5 + 1, .mapping = Mod2Mask }, { .name = XKB_VMOD_NAME_SUPER, .index = XKB_MOD_INDEX_MOD5 + 12, .mapping = Mod4Mask }, { .name = XKB_VMOD_NAME_HYPER, .index = XKB_MOD_INDEX_MOD5 + 13, .mapping = Mod4Mask }, { .name = XKB_VMOD_NAME_LEVEL3, .index = XKB_MOD_INDEX_MOD5 + 3, .mapping = Mod5Mask }, { .name = XKB_VMOD_NAME_SCROLL, .index = XKB_MOD_INDEX_MOD5 + 8, .mapping = 0 }, { .name = XKB_VMOD_NAME_LEVEL5, .index = XKB_MOD_INDEX_MOD5 + 9, .mapping = 0 }, /* Legacy stuff, removed from xkeyboard-config */ { .name = "LAlt", .index = XKB_MOD_INDEX_MOD5 + 4, .mapping = 0 }, { .name = "RAlt", .index = XKB_MOD_INDEX_MOD5 + 5, .mapping = 0 }, { .name = "LControl", .index = XKB_MOD_INDEX_MOD5 + 7, .mapping = 0 }, { .name = "RControl", .index = XKB_MOD_INDEX_MOD5 + 6, .mapping = 0 }, { .name = "AltGr", .index = XKB_MOD_INDEX_MOD5 + 10, .mapping = Mod5Mask }, }; for (unsigned int k = 0; k < ARRAY_SIZE(mods); k++) { const xkb_mod_mask_t index = xkb_keymap_mod_get_index(keymap, mods[k].name); assert_printf(index == mods[k].index, "%s: expected %"PRIu32", got: %"PRIu32"\n", mods[k].name, mods[k].index, index); const xkb_mod_mask_t mask = UINT32_C(1) << index; xkb_state_update_mask(state, mask, 0, 0, 0, 0, 0); const xkb_mod_mask_t mapping = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); assert_printf(mapping == mods[k].mapping, "%s: expected %#"PRIx32", got: %#"PRIx32"\n", mods[k].name, mods[k].mapping, mapping); assert(mapping == xkb_keymap_mod_get_mask(keymap, mods[k].name)); assert(mapping == xkb_keymap_mod_get_mask2(keymap, mods[k].index)); } xkb_state_unref(state); xkb_keymap_unref(keymap); } static void test_pure_virtual_modifiers(struct xkb_context *context) { struct xkb_keymap *keymap; /* Test definition of >20 pure virtual modifiers. * We overcome the X11 limit of 16 virtual modifiers. */ struct { const char* path; enum xkb_keymap_format formats[2]; } keymaps[] = { { .path = "keymaps/pure-virtual-mods-explicit.xkb", .formats = { XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_FORMAT_TEXT_V2 } }, { .path = "keymaps/pure-virtual-mods-implicit.xkb", /* Auto canonical vmod available since keymap format v2 */ .formats = { XKB_KEYMAP_FORMAT_TEXT_V2 } } }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { for (unsigned int f = 0; f < ARRAY_SIZE(keymaps[k].formats); f++) { if (!keymaps[k].formats[f]) break; fprintf(stderr, "------\n*** %s: #%u %s (%d) ***\n", __func__, k, keymaps[k].path, keymaps[k].formats[f]); keymap = test_compile_file(context, keymaps[k].formats[f], keymaps[k].path); assert(keymap); assert(test_key_seq(keymap, KEY_W, BOTH, XKB_KEY_w, NEXT, KEY_A, DOWN, XKB_KEY_a, NEXT, KEY_W, BOTH, XKB_KEY_a, NEXT, KEY_A, UP, XKB_KEY_a, NEXT, KEY_B, DOWN, XKB_KEY_b, NEXT, KEY_W, BOTH, XKB_KEY_b, NEXT, KEY_B, UP, XKB_KEY_b, NEXT, KEY_C, DOWN, XKB_KEY_c, NEXT, KEY_W, BOTH, XKB_KEY_c, NEXT, KEY_C, UP, XKB_KEY_c, NEXT, KEY_D, DOWN, XKB_KEY_d, NEXT, KEY_W, BOTH, XKB_KEY_d, NEXT, KEY_D, UP, XKB_KEY_d, NEXT, KEY_E, DOWN, XKB_KEY_e, NEXT, KEY_W, BOTH, XKB_KEY_e, NEXT, KEY_E, UP, XKB_KEY_e, NEXT, KEY_F, DOWN, XKB_KEY_f, NEXT, KEY_W, BOTH, XKB_KEY_f, NEXT, KEY_F, UP, XKB_KEY_f, NEXT, KEY_G, DOWN, XKB_KEY_g, NEXT, KEY_W, BOTH, XKB_KEY_g, NEXT, KEY_G, UP, XKB_KEY_g, NEXT, KEY_H, DOWN, XKB_KEY_h, NEXT, KEY_W, BOTH, XKB_KEY_h, NEXT, KEY_H, UP, XKB_KEY_h, NEXT, KEY_I, DOWN, XKB_KEY_i, NEXT, KEY_W, BOTH, XKB_KEY_i, NEXT, KEY_I, UP, XKB_KEY_i, NEXT, KEY_J, DOWN, XKB_KEY_j, NEXT, KEY_W, BOTH, XKB_KEY_j, NEXT, KEY_J, UP, XKB_KEY_j, NEXT, KEY_K, DOWN, XKB_KEY_k, NEXT, KEY_W, BOTH, XKB_KEY_k, NEXT, KEY_K, UP, XKB_KEY_k, NEXT, KEY_L, DOWN, XKB_KEY_l, NEXT, KEY_W, BOTH, XKB_KEY_l, NEXT, KEY_L, UP, XKB_KEY_l, NEXT, KEY_M, DOWN, XKB_KEY_m, NEXT, KEY_W, BOTH, XKB_KEY_m, NEXT, KEY_M, UP, XKB_KEY_m, NEXT, KEY_N, DOWN, XKB_KEY_n, NEXT, KEY_W, BOTH, XKB_KEY_n, NEXT, KEY_N, UP, XKB_KEY_n, NEXT, KEY_O, DOWN, XKB_KEY_o, NEXT, KEY_W, BOTH, XKB_KEY_o, NEXT, KEY_O, UP, XKB_KEY_o, NEXT, KEY_P, DOWN, XKB_KEY_p, NEXT, KEY_W, BOTH, XKB_KEY_p, NEXT, KEY_P, UP, XKB_KEY_p, NEXT, KEY_Q, DOWN, XKB_KEY_q, NEXT, KEY_W, BOTH, XKB_KEY_q, NEXT, KEY_Q, UP, XKB_KEY_q, NEXT, KEY_R, DOWN, XKB_KEY_r, NEXT, KEY_W, BOTH, XKB_KEY_r, NEXT, KEY_R, UP, XKB_KEY_r, NEXT, KEY_S, DOWN, XKB_KEY_s, NEXT, KEY_W, BOTH, XKB_KEY_s, NEXT, KEY_S, UP, XKB_KEY_s, NEXT, KEY_T, DOWN, XKB_KEY_t, NEXT, KEY_W, BOTH, XKB_KEY_t, NEXT, KEY_T, UP, XKB_KEY_t, NEXT, KEY_U, DOWN, XKB_KEY_u, NEXT, KEY_W, BOTH, XKB_KEY_u, NEXT, KEY_U, UP, XKB_KEY_u, NEXT, KEY_V, DOWN, XKB_KEY_v, NEXT, KEY_W, BOTH, XKB_KEY_v, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_W, BOTH, XKB_KEY_V, NEXT, KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, NEXT, KEY_V, UP, XKB_KEY_v, NEXT, KEY_A, DOWN, XKB_KEY_a, NEXT, KEY_S, DOWN, XKB_KEY_s, NEXT, KEY_W, BOTH, XKB_KEY_1, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_W, BOTH, XKB_KEY_4, NEXT, KEY_S, UP, XKB_KEY_s, NEXT, KEY_W, BOTH, XKB_KEY_3, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_Q, DOWN, XKB_KEY_q, NEXT, KEY_W, BOTH, XKB_KEY_2, NEXT, KEY_Q, UP, XKB_KEY_q, NEXT, KEY_B, DOWN, XKB_KEY_b, NEXT, KEY_C, DOWN, XKB_KEY_c, NEXT, KEY_W, BOTH, XKB_KEY_5, NEXT, KEY_C, UP, XKB_KEY_c, NEXT, KEY_B, UP, XKB_KEY_b, NEXT, KEY_A, UP, XKB_KEY_a, NEXT, KEY_Y, BOTH, XKB_KEY_y, FINISH)); xkb_keymap_unref(keymap); }} /* Test invalid interpret using a virtual modifier */ const char keymap_str[] = "xkb_keymap {" " xkb_keycodes { include \"evdev\" };" " xkb_types { include \"complete\" };" " xkb_compat { include \"complete+basic(invalid-pure-virtual-modifiers)\" };" " xkb_symbols { include \"pc(pc105-pure-virtual-modifiers)\" };" "};"; keymap = test_compile_string(context, XKB_KEYMAP_FORMAT_TEXT_V1, keymap_str); assert(!keymap); } /* Test FAQ snippet */ //! [xkb_keymap_mod_get_codes] #include /** * Get the keycodes associated with a modifier by index. * * @param[in] keymap The keymap * @param[in] idx The index of the modifier * @param[out] codes_out A buffer in which the codes should be stored * @param[out] codes_size The size of the codes_out buffer * * @returns the number of key codes in the keysyms_out array, or a negative * in case of error. */ static ssize_t xkb_keymap_mod_get_codes(struct xkb_keymap *keymap, xkb_mod_index_t mod, xkb_keycode_t *codes_out, size_t codes_size) { if (mod >= xkb_keymap_num_mods(keymap)) return -1; ssize_t idx = 0; for (xkb_keycode_t k = xkb_keymap_min_keycode(keymap); k <= xkb_keymap_max_keycode(keymap) && idx >= 0; k++) { /* * We only test the first level of the first group. * * Since there is currently no way to reset the state, use a new one to * avoid side effects (latches, etc.) */ struct xkb_state * const state = xkb_state_new(keymap); assert(state); static const enum xkb_key_direction directions[] = { XKB_KEY_DOWN, XKB_KEY_UP }; for (size_t d = 0; d < ARRAY_SIZE(directions); d++) { if (xkb_state_update_key(state, k, directions[d]) && xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_EFFECTIVE)) { if ((size_t) idx < codes_size) { assert(idx < (ssize_t) (SIZE_MAX / 2)); codes_out[idx++] = k; } else { idx = -2; } break; } } xkb_state_unref(state); } return idx; } //! [xkb_keymap_mod_get_codes] static void test_get_modifier_keycodes(struct xkb_context *context) { struct xkb_keymap *keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc104", "cz", NULL, NULL); assert(keymap); #define MAX_KEYCODES_COUNT 10 #define KEY_LVL3 (92 - EVDEV_OFFSET) const struct { const char *mod; xkb_keycode_t keycodes[MAX_KEYCODES_COUNT]; } mods[] = { { .mod = XKB_MOD_NAME_SHIFT, .keycodes = { KEY_LEFTSHIFT, KEY_RIGHTSHIFT, 0 } }, { .mod = XKB_MOD_NAME_CAPS, .keycodes = { KEY_CAPSLOCK, 0 } }, { .mod = XKB_MOD_NAME_CTRL, .keycodes = { KEY_LEFTCTRL, KEY_RIGHTCTRL, 0 } }, { .mod = XKB_MOD_NAME_MOD1, .keycodes = { KEY_LEFTALT, 0 } }, { .mod = XKB_MOD_NAME_MOD2, .keycodes = { KEY_NUMLOCK, 0 } }, { .mod = XKB_MOD_NAME_MOD3, .keycodes = { 0 } }, { .mod = XKB_MOD_NAME_MOD4, .keycodes = { KEY_LEFTMETA, KEY_RIGHTMETA, 0 } }, { .mod = XKB_MOD_NAME_MOD5, .keycodes = { KEY_LVL3, KEY_RIGHTALT, 0 } }, { .mod = XKB_VMOD_NAME_ALT, .keycodes = { KEY_LEFTALT, 0 } }, { .mod = XKB_VMOD_NAME_META, .keycodes = { KEY_LEFTALT, 0 } }, { .mod = XKB_VMOD_NAME_SUPER, .keycodes = { KEY_LEFTMETA, KEY_RIGHTMETA, 0 } }, { .mod = XKB_VMOD_NAME_HYPER, .keycodes = { KEY_LEFTMETA, KEY_RIGHTMETA, 0 } }, { .mod = XKB_VMOD_NAME_NUM, .keycodes = { KEY_NUMLOCK, 0 } }, { .mod = XKB_VMOD_NAME_LEVEL3, .keycodes = { KEY_LVL3, KEY_RIGHTALT, 0 } }, { .mod = XKB_VMOD_NAME_LEVEL5, .keycodes = { 0 } }, }; xkb_keycode_t got[MAX_KEYCODES_COUNT] = {0}; for (size_t m = 0; m < ARRAY_SIZE(mods); m++) { const xkb_mod_index_t mod = xkb_keymap_mod_get_index(keymap, mods[m].mod); assert(mod != XKB_MOD_INVALID); const ssize_t count = xkb_keymap_mod_get_codes(keymap, mod, got, ARRAY_SIZE(got)); assert(count >= 0); const xkb_keycode_t * const expected = mods[m].keycodes; for (size_t k = 0; k < ARRAY_SIZE(got); k++) { if (expected[k] == 0) { assert_printf(k == (size_t) count, "Mod %s: expected %zu, got %zd\n", mods[m].mod, k, count); break; } assert_printf(k < (size_t) count, "Mod %s: Missing keycode 0x%"PRIu32"\n", mods[m].mod, expected[k]); assert_printf(got[k] == expected[k] + EVDEV_OFFSET, "Mod %s: Expected keycode %"PRIu32" but got: %"PRIu32"\n", mods[m].mod, expected[k] + EVDEV_OFFSET, got[k]); } } xkb_keymap_unref(keymap); } #undef MAX_KEYCODES_COUNT int main(void) { test_init(); struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); assert(context); test_modmap_none(context); test_modifiers_names(context); test_explicit_virtual_modifiers(context); test_virtual_modifiers_mapping_hack(context); test_pure_virtual_modifiers(context); test_get_modifier_keycodes(context); xkb_context_unref(context); return 0; } xkbcommon-libxkbcommon-54ee7ac/test/registry.c000066400000000000000000001004671510033435100216660ustar00rootroot00000000000000/* * Copyright © 2020 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #include "config.h" #include #if HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include "xkbcommon/xkbregistry.h" #include "utils.h" #include "test.h" #define NO_VARIANT NULL enum { MODEL = 78, LAYOUT, VARIANT, OPTION, }; enum popularity { POPULARITY_UNDEFINED = 0, /* Not member of enum rxkb_popularity */ POPULARITY_STANDARD = RXKB_POPULARITY_STANDARD, POPULARITY_EXOTIC = RXKB_POPULARITY_EXOTIC, }; struct test_model { const char *name; /* required */ const char *vendor; const char *description; }; struct test_layout { const char *name; /* required */ const char *variant; const char *brief; const char *description; const char *iso639[3]; /* language list (iso639 three letter codes), 3 is enough for our test */ const char *iso3166[3]; /* country list (iso3166 two letter codes), 3 is enough for our tests */ enum popularity popularity; }; struct test_option { const char *name; const char *description; }; struct test_option_group { const char *name; const char *description; bool allow_multiple_selection; struct test_option options[10]; }; static const char * popularity_attr(enum popularity popularity) { switch (popularity) { case POPULARITY_UNDEFINED: return ""; case RXKB_POPULARITY_STANDARD: return " popularity=\"standard\""; case RXKB_POPULARITY_EXOTIC: return " popularity=\"exotic\""; default: fprintf(stderr, "ERROR: unsupported popularity: %d\n", popularity); assert(false); } } static void fprint_config_item(FILE *fp, const char *name, const char *vendor, const char *brief, const char *description, const char * const iso639[3], const char * const iso3166[3], enum popularity popularity) { fprintf(fp, " \n" " %s\n", popularity_attr(popularity), name); if (brief) fprintf(fp, " %s\n", brief); if (description) fprintf(fp, " %s\n", description); if (vendor) fprintf(fp, " %s\n", vendor); if (iso3166 && iso3166[0]) { fprintf(fp, " \n"); for (int i = 0; i < 3; i++) { const char *iso = iso3166[i]; if (!iso) break; fprintf(fp, " %s\n", iso); } fprintf(fp, " \n"); } if (iso639 && iso639[0]) { fprintf(fp, " \n"); for (int i = 0; i < 3; i++) { const char *iso = iso639[i]; if (!iso) break; fprintf(fp, " %s\n", iso); } fprintf(fp, " \n"); } fprintf(fp, " \n"); } /** * Create a directory populated with a rules/.xml that contains the * given items. * * @return the XKB base directory */ static char * test_create_rules(const char *ruleset, const struct test_model *test_models, const struct test_layout *test_layouts, const struct test_option_group *test_groups) { static int iteration; char *tmpdir; char buf[PATH_MAX]; int rc; FILE *fp; char *template = asprintf_safe("%s.%d.XXXXXX", ruleset, iteration++); assert(template != NULL); tmpdir = test_maketempdir(template); free(template); free(test_makedir(tmpdir, "rules")); rc = snprintf_safe(buf, sizeof(buf), "%s/rules/%s.xml", tmpdir, ruleset); assert(rc); fp = fopen(buf, "w"); assert(fp); fprintf(fp, "\n" "\n" "\n"); if (test_models) { fprintf(fp, "\n"); for (const struct test_model *m = test_models; m->name; m++) { fprintf(fp, "\n"); fprint_config_item(fp, m->name, m->vendor, NULL, m->description, NULL, NULL, POPULARITY_UNDEFINED); fprintf(fp, "\n"); } fprintf(fp, "\n"); } if (test_layouts) { const struct test_layout *l, *next; fprintf(fp, "\n"); l = test_layouts; next = l + 1; assert(l->variant == NULL); while (l->name) { fprintf(fp, "\n"); fprint_config_item(fp, l->name, NULL, l->brief, l->description, l->iso639, l->iso3166, l->popularity); if (next->name && streq(next->name, l->name)) { fprintf(fp, "\n"); do { fprintf(fp, "\n"); fprint_config_item(fp, next->variant, NULL, next->brief, next->description, next->iso639, next->iso3166, next->popularity); fprintf(fp, "\n"); l = next; next++; } while (next->name && streq(next->name, l->name)); fprintf(fp, "\n"); } fprintf(fp, "\n"); l++; next = l + 1; } fprintf(fp, "\n"); } if (test_groups) { fprintf(fp, "\n"); for (const struct test_option_group *g = test_groups; g->name; g++) { fprintf(fp, "\n", g->allow_multiple_selection ? "true" : "false"); fprint_config_item(fp, g->name, NULL, NULL, g->description, NULL, NULL, POPULARITY_UNDEFINED); for (const struct test_option *o = g->options; o->name; o++) { fprintf(fp, " \n"); } fprintf(fp, "\n"); } fprintf(fp, "\n"); } fprintf(fp, "\n"); fclose(fp); return tmpdir; } static void test_remove_rules(char *basedir, const char *ruleset) { char path[PATH_MAX]; int rc; rc = snprintf_safe(path, sizeof(path), "%s/rules/%s.xml", basedir, ruleset); assert(rc); unlink(path); rc = snprintf_safe(path, sizeof(path), "%s/xkb/rules", basedir); assert(rc); rmdir(path); rmdir(basedir); free(basedir); } static struct rxkb_context * test_setup_context_for(const char *ruleset, struct test_model *system_models, struct test_model *user_models, struct test_layout *system_layouts, struct test_layout *user_layouts, struct test_option_group *system_groups, struct test_option_group *user_groups) { char *sysdir = NULL, *userdir = NULL; struct rxkb_context *ctx; sysdir = test_create_rules(ruleset, system_models, system_layouts, system_groups); if (user_models || user_layouts || user_groups) userdir = test_create_rules(ruleset, user_models, user_layouts, user_groups); ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES); assert(ctx); if (userdir) assert(rxkb_context_include_path_append(ctx, userdir)); assert(rxkb_context_include_path_append(ctx, sysdir)); assert(rxkb_context_parse(ctx, ruleset)); test_remove_rules(sysdir, ruleset); if (userdir) test_remove_rules(userdir, ruleset); return ctx; } static struct rxkb_context * test_setup_context(struct test_model *system_models, struct test_model *user_models, struct test_layout *system_layouts, struct test_layout *user_layouts, struct test_option_group *system_groups, struct test_option_group *user_groups) { const char *ruleset = "xkbtests"; return test_setup_context_for(ruleset, system_models, user_models, system_layouts, user_layouts, system_groups, user_groups); } static struct rxkb_model * fetch_model(struct rxkb_context *ctx, const char *model) { struct rxkb_model *m = rxkb_model_first(ctx); while (m) { if (streq(rxkb_model_get_name(m), model)) return rxkb_model_ref(m); m = rxkb_model_next(m); } return NULL; } static bool find_model(struct rxkb_context *ctx, const char *model) { struct rxkb_model *m = fetch_model(ctx, model); rxkb_model_unref(m); return m != NULL; } static bool find_models(struct rxkb_context *ctx, ...) { va_list args; const char *name; int idx = 0; bool rc = false; va_start(args, ctx); name = va_arg(args, const char *); while(name) { ++idx; assert(idx < 20); /* safety guard */ if (!find_model(ctx, name)) goto out; name = va_arg(args, const char *); }; rc = true; out: va_end(args); return rc; } static struct rxkb_layout * fetch_layout(struct rxkb_context *ctx, const char *layout, const char *variant) { struct rxkb_layout *l = rxkb_layout_first(ctx); while (l) { const char *v = rxkb_layout_get_variant(l); if (streq(rxkb_layout_get_name(l), layout) && ((v == NULL && variant == NULL) || (v != NULL && variant != NULL && streq(v, variant)))) return rxkb_layout_ref(l); l = rxkb_layout_next(l); } return NULL; } static bool find_layout(struct rxkb_context *ctx, const char *layout, const char *variant) { struct rxkb_layout *l = fetch_layout(ctx, layout, variant); rxkb_layout_unref(l); return l != NULL; } static bool find_layouts(struct rxkb_context *ctx, ...) { va_list args; const char *name, *variant; int idx = 0; bool rc = false; va_start(args, ctx); name = va_arg(args, const char *); variant = va_arg(args, const char *); while(name) { ++idx; assert(idx < 20); /* safety guard */ if (!find_layout(ctx, name, variant)) goto out; name = va_arg(args, const char *); if (name) variant = va_arg(args, const char *); }; rc = true; out: va_end(args); return rc; } static bool check_layouts_order(struct rxkb_context *ctx, ...) { va_list args; const char *layout, *variant; int idx = 0; bool rc = false; struct rxkb_layout *l = rxkb_layout_first(ctx); va_start(args, ctx); layout = va_arg(args, const char *); variant = va_arg(args, const char *); while(layout) { ++idx; assert(idx < 20); /* safety guard */ if (!l) { fprintf(stderr, "ERROR: expected layout #%d \"%s(%s)\", got none\n", idx, layout, variant ? variant : "-"); goto out; } const char *v = rxkb_layout_get_variant(l); if (!streq(rxkb_layout_get_name(l), layout) || !streq_null(v, variant)) { fprintf(stderr, "ERROR: expected layout #%d \"%s(%s)\", got \"%s(%s)\"\n", idx, layout, variant ? variant : "-", rxkb_layout_get_name(l), v ? v : "-"); goto out; } layout = va_arg(args, const char *); if (layout) variant = va_arg(args, const char *); l = rxkb_layout_next(l); }; if (l) { const char *v = rxkb_layout_get_variant(l); fprintf(stderr, "ERROR: unexpected layout at #%d: \"%s(%s)\"\n", idx + 1, rxkb_layout_get_name(l), v ? v : "-"); } rc = l == NULL; out: va_end(args); return rc; } static struct rxkb_option_group * fetch_option_group(struct rxkb_context *ctx, const char *grp) { struct rxkb_option_group *g = rxkb_option_group_first(ctx); while (g) { if (streq(grp, rxkb_option_group_get_name(g))) return rxkb_option_group_ref(g); g = rxkb_option_group_next(g); } return NULL; } static struct rxkb_option * fetch_option(struct rxkb_context *ctx, const char *grp, const char *opt) { struct rxkb_option_group *g = rxkb_option_group_first(ctx); while (g) { if (streq(grp, rxkb_option_group_get_name(g))) { struct rxkb_option *o = rxkb_option_first(g); while (o) { if (streq(opt, rxkb_option_get_name(o))) return rxkb_option_ref(o); o = rxkb_option_next(o); } } g = rxkb_option_group_next(g); } return NULL; } static bool find_option(struct rxkb_context *ctx, const char *grp, const char *opt) { struct rxkb_option *o = fetch_option(ctx, grp, opt); rxkb_option_unref(o); return o != NULL; } static bool find_options(struct rxkb_context *ctx, ...) { va_list args; const char *grp, *opt; int idx = 0; bool rc = false; va_start(args, ctx); grp = va_arg(args, const char *); opt = va_arg(args, const char *); while(grp) { ++idx; assert(idx < 20); /* safety guard */ if (!find_option(ctx, grp, opt)) goto out; grp = va_arg(args, const char *); if (grp) opt = va_arg(args, const char *); }; rc = true; out: va_end(args); return rc; } static bool cmp_models(struct test_model *tm, struct rxkb_model *m) { if (!tm || !m) return false; if (!streq(tm->name, rxkb_model_get_name(m))) return false; if (!streq_null(tm->vendor, rxkb_model_get_vendor(m))) return false; if (!streq_null(tm->description, rxkb_model_get_description(m))) return false; return true; } static bool cmp_layouts(struct test_layout *tl, struct rxkb_layout *l) { struct rxkb_iso3166_code *iso3166 = NULL; struct rxkb_iso639_code *iso639 = NULL; if (!tl || !l) return false; if (!streq(tl->name, rxkb_layout_get_name(l))) return false; if (!streq_null(tl->variant, rxkb_layout_get_variant(l))) return false; if (!streq_null(tl->brief, rxkb_layout_get_brief(l))) return false; if (!streq_null(tl->description, rxkb_layout_get_description(l))) return false; iso3166 = rxkb_layout_get_iso3166_first(l); for (size_t i = 0; i < ARRAY_SIZE(tl->iso3166); i++) { const char *iso = tl->iso3166[i]; if (iso == NULL && iso3166 == NULL) break; if (!streq_null(iso, rxkb_iso3166_code_get_code(iso3166))) return false; iso3166 = rxkb_iso3166_code_next(iso3166); } if (iso3166 != NULL) return false; iso639 = rxkb_layout_get_iso639_first(l); for (size_t i = 0; i < ARRAY_SIZE(tl->iso639); i++) { const char *iso = tl->iso639[i]; if (iso == NULL && iso639 == NULL) break; if (!streq_null(iso, rxkb_iso639_code_get_code(iso639))) return false; iso639 = rxkb_iso639_code_next(iso639); } if (iso639 != NULL) return false; return true; } static bool cmp_options(struct test_option *to, struct rxkb_option *o) { if (!to || !o) return false; if (!streq(to->name, rxkb_option_get_name(o))) return false; if (!streq_null(to->description, rxkb_option_get_description(o))) return false; return true; } enum cmp_type { CMP_EXACT, CMP_MATCHING_ONLY, }; static bool cmp_option_groups(struct test_option_group *tg, struct rxkb_option_group *g, enum cmp_type cmp) { struct rxkb_option *o; struct test_option *to; if (!tg || !g) return false; if (!streq(tg->name, rxkb_option_group_get_name(g))) return false; if (!streq_null(tg->description, rxkb_option_group_get_description(g))) return false; if (tg->allow_multiple_selection != rxkb_option_group_allows_multiple(g)) return false; to = tg->options; o = rxkb_option_first(g); while (o && to->name) { if (!cmp_options(to, o)) return false; to++; o = rxkb_option_next(o); } if (cmp == CMP_EXACT && (o || to->name)) return false; return true; } static void test_load_basic(void) { struct test_model system_models[] = { {"m1"}, {"m2"}, {NULL}, }; struct test_layout system_layouts[] = { {"l1"}, {"l1", "v1"}, {NULL}, }; struct test_option_group system_groups[] = { {"grp1", NULL, true, { {"grp1:1"}, {"grp1:2"} } }, {"grp2", NULL, false, { {"grp2:1"}, {"grp2:2"} } }, { NULL }, }; struct rxkb_context *ctx; ctx = test_setup_context(system_models, NULL, system_layouts, NULL, system_groups, NULL); assert(find_models(ctx, "m1", "m2", NULL)); assert(find_layouts(ctx, "l1", NO_VARIANT, "l1", "v1", NULL)); assert(find_options(ctx, "grp1", "grp1:1", "grp1", "grp1:2", "grp2", "grp2:1", "grp2", "grp2:2", NULL)); rxkb_context_unref(ctx); } static void test_load_full(void) { struct test_model system_models[] = { {"m1", "vendor1", "desc1"}, {"m2", "vendor2", "desc2"}, {NULL}, }; struct test_layout system_layouts[] = { {"l1", NO_VARIANT, "lbrief1", "ldesc1"}, {"l1", "v1", "vbrief1", "vdesc1"}, {"l1", "v2", NULL, "vdesc2"}, {NULL}, }; struct test_option_group system_groups[] = { {"grp1", "gdesc1", true, { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } }, {"grp2", "gdesc2", false, { {"grp2:1", "odesc21"}, {"grp2:2", "odesc22"} } }, { NULL }, }; struct rxkb_context *ctx; struct rxkb_model *m; struct rxkb_layout *l; struct rxkb_option_group *g; ctx = test_setup_context(system_models, NULL, system_layouts, NULL, system_groups, NULL); m = fetch_model(ctx, "m1"); assert(cmp_models(&system_models[0], m)); rxkb_model_unref(m); m = fetch_model(ctx, "m2"); assert(cmp_models(&system_models[1], m)); rxkb_model_unref(m); l = fetch_layout(ctx, "l1", NO_VARIANT); assert(cmp_layouts(&system_layouts[0], l)); rxkb_layout_unref(l); l = fetch_layout(ctx, "l1", "v1"); assert(cmp_layouts(&system_layouts[1], l)); rxkb_layout_unref(l); l = fetch_layout(ctx, "l1", "v2"); struct test_layout expected = {"l1", "v2", "lbrief1", "vdesc2"}; assert(cmp_layouts(&expected, l)); rxkb_layout_unref(l); g = fetch_option_group(ctx, "grp1"); assert(cmp_option_groups(&system_groups[0], g, CMP_EXACT)); rxkb_option_group_unref(g); g = fetch_option_group(ctx, "grp2"); assert(cmp_option_groups(&system_groups[1], g, CMP_EXACT)); rxkb_option_group_unref(g); rxkb_context_unref(ctx); } static void test_load_languages(void) { struct test_model system_models[] = { {"m1", "vendor1", "desc1"}, {NULL}, }; struct test_layout system_layouts[] = { {"l1", NO_VARIANT, "lbrief1", "ldesc1", .iso639 = { "abc", "def" }, .iso3166 = { "uv", "wx" }}, {"l1", "v1", "vbrief1", "vdesc1", .iso639 = {"efg"}, .iso3166 = {"yz"}}, {"l2", NO_VARIANT, "lbrief1", "ldesc1", .iso639 = { "hij", "klm" }, .iso3166 = { "op", "qr" }}, {"l2", "v2", "lbrief1", "ldesc1", .iso639 = { NULL }, /* inherit from parent */ .iso3166 = { NULL }}, /* inherit from parent */ {NULL}, }; struct test_option_group system_groups[] = { {"grp1", "gdesc1", true, { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } }, { NULL }, }; struct rxkb_context *ctx; struct rxkb_layout *l; struct rxkb_iso3166_code *iso3166; struct rxkb_iso639_code *iso639; ctx = test_setup_context(system_models, NULL, system_layouts, NULL, system_groups, NULL); l = fetch_layout(ctx, "l1", NO_VARIANT); assert(cmp_layouts(&system_layouts[0], l)); rxkb_layout_unref(l); l = fetch_layout(ctx, "l1", "v1"); assert(cmp_layouts(&system_layouts[1], l)); rxkb_layout_unref(l); l = fetch_layout(ctx, "l2", "v2"); iso3166 = rxkb_layout_get_iso3166_first(l); assert(streq(rxkb_iso3166_code_get_code(iso3166), "op")); iso3166 = rxkb_iso3166_code_next(iso3166); assert(streq(rxkb_iso3166_code_get_code(iso3166), "qr")); iso639 = rxkb_layout_get_iso639_first(l); assert(streq(rxkb_iso639_code_get_code(iso639), "hij")); iso639 = rxkb_iso639_code_next(iso639); assert(streq(rxkb_iso639_code_get_code(iso639), "klm")); rxkb_layout_unref(l); rxkb_context_unref(ctx); } static void test_load_invalid_languages(void) { struct test_model system_models[] = { {"m1", "vendor1", "desc1"}, {NULL}, }; struct test_layout system_layouts[] = { {"l1", NO_VARIANT, "lbrief1", "ldesc1", .iso639 = { "ab", "def" }, .iso3166 = { "uvw", "xz" }}, {NULL}, }; struct test_option_group system_groups[] = { {"grp1", "gdesc1", true, { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } }, { NULL }, }; struct rxkb_context *ctx; struct rxkb_layout *l; struct rxkb_iso3166_code *iso3166; struct rxkb_iso639_code *iso639; ctx = test_setup_context(system_models, NULL, system_layouts, NULL, system_groups, NULL); l = fetch_layout(ctx, "l1", NO_VARIANT); /* uvw is invalid, we expect 2 letters, verify it was ignored */ iso3166 = rxkb_layout_get_iso3166_first(l); assert(streq(rxkb_iso3166_code_get_code(iso3166), "xz")); assert(rxkb_iso3166_code_next(iso3166) == NULL); /* ab is invalid, we expect 3 letters, verify it was ignored */ iso639 = rxkb_layout_get_iso639_first(l); assert(streq(rxkb_iso639_code_get_code(iso639), "def")); assert(rxkb_iso639_code_next(iso639) == NULL); rxkb_layout_unref(l); rxkb_context_unref(ctx); } static void test_popularity(void) { assert(POPULARITY_UNDEFINED != POPULARITY_STANDARD); assert(POPULARITY_UNDEFINED != POPULARITY_EXOTIC); struct test_layout system_layouts[] = { {.name = "l1", .variant = NO_VARIANT }, /* Default popularity */ {.name = "l1", .variant = "v1" }, /* Default popularity */ {.name = "l2", .popularity = POPULARITY_STANDARD }, {.name = "l3", .popularity = POPULARITY_EXOTIC }, {NULL}, }; struct rxkb_context *ctx; struct rxkb_layout *l; struct ruleset_conf { const char *ruleset; enum rxkb_context_flags flags; enum rxkb_popularity popularity; /* Default popularity */ }; struct ruleset_conf rulesets[] = { { /* Rules with “standard” popularity */ .ruleset="xkbtests", .flags=RXKB_CONTEXT_NO_DEFAULT_INCLUDES, .popularity=RXKB_POPULARITY_STANDARD }, { /* Rules with “exotic” popularity (hack, see below) */ .ruleset="xkbtests.extras", .flags=RXKB_CONTEXT_NO_DEFAULT_INCLUDES | RXKB_CONTEXT_LOAD_EXOTIC_RULES, .popularity=RXKB_POPULARITY_EXOTIC } }; for (size_t k = 0; k < ARRAY_SIZE(rulesets); k++) { struct ruleset_conf *conf = &rulesets[k]; char *dir = NULL; dir = test_create_rules(conf->ruleset, NULL, system_layouts, NULL); ctx = rxkb_context_new(conf->flags); assert(ctx); assert(rxkb_context_include_path_append(ctx, dir)); /* Hack: ruleset "xkbtests.extras" above generates xkbtests.extras.xml, * loading "xkbtests" means the extras file counts as exotic */ assert(rxkb_context_parse(ctx, "xkbtests")); /* Test implicit popularity */ l = fetch_layout(ctx, "l1", NO_VARIANT); assert(rxkb_layout_get_popularity(l) == conf->popularity); rxkb_layout_unref(l); l = fetch_layout(ctx, "l1", "v1"); assert(rxkb_layout_get_popularity(l) == conf->popularity); rxkb_layout_unref(l); /* Test explicit popularity */ l = fetch_layout(ctx, "l2", NO_VARIANT); assert(rxkb_layout_get_popularity(l) == RXKB_POPULARITY_STANDARD); rxkb_layout_unref(l); l = fetch_layout(ctx, "l3", NO_VARIANT); assert(rxkb_layout_get_popularity(l) == RXKB_POPULARITY_EXOTIC); rxkb_layout_unref(l); test_remove_rules(dir, conf->ruleset); rxkb_context_unref(ctx); } } static void test_load_merge(void) { struct test_model system_models[] = { {"m1", "vendor1", "desc1"}, {"m2", "vendor2", "desc2"}, {NULL}, }; struct test_model user_models[] = { {"m3", "vendor3", "desc3"}, {"m4", "vendor4", "desc4"}, {NULL}, }; struct test_layout system_layouts[] = { {"l1", NO_VARIANT, "lbrief1", "ldesc1"}, {"l1", "v1", "vbrief1", "vdesc1"}, {NULL}, }; struct test_layout user_layouts[] = { {"l2", NO_VARIANT, "lbrief2", "ldesc2"}, {"l2", "v2", "vbrief2", "vdesc2"}, // Duplicate with system {"l1", NO_VARIANT, "lbrief1bis", "ldesc1bis"}, {"l1", "v1", "vbrief1bis", "vdesc1bis"}, {NULL}, }; struct test_option_group system_groups[] = { {"grp1", NULL, true, { {"grp1:1"}, {"grp1:2"} } }, {"grp2", NULL, false, { {"grp2:1"}, {"grp2:2"} } }, { NULL }, }; struct test_option_group user_groups[] = { {"grp3", NULL, true, { {"grp3:1"}, {"grp3:2"} } }, {"grp4", NULL, false, { {"grp4:1"}, {"grp4:2"} } }, { NULL }, }; struct rxkb_context *ctx; struct rxkb_model *m; struct rxkb_layout *l; struct rxkb_option_group *g; ctx = test_setup_context(system_models, user_models, system_layouts, user_layouts, system_groups, user_groups); assert(find_models(ctx, "m1", "m2", "m3", "m4", NULL)); assert(find_layouts(ctx, "l1", NO_VARIANT, "l1", "v1", "l2", NO_VARIANT, "l2", "v2", NULL)); m = fetch_model(ctx, "m1"); assert(cmp_models(&system_models[0], m)); rxkb_model_unref(m); m = fetch_model(ctx, "m2"); assert(cmp_models(&system_models[1], m)); rxkb_model_unref(m); m = fetch_model(ctx, "m3"); assert(cmp_models(&user_models[0], m)); rxkb_model_unref(m); m = fetch_model(ctx, "m4"); assert(cmp_models(&user_models[1], m)); rxkb_model_unref(m); l = fetch_layout(ctx, "l1", NO_VARIANT); assert(cmp_layouts(&system_layouts[0], l)); rxkb_layout_unref(l); l = fetch_layout(ctx, "l1", "v1"); assert(cmp_layouts(&system_layouts[1], l)); rxkb_layout_unref(l); l = fetch_layout(ctx, "l2", NO_VARIANT); assert(cmp_layouts(&user_layouts[0], l)); rxkb_layout_unref(l); l = fetch_layout(ctx, "l2", "v2"); assert(cmp_layouts(&user_layouts[1], l)); rxkb_layout_unref(l); /* Check that the duplicate layouts are skipped */ assert(check_layouts_order(ctx, "l1", NO_VARIANT, "l1", "v1", "l2", NO_VARIANT, "l2", "v2", NULL)); g = fetch_option_group(ctx, "grp1"); assert(cmp_option_groups(&system_groups[0], g, CMP_EXACT)); rxkb_option_group_unref(g); g = fetch_option_group(ctx, "grp2"); assert(cmp_option_groups(&system_groups[1], g, CMP_EXACT)); rxkb_option_group_unref(g); g = fetch_option_group(ctx, "grp3"); assert(cmp_option_groups(&user_groups[0], g, CMP_EXACT)); rxkb_option_group_unref(g); g = fetch_option_group(ctx, "grp4"); assert(cmp_option_groups(&user_groups[1], g, CMP_EXACT)); rxkb_option_group_unref(g); rxkb_context_unref(ctx); } static void test_load_merge_no_overwrite(void) { struct test_model system_models[] = { {"m1", "vendor1", "desc1"}, {"m2", "vendor2", "desc2"}, {NULL}, }; struct test_model user_models[] = { {"m1", "vendor3", "desc3"}, /* must not overwrite */ {"m4", "vendor4", "desc4"}, {NULL}, }; struct test_layout system_layouts[] = { {"l1", NO_VARIANT, "lbrief1", "ldesc1"}, {"l1", "v1", "vbrief1", "vdesc1"}, {NULL}, }; struct test_layout user_layouts[] = { {"l2", NO_VARIANT, "lbrief2", "ldesc2"}, {"l2", "v2", "vbrief2", "vdesc2"}, {"l1", NO_VARIANT, "lbrief3", "ldesc3"}, /* must not overwrite */ {"l1", "v2", "vbrief3", "vdesc3"}, /* must not overwrite */ {NULL}, }; struct test_option_group system_groups[] = { {"grp1", "gdesc1", true, { {"grp1:1", "odesc11"}, {"grp1:2", "odesc12"} } }, {"grp2", "gdesc2", false, { {"grp2:1", "odesc21"}, {"grp2:2", "odesc22"} } }, { NULL }, }; struct test_option_group user_groups[] = { {"grp1", "XXXXX", false, /* must not overwrite */ { {"grp1:1", "YYYYYYY"}, /* must not overwrite */ {"grp1:3", "ZZZZZZ"} } }, /* append */ {"grp4", "gdesc4", false, { {"grp4:1", "odesc41"}, {"grp4:2", "odesc42"} } }, { NULL }, }; struct rxkb_context *ctx; struct rxkb_model *m; struct rxkb_layout *l; struct rxkb_option_group *g; ctx = test_setup_context(system_models, user_models, system_layouts, user_layouts, system_groups, user_groups); m = fetch_model(ctx, "m1"); assert(cmp_models(&system_models[0], m)); rxkb_model_unref(m); l = fetch_layout(ctx, "l1", NO_VARIANT); assert(cmp_layouts(&system_layouts[0], l)); rxkb_layout_unref(l); l = fetch_layout(ctx, "l1", "v1"); assert(cmp_layouts(&system_layouts[1], l)); rxkb_layout_unref(l); assert(find_option(ctx, "grp1", "grp1:3")); g = fetch_option_group(ctx, "grp1"); assert(cmp_option_groups(&system_groups[0], g, CMP_MATCHING_ONLY)); rxkb_option_group_unref(g); rxkb_context_unref(ctx); } static void test_no_include_paths(void) { struct rxkb_context *ctx; ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES); assert(ctx); assert(!rxkb_context_parse_default_ruleset(ctx)); rxkb_context_unref(ctx); } static void test_invalid_include(void) { struct rxkb_context *ctx; ctx = rxkb_context_new(RXKB_CONTEXT_NO_DEFAULT_INCLUDES); assert(ctx); assert(!rxkb_context_include_path_append(ctx, "/foo/bar/baz/bat")); assert(!rxkb_context_parse_default_ruleset(ctx)); rxkb_context_unref(ctx); } /* Check that libxml2 error handler is reset after parsing */ static void test_xml_error_handler(void) { struct test_model system_models[] = { {NULL} }; struct test_layout system_layouts[] = { {NULL} }; struct test_option_group system_groups[] = { { NULL } }; struct rxkb_context *ctx; ctx = test_setup_context(system_models, NULL, system_layouts, NULL, system_groups, NULL); assert(ctx); rxkb_context_unref(ctx); const char invalid_xml[] = " * Copyright © 2019 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #include "config.h" #include "test-config.h" #include "xkbcommon/xkbcommon.h" #include "test.h" #include "utils.h" #include "xkbcomp/rules.h" struct test_data { /* Rules file */ const char *rules; /* Input */ const char *model; const char *layout; const char *variant; const char *options; /* Expected output */ const char *keycodes; const char *types; const char *compat; const char *symbols; const char *geometry; /* Or set this if xkb_components_from_rules() should fail. */ bool should_fail; }; static bool test_rules(struct xkb_context *ctx, struct test_data *data) { fprintf(stderr, "\n\nChecking : %s\t%s\t%s\t%s\t%s\n", data->rules, data->model, data->layout, data->variant, data->options); if (data->should_fail) fprintf(stderr, "Expecting: FAILURE\n"); else fprintf(stderr, "Expecting: %s\t%s\t%s\t%s\n", data->keycodes, data->types, data->compat, data->symbols); const struct xkb_rule_names rmlvo = { data->rules, data->model, data->layout, data->variant, data->options }; struct xkb_component_names kccgst; if (xkb_components_names_from_rules(ctx, &rmlvo, NULL, &kccgst)) { fprintf(stderr, "Received : %s\t%s\t%s\t%s\n", kccgst.keycodes, kccgst.types, kccgst.compatibility, kccgst.symbols); } else { fprintf(stderr, "Received : FAILURE\n"); return data->should_fail; } const bool passed = streq_not_null(kccgst.keycodes, data->keycodes) && streq_not_null(kccgst.types, data->types) && streq_not_null(kccgst.compatibility, data->compat) && streq_not_null(kccgst.symbols, data->symbols) && streq_null(kccgst.geometry, data->geometry); free(kccgst.keycodes); free(kccgst.types); free(kccgst.compatibility); free(kccgst.symbols); free(kccgst.geometry); return passed; } int main(int argc, char *argv[]) { struct xkb_context *ctx; test_init(); setenv("XKB_CONFIG_ROOT", TEST_XKB_CONFIG_ROOT, 1); ctx = test_get_context(0); assert(ctx); struct test_data test1 = { .rules = "inc-src-simple", .model = "my_model", .layout = "my_layout", .variant = "", .options = "", .keycodes = "my_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "my_symbols", }; assert(test_rules(ctx, &test1)); struct test_data test2 = { .rules = "inc-src-nested", .model = "my_model", .layout = "my_layout", .variant = "", .options = "", .keycodes = "my_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "my_symbols", }; assert(test_rules(ctx, &test2)); struct test_data test3 = { .rules = "inc-src-looped", .model = "my_model", .layout = "my_layout", .variant = "", .options = "", .should_fail = true, }; assert(test_rules(ctx, &test3)); struct test_data test4 = { .rules = "inc-src-before-after", .model = "before_model", .layout = "my_layout", .variant = "", .options = "", .keycodes = "my_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "default_symbols", }; assert(test_rules(ctx, &test4)); struct test_data test5 = { .rules = "inc-src-options", .model = "my_model", .layout = "my_layout", .variant = "my_variant", .options = "option11,my_option,colon:opt,option111", .keycodes = "my_keycodes", .types = "default_types", .compat = "default_compat+substring+group(bla)|some:compat", .symbols = "my_symbols+extra_variant+altwin(menu)", }; assert(test_rules(ctx, &test5)); struct test_data test6 = { .rules = "inc-src-loop-twice", .model = "my_model", .layout = "my_layout", .variant = "", .options = "", .keycodes = "my_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "my_symbols", }; assert(test_rules(ctx, &test6)); struct test_data test7 = { .rules = "inc-no-newline", .should_fail = true, }; assert(test_rules(ctx, &test7)); struct test_data test8 = { .rules = "inc-src-relative-path", .model = "my_model", .layout = "my_layout", .variant = "", .options = "", .keycodes = "my_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "my_symbols", }; assert(test_rules(ctx, &test8)); xkb_context_unref(ctx); return 0; } xkbcommon-libxkbcommon-54ee7ac/test/rules-file.c000066400000000000000000000754121510033435100220660ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "xkbcommon/xkbcommon.h" #include "context.h" #include "keymap.h" #include "utils.h" #include "xkbcomp/rules.h" #include "test.h" struct test_data { /* Rules file */ const char *rules; /* Input */ const char *model; const char *layout; const char *variant; const char *options; /* Expected output */ const char *keycodes; const char *types; const char *compat; const char *symbols; const char *geometry; xkb_layout_index_t explicit_layouts; /* Or set this if xkb_components_from_rules() should fail. */ bool should_fail; }; static bool test_rules(struct xkb_context *ctx, const struct test_data *data) { fprintf(stderr, "\n\nChecking : %s\t%s\t%s\t%s\t%s\n", data->rules, data->model, data->layout, data->variant, data->options); if (data->should_fail) fprintf(stderr, "Expecting: FAILURE\n"); else fprintf(stderr, "Expecting: %s\t%s\t%s\t%s\t%s\t%u\n", data->keycodes, data->types, data->compat, data->symbols, data->geometry, data->explicit_layouts); bool passed = true; xkb_layout_index_t explicit_layouts = 0; for (int k = 0; k < 2; k++) { bool ok; const struct xkb_rule_names rmlvo = { data->rules, data->model, data->layout, data->variant, data->options }; struct xkb_component_names kccgst; if (k == 0) { /* Private API */ ok = xkb_components_from_rules_names(ctx, &rmlvo, &kccgst, &explicit_layouts); } else { /* Public API */ ok = xkb_components_names_from_rules(ctx, &rmlvo, NULL, &kccgst); } if (ok) { fprintf(stderr, "Received : %s\t%s\t%s\t%s\t%s\t%u\n", kccgst.keycodes, kccgst.types, kccgst.compatibility, kccgst.symbols, kccgst.geometry, explicit_layouts); } else { fprintf(stderr, "Received : FAILURE\n"); return data->should_fail; } passed &= streq_not_null(kccgst.keycodes, data->keycodes) && streq_not_null(kccgst.types, data->types) && streq_not_null(kccgst.compatibility, data->compat) && streq_not_null(kccgst.symbols, data->symbols) && streq_null(kccgst.geometry, data->geometry) && explicit_layouts == data->explicit_layouts; free(kccgst.keycodes); free(kccgst.types); free(kccgst.compatibility); free(kccgst.symbols); free(kccgst.geometry); } return passed; } static void test_encodings(struct xkb_context *ctx) { static const struct test_data tests[] = { { .rules = "utf-8_with_bom", .model = "my_model", .layout = "my_layout", .variant = "my_variant", .options = "my_option", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat|some:compat", .symbols = "my_symbols+extra_variant", .explicit_layouts = 1, }, { .rules = "utf-16le_with_bom", .model = "my_model", .layout = "my_layout", .variant = "my_variant", .options = "my_option", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat|some:compat", .symbols = "my_symbols+extra_variant", .explicit_layouts = 1, .should_fail = true, }, { .rules = "utf-16be_with_bom", .model = "my_model", .layout = "my_layout", .variant = "my_variant", .options = "my_option", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat|some:compat", .symbols = "my_symbols+extra_variant", .explicit_layouts = 1, .should_fail = true, }, { .rules = "utf-32be", .model = "my_model", .layout = "my_layout", .variant = "my_variant", .options = "my_option", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat|some:compat", .symbols = "my_symbols+extra_variant", .explicit_layouts = 1, .should_fail = true, } }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_rules(ctx, &tests[k])); } } /* Only parse strict decimal groups */ static void test_strict_decimal_groups(struct xkb_context *ctx) { static const struct test_data tests[] = { { .rules = "invalid-group-index", .model = "my_model", .layout = "1,2", .variant = NULL, .options = NULL, .keycodes = "default_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "default_symbols+default_symbols:2", .explicit_layouts = 2, .should_fail = true, }, { .rules = "invalid-group-qualifier", .model = "my_model", .layout = "1,2", .variant = NULL, .options = NULL, .keycodes = "default_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "default_symbols+default_symbols:+2", .explicit_layouts = 1, } }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_rules(ctx, &tests[k])); } } static void test_simple(struct xkb_context *ctx) { static const struct test_data tests[] = { { .rules = "simple", .model = "my_model", .layout = "my_layout", .variant = "my_variant", .options = "my_option", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat|some:compat", .symbols = "my_symbols+extra_variant", .explicit_layouts = 1, }, { .rules = "simple", .model = "", .layout = "foo", .variant = "", .options = "", .keycodes = "default_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "default_symbols", .explicit_layouts = 1, }, { .rules = "groups", .model = "pc104", .layout = "foo", .variant = "", .options = "", .keycodes = "something(pc104)", .types = "default_types", .compat = "default_compat", .symbols = "default_symbols", .explicit_layouts = 1, }, { .rules = "groups", .model = "foo", .layout = "ar", .variant = "bar", .options = "", .keycodes = "default_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "my_symbols+(bar)", .explicit_layouts = 1, }, { .rules = "simple", .model = NULL, .layout = "my_layout,second_layout", .variant = "my_variant", .options = "my_option", .should_fail = true }, { .rules = "index", .model = "", .layout = "br,al,cn,az", .variant = "", .options = "some:opt", .keycodes = "default_keycodes", .types = "default_types", .compat = "default_compat", .symbols = "default_symbols+extra:1+extra:2+extra:3+extra:4", .explicit_layouts = 4, }, { .rules = "multiple-options", .model = "my_model", .layout = "my_layout", .variant = "my_variant", .options = "option3,option1,colon:opt,option11", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat+some:compat+group(bla)", .symbols = "my_symbols+extra_variant+compose(foo)+keypad(bar)+altwin(menu)", .explicit_layouts = 1, }, /* “replace” merge mode */ { .rules = "merge-mode-replace", .model = "my_model", .layout = "us,de", .variant = "", .options = "replace:first", .keycodes = "evdev", .types = "complete", .compat = "complete", .symbols = "pc+us+de:2^level3(ralt_alt)|empty", .explicit_layouts = 2, } }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_rules(ctx, &tests[k])); } } static void test_wild_card(struct xkb_context *ctx) { /* Wild card does not match empty entries for layouts and variants */ #define ENTRY(_model, _layout, _variant, _options, _symbols, _layouts, _fail) \ { .rules = "wildcard", .model = (_model), \ .layout = (_layout), .variant = (_variant), .options = (_options), \ .keycodes = "evdev", .types = "complete", .compat = "complete", \ .symbols = (_symbols) , .geometry = "pc(pc104)", \ .explicit_layouts = (_layouts), .should_fail = (_fail) } static const struct test_data tests[] = { /* OK: empty model and options and at least one layout+variant combo */ ENTRY(NULL, "a" , "1" , NULL, "pc+a(1)", 1, false), ENTRY("" , "a" , "1" , "" , "pc+a(1)", 1, false), ENTRY("" , "a," , "1," , "" , "pc+a(1)", 1, false), ENTRY("" , ",b" , ",2" , "" , "+b(2):2", 2, false), ENTRY("" , "a,b", "1," , "" , "pc+a(1)", 1, false), ENTRY("" , "a,b", ",2" , "" , "+b(2):2", 2, false), /* Fails: empty layout or variant */ ENTRY(NULL, NULL , NULL , NULL, "", 1, true), ENTRY(NULL, "" , "" , NULL, "", 1, true), ENTRY(NULL, NULL , "1" , NULL, "", 1, true), ENTRY(NULL, "" , "1" , NULL, "", 1, true), ENTRY(NULL, "," , "1,2", NULL, "", 2, true), ENTRY(NULL, "a" , NULL , NULL, "", 1, true), ENTRY(NULL, "a" , "" , NULL, "", 1, true), ENTRY(NULL, "a,b", NULL , NULL, "", 2, true), ENTRY(NULL, "a,b", "" , NULL, "", 2, true), ENTRY(NULL, "a,b", "," , NULL, "", 2, true) }; #undef ENTRY for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_rules(ctx, &tests[k])); } } /* Test extended wild cards: , and */ static void test_extended_wilcards(struct xkb_context *ctx) { #define ENTRY(_rules, _layout, _variant, _symbols, _layouts, _fail) \ { .rules = (_rules), .model = NULL, \ .layout = (_layout), .variant = (_variant), .options = NULL, \ .keycodes = "evdev", .types = "complete", .compat = "complete", \ .symbols = (_symbols) , .explicit_layouts = (_layouts), \ .should_fail = (_fail) } static const struct test_data tests[] = { ENTRY("extended-wild-cards", "l1", NULL, "pc+l10:1", 1, false), ENTRY("extended-wild-cards", "l1", "v1", "pc+l20:1", 1, false), ENTRY("extended-wild-cards", "l1", "v2", "pc+l30(v2):1", 1, false), /* legacy wild card * does not catch empty variant */ ENTRY("extended-wild-cards", "l2", NULL, "pc+l2:1", 1, false), ENTRY("extended-wild-cards", "l2", "v1", "pc+l40(v1):1", 1, false), ENTRY("extended-wild-cards", "l2", "v2", "pc+l40(v2):1", 1, false), ENTRY("extended-wild-cards", "l3", NULL, "pc+l50:1", 1, false), ENTRY("extended-wild-cards", "l3", "v1", "pc+l50(v1):1", 1, false), ENTRY("extended-wild-cards", "l3", "v2", "pc+l50(v2):1", 1, false), /* ? wild card does catch empty variant */ ENTRY("extended-wild-cards", "l4", NULL, "pc+l4:1", 1, false), ENTRY("extended-wild-cards", "l4", "v1", "pc+l4(v1):1", 1, false), ENTRY("extended-wild-cards", "l4", "v2", "pc+l4(v20):1", 1, false), ENTRY("extended-wild-cards", "l1,l1,l1,l2", ",v1,v2,", "pc+l10:1+l20:2+l30(v2):3+l2:4", 4, false), ENTRY("extended-wild-cards", "l2,l2,l3,l3", "v1,v2,,v1", "pc+l40(v1):1+l40(v2):2+l50:3+l50(v1):4", 4, false), ENTRY("extended-wild-cards", "l3,l4,l4,l4", "v2,,v1,v2", "pc+l50(v2):1+l4:2+l4(v1):3+l4(v20):4", 4, false), }; #undef ENTRY for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_rules(ctx, &tests[k])); } } static void test_layout_index_ranges(struct xkb_context *ctx, const char *too_much_layouts, const char *too_much_symbols) { #define ENTRY2(_rules, _model, _layout, _variant, _options, \ _keycodes, _types, _compat, _symbols, _count, _should_fail) \ { .rules = (_rules), .model = (_model), \ .layout = (_layout), .variant = (_variant), .options = (_options), \ .keycodes = (_keycodes), .types = (_types), .compat = (_compat), \ .symbols = (_symbols), \ .geometry = (strncmp((_rules), "evdev", 5) == 0) ? "pc(pc104)" : NULL,\ .explicit_layouts = (_count), .should_fail = (_should_fail) } #define ENTRY(layout, variant, options, symbols, count, should_fail) \ ENTRY2("special_indices", NULL, layout, variant, options, \ "default_keycodes", "default_types", "default_compat", symbols, \ count, should_fail) const struct test_data tests[] = { /* Test index ranges: layout vs layout[first] */ ENTRY("layout_a", NULL, NULL, "A", 1, false), ENTRY("layout_e", NULL, NULL, "E+layout_e", 1, false), ENTRY("a", NULL, NULL, "a", 1, false), ENTRY("a", "1", NULL, "a(1)", 1, false), /* Test index ranges: invalid layout qualifier */ ENTRY("layout_c", NULL, NULL, "C:1+z:1", 1, false), /* Test index ranges: invalid layout[first] qualifier */ ENTRY("layout_d", NULL, NULL, "D", 1, false), /* Test index ranges: multiple layouts */ ENTRY("a,b", NULL, NULL, "a+b:2", 2, false), ENTRY("a,b", ",c", NULL, "a+b(c):2", 2, false), ENTRY("layout_e,layout_a", NULL, NULL, "e:1+x:2", 2, false), ENTRY("layout_a,layout_b,layout_c,layout_d", NULL, NULL, "a:1+y:2+layout_c:3+layout_d:4+z:3", 4, false), ENTRY("layout_a,layout_b,layout_c,layout_d", "extra,,,extra", NULL, "a:1+y:2+layout_c:3+layout_d(extra):4+z:3" "+foo:1|bar:1+foo:4|bar:4", 4, false), ENTRY("layout_a,layout_b,layout_c,layout_d,layout_e", NULL, NULL, "a:1+y:2+layout_c:3+layout_d:4+layout_e:5+z:3", 5, false), /* Check that special indices merge the KcCGST values in the expected order */ ENTRY("layout_a,layout_b,layout_c", NULL, "option_3,option_2,option_1", "a:1+y:2+layout_c:3+z:3+III:2+JJJ:2+HHH:3+KKK:3+LLL+OOO:2+MMM:3+NNN:3", 3, false), #undef ENTRY /* Test index ranges: too much layouts */ ENTRY2("special_indices-limit", NULL, too_much_layouts, NULL, NULL, "default_keycodes", "default_types", "default_compat", too_much_symbols, XKB_MAX_GROUPS, false), #define ENTRY(model, layout, variant, options, compat, symbols, count, should_fail) \ ENTRY2("evdev-modern", model, layout, variant, options, \ "evdev+aliases(qwerty)", "complete", compat, symbols, count, should_fail) /* evdev-modern: 1 layout */ ENTRY("whatever", "ar", NULL, NULL, "complete", "pc+ara+inet(evdev)", 1, false), ENTRY("whatever", "ben", "probhat", NULL, "complete", "pc+in(ben_probhat)+inet(evdev)", 1, false), ENTRY("ataritt", "es", NULL, NULL, "complete", "xfree68_vndr/ataritt(us)+es+inet(evdev)", 1, false), ENTRY("ataritt", "jp", NULL, NULL, "complete+japan", "xfree68_vndr/ataritt(us)+jp+inet(evdev)", 1, false), ENTRY2("evdev-modern", "olpc", "us", NULL, NULL, "evdev+olpc(olpc)+aliases(qwerty)", "complete", "olpc", "olpc+us(olpc)+inet(evdev)", 1, false), ENTRY2("evdev-modern", "olpc", "jp", NULL, NULL, "evdev+olpc(olpc)+aliases(qwerty)", "complete", "complete+japan", "olpc+jp+inet(evdev)", 1, false), ENTRY("pc104", "jp", NULL, NULL, "complete+japan", "pc+jp+inet(evdev)", 1, false), ENTRY("pc104", "jp", "xxx", NULL, "complete+japan", "pc+jp(xxx)+inet(evdev)", 1, false), ENTRY("pc104", "es", NULL, NULL, "complete", "pc+es+inet(evdev)", 1, false), ENTRY("pc104", "es", "xxx", NULL, "complete", "pc+es(xxx)+inet(evdev)", 1, false), ENTRY2("evdev-modern", "pc104", "de", "neo", NULL, "evdev+aliases(qwertz)", "complete", "complete+caps(caps_lock):1+misc(assign_shift_left_action):1+level5(level5_lock):1", "pc+de(neo)+inet(evdev)", 1, false), ENTRY("pc104", "br", NULL, "misc:typo,misc:apl", "complete", "pc+br+inet(evdev)+apl(level3):1+typo(base):1", 1, false), /* evdev-modern: 2 layouts */ ENTRY("whatever", "ar,pt", NULL, NULL, "complete", "pc+ara+pt:2+inet(evdev)", 2, false), ENTRY("whatever", "pt,ar", NULL, NULL, "complete", "pc+pt+ara:2+inet(evdev)", 2, false), ENTRY("whatever", "ben,gb", "probhat,", NULL, "complete", "pc+in(ben_probhat)+gb:2+inet(evdev)", 2, false), ENTRY("whatever", "gb,ben", ",probhat", NULL, "complete", "pc+gb+in(ben):2+in(ben_probhat):2+inet(evdev)", 2, false), ENTRY("whatever", "ben,ar", "probhat,", NULL, "complete", "pc+in(ben_probhat)+ara:2+inet(evdev)", 2, false), ENTRY("ataritt", "jp,es", NULL, NULL, "complete", "pc+jp+es:2+inet(evdev)", 2, false), ENTRY("ataritt", "es,jp", NULL, NULL, "complete", "pc+es+jp:2+inet(evdev)", 2, false), ENTRY2("evdev-modern", "olpc", "jp,es", NULL, NULL, "evdev+olpc(olpc)+aliases(qwerty)", "complete", "complete", "pc+jp+es:2+inet(evdev)", 2, false), ENTRY2("evdev-modern", "olpc", "es,jp", NULL, NULL, "evdev+olpc(olpc)+aliases(qwerty)", "complete", "complete", "pc+es+jp:2+inet(evdev)", 2, false), ENTRY("pc104", "jp,es", NULL, NULL, "complete", "pc+jp+es:2+inet(evdev)", 2, false), ENTRY("pc104", "jp,es", "xxx,yyy", NULL, "complete", "pc+jp(xxx)+es(yyy):2+inet(evdev)", 2, false), ENTRY("pc104", "latin,jp", NULL, NULL, "complete", "pc+latin+jp:2+inet(evdev)", 2, false), ENTRY("pc104", "latin,jp", "xxx,yyy", NULL, "complete", "pc+latin(xxx)+jp(yyy):2+inet(evdev)", 2, false), ENTRY2("evdev-modern", "pc104", "gb,de", ",neo", NULL, "evdev+aliases(qwerty)", "complete", "complete+caps(caps_lock):2+misc(assign_shift_left_action):2+level5(level5_lock):2", "pc+gb+de(neo):2+inet(evdev)", 2, false), ENTRY("pc104", "ca,br", NULL, "misc:typo,misc:apl", "complete", "pc+ca+br:2+inet(evdev)+apl(level3):1+apl(level3):2+typo(base):1+typo(base):2", 2, false), }; #undef ENTRY for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_rules(ctx, &tests[k])); } } static void test_extended_layout_indices(struct xkb_context *ctx) { char layouts[(2 + MAX_LAYOUT_INDEX_STR_LENGTH) * XKB_MAX_GROUPS] = { 0 }; size_t count = 0; for (xkb_layout_index_t l = 0; l < XKB_MAX_GROUPS; l++) { count += snprintf(&layouts[count], sizeof(layouts) - count, "x%"PRIu32",", l + 1); } layouts[--count] = '\0'; static const char symbols_prefix[] = "pc+x1+"; static const char symbols_suffix[] = "+inet(evdev)"; char symbols[ (3 + 2 * MAX_LAYOUT_INDEX_STR_LENGTH) * XKB_MAX_GROUPS + sizeof(symbols_prefix) + sizeof(symbols_suffix) ] = { 0 }; memcpy(symbols, symbols_prefix, sizeof(symbols_prefix)); count = sizeof(symbols_prefix) - 1; for (xkb_layout_index_t l = 1; l < XKB_MAX_GROUPS; l++) { count += snprintf(&symbols[count], sizeof(symbols) - count, "x%"PRIu32":%"PRIu32"+", l + 1, l + 1); } memcpy(symbols + count - 1, symbols_suffix, sizeof(symbols_suffix)); const struct test_data test = { .rules = "evdev-modern", .model = "pc104", .layout = layouts, .variant = "", .options = "", .keycodes = "evdev+aliases(qwerty)", .compat = "complete", .types = "complete", .symbols = symbols, .geometry = "pc(pc104)", .explicit_layouts = XKB_MAX_GROUPS }; assert(test_rules(ctx, &test)); } static void test_all_qualifier(struct xkb_context *ctx, const char *too_much_layouts, const char *too_much_symbols) { const struct test_data tests[] = { /* Test :all qualifier without special indices, with option */ { .rules = "all_qualifier", .model = "my_model", .layout = "layout_a,layout_b,layout_a,layout_b,layout_c", .variant = "", .options = "my_option", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat", .symbols = "symbols_a:1+symbols_b:2+symbols_a:3+symbols_b:4+symbols_c:5" "+extra_option:1+extra_option:2+extra_option:3+extra_option:4" "+extra_option:5", .explicit_layouts = 5, }, /* Test :all qualifier without special indices, base for all layout */ { .rules = "all_qualifier", .model = "my_model", .layout = "layout_x,layout_a,layout_b,layout_c,layout_d", .variant = "", .options = "", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat", .symbols = "base:1+base:2+base:3+base:4+base:5" "+symbols_a:2+symbols_b:3+default_symbols:4+default_symbols:5", .explicit_layouts = 5, }, /* Test :all qualifier without special indices, with option, too much layouts */ { .rules = "all_qualifier-limit", .model = "my_model", .layout = too_much_layouts, .variant = "", .options = "", .keycodes = "default_keycodes", .types = "default_types", .compat = "default_compat", .symbols = too_much_symbols, .explicit_layouts = XKB_MAX_GROUPS, }, /* Test :all qualifier with special indices */ { .rules = "all_qualifier", .model = "my_model", .layout = "layout_a,layout_b,layout_a,layout_b,layout_c", .variant = "extra1,,,,", .options = "my_option", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat", .symbols = "symbols_a:1+symbols_b:2+symbols_a:3+symbols_b:4+symbols_c:5" "+extra_symbols:1+extra_symbols:2+extra_symbols:3+extra_symbols:4+extra_symbols:5" "+extra_option:1+extra_option:2+extra_option:3+extra_option:4+extra_option:5", .explicit_layouts = 5, }, /* Test :all qualifier with special indices * It uses :all combined with layout[any], which is valid but * :%i was probably the intended qualified, so raises warning */ { .rules = "all_qualifier", .model = "my_model", .layout = "layout_a,layout_b,layout_a,layout_b,layout_c", .variant = "extra2,,extra3,,", .options = "my_option", .keycodes = "my_keycodes", .types = "my_types", .compat = "my_compat", .symbols = "symbols_a:1+symbols_b:2+symbols_a:3+symbols_b:4+symbols_c:5" "+extra_symbols1:1+extra_symbols2:1+extra_symbols2:2+extra_symbols2:3+extra_symbols2:4+extra_symbols2:5" "+extra_symbols2:1+extra_symbols2:2+extra_symbols2:3+extra_symbols2:4+extra_symbols2:5" "+extra_symbols1:3" "+extra_option:1" "+extra_option:2+extra_option:3+extra_option:4+extra_option:5", .explicit_layouts = 5, } }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_rules(ctx, &tests[k])); } } static void test_layout_specific_options(struct xkb_context *ctx) { const struct test_data tests[] = { /* * 1 layout, no layout index */ { .rules = "layout-specific-options", .model = "pc104", .layout = "l1", .variant = NULL, .options = "opt1,opt2,opt3,opt4,opt5,opt6,opt7", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1+s1:1+s3:1+s7", .explicit_layouts = 1 }, { .rules = "layout-specific-options", .model = "pc104", .layout = "l2", .variant = NULL, .options = "opt1,opt2,opt3,opt4,opt5,opt6,opt7", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l2:1+s1:1+s2:1+s3:1+s4:1+s7", .explicit_layouts = 1 }, /* * 1 layout, invalid layout index */ { .rules = "layout-specific-options", .model = "pc104", .layout = "l1", .variant = NULL, .options = "opt1!,opt2!1x,opt3!x,opt4!x1,opt5!!,opt6!+,opt7!|", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1+s1:1+s3:1+s7", .explicit_layouts = 1 }, /* * 1 layout, matching layout index */ { .rules = "layout-specific-options", .model = "pc104", .layout = "l1", .variant = NULL, .options = "opt1!1,opt2!1,opt3!1,opt4!1,opt5!1,opt6!1,opt7!1", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1+s1:1+s3:1", .explicit_layouts = 1 }, { .rules = "layout-specific-options", .model = "pc104", .layout = "l2", .variant = NULL, .options = "opt1!1,opt2!1,opt3!1,opt4!1,opt5!1,opt6!1,opt7!1", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l2:1+s1:1+s2:1+s3:1+s4:1", .explicit_layouts = 1 }, /* * 1 layout, non-matching layout index */ { .rules = "layout-specific-options", .model = "pc104", .layout = "l1", .variant = NULL, .options = "opt1!2,opt2!2,opt3!2,opt4!2,opt5!2,opt6!2,opt7!2", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1", .explicit_layouts = 1 }, { .rules = "layout-specific-options", .model = "pc104", .layout = "l2", .variant = NULL, .options = "opt1!2,opt2!2,opt3!2,opt4!2,opt5!2,opt6!2,opt7!2", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l2:1", .explicit_layouts = 1 }, /* * 2 layouts: no specifier */ { .rules = "layout-specific-options", .model = "pc104", .layout = "l1,l2", .variant = NULL, .options = "opt1,opt2,opt3,opt4,opt5,opt6,opt7", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1+l2:2+s1:1+s3:1+s3:2+s4:2+s5:1+s6:2+s7", .explicit_layouts = 2 }, /* 2 layout: non-matching index */ { .rules = "layout-specific-options", .model = "pc104", .layout = "l1,l2", .variant = NULL, .options = "opt1!3,opt2!3,opt3!3,opt4!3,opt5!3,opt6!3,opt7!3", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1+l2:2", .explicit_layouts = 2 }, /* * 2 layouts: specify only 1 layout for each option */ { .rules = "layout-specific-options", .model = "pc104", .layout = "l1,l2", .variant = NULL, .options = "opt1!1,opt2!1,opt3!1,opt4!1,opt5!1,opt6!1,opt7!1", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1+l2:2+s1:1+s3:1+s5:1", .explicit_layouts = 2 }, { .rules = "layout-specific-options", .model = "pc104", .layout = "l1,l2", .variant = NULL, .options = "opt1!2,opt2!2,opt3!2,opt4!2,opt5!2,opt6!2,opt7!2", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1+l2:2+s3:2+s4:2+s6:2", .explicit_layouts = 2 }, /* * 2 layouts: specify 2 layouts for each option */ { .rules = "layout-specific-options", .model = "pc104", .layout = "l1,l2", .variant = NULL, .options = "opt1!1,opt1!2,opt2!1,opt2!2,opt3!1,opt3!2," "opt4!1,opt4!2,opt5!1,opt5!2,opt6!1,opt6!2,opt7!1,opt7!2", .keycodes = "evdev", .compat = "complete", .types = "complete", .symbols = "pc+l1:1+l2:2+s1:1+s3:1+s3:2+s4:2+s5:1+s6:2", .explicit_layouts = 2 }, }; for (unsigned int k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_rules(ctx, &tests[k])); } } int main(int argc, char *argv[]) { struct xkb_context *ctx; test_init(); ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); test_encodings(ctx); test_strict_decimal_groups(ctx); test_simple(ctx); test_wild_card(ctx); test_extended_wilcards(ctx); /* Prepare data with too much layouts */ char too_much_layouts[(2 + MAX_LAYOUT_INDEX_STR_LENGTH) * (XKB_MAX_GROUPS + 1)] = { 0 }; char too_much_symbols[(3 + MAX_LAYOUT_INDEX_STR_LENGTH) * XKB_MAX_GROUPS] = { 0 }; size_t i = 0; for (xkb_layout_index_t l = 0; l <= XKB_MAX_GROUPS; l++) { i += snprintf(&too_much_layouts[i], sizeof(too_much_layouts) - i, "x%"PRIu32",", l + 1); } too_much_layouts[--i] = '\0'; i = 0; for (xkb_layout_index_t l = 0; l < XKB_MAX_GROUPS; l++) { i += snprintf(&too_much_symbols[i], sizeof(too_much_symbols) - i, "x:%"PRIu32"+", l + 1); } too_much_symbols[--i] = '\0'; test_layout_index_ranges(ctx, too_much_layouts, too_much_symbols); test_extended_layout_indices(ctx); test_all_qualifier(ctx, too_much_layouts, too_much_symbols); test_layout_specific_options(ctx); xkb_context_unref(ctx); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/rulescomp.c000066400000000000000000000325051510033435100220240ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "xkbcommon/xkbcommon.h" #include "evdev-scancodes.h" #include "src/keymap.h" #include "src/keysym.h" #include "test.h" #include "utils.h" /* xkb_rule_names API */ static int test_rmlvo_va(struct xkb_context *context, enum xkb_keymap_format format, const char *rules, const char *model, const char *layout, const char *variant, const char *options, va_list ap) { struct xkb_keymap * const keymap = test_compile_rules(context, format, rules, model, layout, variant, options); if (!keymap) return 0; fprintf(stderr, "Compiled '%s' '%s' '%s' '%s' '%s'\n", strnull(rules), strnull(model), strnull(layout), strnull(variant), strnull(options)); const int ret = test_key_seq_va(keymap, ap); xkb_keymap_unref(keymap); return ret; } /* xkb_rmlvo_builder API */ static int test_rmlvo_builder_va(struct xkb_context *context, enum xkb_keymap_format format, const char *rules, const char *model, const char *layout, const char *variant, const char *options, va_list ap) { struct xkb_keymap * const keymap = test_compile_rmlvo(context, format, rules, model, layout, variant, options); if (!keymap) return 0; fprintf(stderr, "Compiled '%s' '%s' '%s' '%s' '%s'\n", strnull(rules), strnull(model), strnull(layout), strnull(variant), strnull(options)); const int ret = test_key_seq_va(keymap, ap); xkb_keymap_unref(keymap); return ret; } static int test_rmlvo(struct xkb_context *context, enum xkb_keymap_format format, const char *rules, const char *model, const char *layout, const char *variant, const char *options, ...) { va_list ap; int ret; va_start(ap, options); ret = test_rmlvo_va(context, format, rules, model, layout, variant, options, ap); va_end(ap); va_start(ap, options); ret &= test_rmlvo_builder_va(context, format, rules, model, layout, variant, options, ap); va_end(ap); return ret; } static int test_rmlvo_env(struct xkb_context *ctx, enum xkb_keymap_format format, const char *rules, const char *model, const char *layout, const char *variant, const char *options, ...) { va_list ap; int ret; va_start (ap, options); if (!isempty(rules)) setenv("XKB_DEFAULT_RULES", rules, 1); else unsetenv("XKB_DEFAULT_RULES"); if (!isempty(model)) setenv("XKB_DEFAULT_MODEL", model, 1); else unsetenv("XKB_DEFAULT_MODEL"); if (!isempty(layout)) setenv("XKB_DEFAULT_LAYOUT", layout, 1); else unsetenv("XKB_DEFAULT_LAYOUT"); if (!isempty(variant)) setenv("XKB_DEFAULT_VARIANT", variant, 1); else unsetenv("XKB_DEFAULT_VARIANT"); if (!isempty(options)) setenv("XKB_DEFAULT_OPTIONS", options, 1); else unsetenv("XKB_DEFAULT_OPTIONS"); ret = test_rmlvo_va(ctx, format, NULL, NULL, NULL, NULL, NULL, ap); va_end(ap); return ret; } /* Test more than 4 groups */ static void test_extended_groups(struct xkb_context *ctx) { struct { enum xkb_keymap_format format; xkb_layout_index_t num_layouts; const char *layouts; } tests[] = { /* v1: 4 groups */ { .format = XKB_KEYMAP_FORMAT_TEXT_V1, .layouts = "cz,us,ca,de", .num_layouts = XKB_MAX_GROUPS_X11 }, /* v1: 5 groups, discard 1 group */ { .format = XKB_KEYMAP_FORMAT_TEXT_V1, .layouts = "cz,us,ca,de,in", .num_layouts = XKB_MAX_GROUPS_X11 }, /* v2: 5 groups */ { .format = XKB_KEYMAP_FORMAT_TEXT_V2, .layouts = "cz,us,ca,de,in", .num_layouts = XKB_MAX_GROUPS_X11 + 1 }, /* v2: 32 groups */ { .format = XKB_KEYMAP_FORMAT_TEXT_V2, .layouts = "cz,us,ca,de,in,cz,us,ca,de,in,cz,us,ca,de,in," "cz,us,ca,de,in,cz,us,ca,de,in,cz,us,ca,de,in," "cz,us", .num_layouts = XKB_MAX_GROUPS }, /* v2: 33 groups, discard 1 group */ { .format = XKB_KEYMAP_FORMAT_TEXT_V2, .layouts = "cz,us,ca,de,in,cz,us,ca,de,in,cz,us,ca,de,in," "cz,us,ca,de,in,cz,us,ca,de,in,cz,us,ca,de,in," "cz,us,ca", .num_layouts = XKB_MAX_GROUPS }, }; for (size_t k = 0; k < ARRAY_SIZE(tests); k++) { fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, k); struct xkb_keymap *keymap = test_compile_rules(ctx, tests[k].format, "evdev-modern", "pc105", tests[k].layouts, NULL, NULL); assert(keymap); assert(xkb_keymap_num_layouts(keymap) == tests[k].num_layouts); xkb_keymap_unref(keymap); } #define U(cp) (XKB_KEYSYM_UNICODE_OFFSET + (cp)) assert(test_rmlvo_env(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev-modern", "", "cz,us,ca,de,in,ru,il", ",,,,,phonetic,", "grp:menu_toggle", KEY_2, BOTH, XKB_KEY_ecaron, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_Y, BOTH, XKB_KEY_y, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_102ND, BOTH, XKB_KEY_guillemetleft, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_Y, BOTH, XKB_KEY_z, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_Y, BOTH, U(0x092c), NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_Y, BOTH, XKB_KEY_Cyrillic_ze, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_Y, BOTH, XKB_KEY_hebrew_tet, FINISH)); #undef U } int main(int argc, char *argv[]) { test_init(); struct xkb_context *ctx = test_get_context(CONTEXT_ALLOW_ENVIRONMENT_NAMES); assert(ctx); #define KS(name) xkb_keysym_from_name(name, 0) assert(test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc105", "us,il,ru,ca", ",,,multix", "grp:alts_toggle,ctrl:nocaps,compose:rwin", KEY_Q, BOTH, XKB_KEY_q, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, KEY_Q, BOTH, XKB_KEY_slash, NEXT, KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, KEY_Q, BOTH, XKB_KEY_Q, NEXT, KEY_RIGHTMETA, BOTH, XKB_KEY_Multi_key, FINISH)); assert(test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc105", "us,in", "", "grp:alts_toggle", KEY_A, BOTH, XKB_KEY_a, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, KEY_A, BOTH, KS("U094b"), FINISH)); assert(test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc105", "us", "intl", "", KEY_GRAVE, BOTH, XKB_KEY_dead_grave, FINISH)); assert(test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "pc105", "us", "intl", "grp:alts_toggle", KEY_GRAVE, BOTH, XKB_KEY_dead_grave, FINISH)); /* 33 is not a legal group; make sure this is handled gracefully. */ #define EXCESSIVE_GROUPS 33 static_assert(EXCESSIVE_GROUPS > XKB_MAX_GROUPS, "Test upgrade required"); assert(test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, "evdev", "", "us:" STRINGIFY(EXCESSIVE_GROUPS), "", "", KEY_A, BOTH, XKB_KEY_a, FINISH)); #undef EXCESSIVE_GROUPS /* Don't choke on missing values in RMLVO. Should just skip them. Currently generates us,us,ca. */ assert(test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "", "us,,ca", "", "grp:alts_toggle", KEY_A, BOTH, XKB_KEY_a, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Next_Group, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, KEY_APOSTROPHE, BOTH, XKB_KEY_dead_grave, FINISH)); assert(test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "", "", "", "", "", KEY_A, BOTH, XKB_KEY_a, FINISH)); assert(!test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "does-not-exist", "", "", "", "", KEY_A, BOTH, XKB_KEY_a, FINISH)); assert(test_rmlvo_env(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "", "us", "", "", KEY_A, BOTH, XKB_KEY_a, FINISH)); assert(test_rmlvo_env(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "", "us", "", "ctrl:nocaps", KEY_CAPSLOCK, BOTH, XKB_KEY_Control_L, FINISH)); /* Ignores multix and generates us,ca. */ assert(test_rmlvo_env(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "", "us,ca", ",,,multix", "grp:alts_toggle", KEY_A, BOTH, XKB_KEY_a, NEXT, KEY_LEFTALT, DOWN, XKB_KEY_Alt_L, NEXT, KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Next_Group, NEXT, KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, NEXT, KEY_LEFTALT, UP, XKB_KEY_Alt_L, NEXT, KEY_GRAVE, UP, XKB_KEY_numbersign, FINISH)); assert(!test_rmlvo_env(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "broken", "what-on-earth", "invalid", "", "", KEY_A, BOTH, XKB_KEY_a, FINISH)); /* Ensure a keymap with an empty xkb_keycodes compiles fine. */ assert(test_rmlvo_env(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "base", "empty", "empty", "", "", KEY_A, BOTH, XKB_KEY_NoSymbol, FINISH)); /* Check replace merge mode: it should replace the whole key */ const char* replace_options[] = { "replace:single,grp:menu_toggle", "replace:first,grp:menu_toggle", "replace:later,grp:menu_toggle", }; for (unsigned int k = 0; k < ARRAY_SIZE(replace_options); k++) { const char* const options = replace_options[k]; assert(test_rmlvo(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "merge-mode-replace", "", "us,de", "", options, KEY_RIGHTALT, BOTH, XKB_KEY_Alt_R, NEXT, KEY_COMPOSE, BOTH, XKB_KEY_ISO_Next_Group, NEXT, KEY_RIGHTALT, BOTH, XKB_KEY_Alt_R, FINISH)); } /* Has an illegal escape sequence, but shouldn't fail. */ assert(test_rmlvo_env(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", "", "cz", "bksl", "", KEY_A, BOTH, XKB_KEY_a, FINISH)); test_extended_groups(ctx); xkb_context_unref(ctx); ctx = test_get_context(0); assert(test_rmlvo_env(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, "broken", "but", "ignored", "per", "ctx flags", KEY_A, BOTH, XKB_KEY_a, FINISH)); /* Test response to invalid flags. */ { struct xkb_rule_names rmlvo = { NULL }; assert(!xkb_keymap_new_from_names2(ctx, &rmlvo, XKB_KEYMAP_FORMAT_TEXT_V1, -1)); assert(!xkb_keymap_new_from_names2(ctx, &rmlvo, XKB_KEYMAP_FORMAT_TEXT_V1, 5453)); } xkb_context_unref(ctx); return 0; } xkbcommon-libxkbcommon-54ee7ac/test/state.c000066400000000000000000004303111510033435100211300ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #include "config.h" #include #include #include #include #include "context.h" #include "evdev-scancodes.h" #include "src/keysym.h" #include "src/keymap.h" #include "test.h" #include "utils.h" #include "xkbcommon/xkbcommon-keysyms.h" #include "xkbcommon/xkbcommon.h" static const enum xkb_keymap_format keymap_formats[] = { XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_FORMAT_TEXT_V2 }; /* Offset between evdev keycodes (where KEY_ESCAPE is 1), and the evdev XKB * keycode set (where ESC is 9). */ #define EVDEV_OFFSET 8 /* S sharp * • U+00DF ß: lower case * • SS: upper case (special mapping, not handled by us) * • U+1E9E ẞ: upper case, only for capitals */ #ifndef XKB_KEY_Ssharp #define XKB_KEY_Ssharp (XKB_KEYSYM_UNICODE_OFFSET + 0x1E9E) #endif /* Reference implementation from XkbAdjustGroup in Xorg xserver */ static int32_t group_wrap_ref(int32_t g, int32_t num_groups) { assert(num_groups >= 0); if (num_groups == 0) { return 0; } else if (g < 0) { while (g < 0) g += num_groups; } else if (g >= num_groups) { g %= num_groups; } return g; } /* Function extracted from XkbWrapGroupIntoRange (current) */ static int32_t group_wrap(int32_t g, int32_t num_groups) { assert(num_groups >= 0); if (num_groups == 0) return 0; if (g >= 0 && g < num_groups) return g; const int32_t remainder = g % num_groups; return (remainder < 0) ? num_groups + remainder : remainder; } /* Old bogus implementation */ static int32_t group_wrap_old(int32_t g, int32_t num_groups) { assert(num_groups >= 0); if (num_groups == 0) return 0; if (g >= 0 && g < num_groups) return g; /* Invalid modulus arithmetic (see comment in XkbWrapGroupIntoRange) */ const int32_t remainder = g % num_groups; return (g < 0) ? num_groups + remainder : remainder; } static bool is_valid_group(int32_t g, int32_t num_groups) { assert(num_groups >= 0); return (num_groups > 0 && g >= 0 && g < num_groups); } static void test_group_wrap(struct xkb_context *ctx) { /* Compare wrap function with reference implementation */ for (int32_t G = 0; G <= XKB_MAX_GROUPS; G++) { for (int32_t g = - 3 * (G + 1); g <= 3 * (G + 1); g++) { /* Same as xserver */ assert(group_wrap(g, G) == group_wrap_ref(g, G)); /* Old implementation */ const int32_t old = group_wrap_old(g, G); const int32_t new = group_wrap(g, G); assert((old == new) ^ (G > 0 && g < 0 && ((-g) % G == 0))); } } /* Check some special cases */ assert(group_wrap(-2, 0) == 0); assert(group_wrap(-1, 0) == 0); assert(group_wrap(0, 0) == 0); assert(group_wrap(1, 0) == 0); assert(group_wrap(2, 0) == 0); assert(group_wrap(-2, 1) == 0); assert(group_wrap(-1, 1) == 0); assert(group_wrap(0, 1) == 0); assert(group_wrap(1, 1) == 0); assert(group_wrap(2, 1) == 0); assert(group_wrap(-6, 2) == 0); assert(group_wrap(-5, 2) == 1); assert(group_wrap(-4, 2) == 0); assert(group_wrap(-3, 2) == 1); assert(group_wrap(-2, 2) == 0); assert(group_wrap(-1, 2) == 1); assert(group_wrap(0, 2) == 0); assert(group_wrap(1, 2) == 1); assert(group_wrap(2, 2) == 0); assert(group_wrap(3, 2) == 1); assert(group_wrap(4, 2) == 0); assert(group_wrap(5, 2) == 1); assert(group_wrap(6, 2) == 0); assert(group_wrap(-7, 3) == 2); assert(group_wrap(-6, 3) == 0); assert(group_wrap(-5, 3) == 1); assert(group_wrap(-4, 3) == 2); assert(group_wrap(-3, 3) == 0); assert(group_wrap(-2, 3) == 1); assert(group_wrap(-1, 3) == 2); assert(group_wrap(0, 3) == 0); assert(group_wrap(1, 3) == 1); assert(group_wrap(2, 3) == 2); assert(group_wrap(3, 3) == 0); assert(group_wrap(4, 3) == 1); assert(group_wrap(5, 3) == 2); assert(group_wrap(6, 3) == 0); assert(group_wrap(7, 3) == 1); assert(group_wrap(-9, 4) == 3); assert(group_wrap(-8, 4) == 0); assert(group_wrap(-7, 4) == 1); assert(group_wrap(-6, 4) == 2); assert(group_wrap(-5, 4) == 3); assert(group_wrap(-4, 4) == 0); assert(group_wrap(-3, 4) == 1); assert(group_wrap(-2, 4) == 2); assert(group_wrap(-1, 4) == 3); assert(group_wrap(0, 4) == 0); assert(group_wrap(1, 4) == 1); assert(group_wrap(2, 4) == 2); assert(group_wrap(3, 4) == 3); assert(group_wrap(4, 4) == 0); assert(group_wrap(5, 4) == 1); assert(group_wrap(6, 4) == 2); assert(group_wrap(7, 4) == 3); assert(group_wrap(8, 4) == 0); assert(group_wrap(9, 4) == 1); assert(group_wrap(-11, 5) == 4); assert(group_wrap(-10, 5) == 0); assert(group_wrap(-9, 5) == 1); assert(group_wrap(-8, 5) == 2); assert(group_wrap(-7, 5) == 3); assert(group_wrap(-6, 5) == 4); assert(group_wrap(-5, 5) == 0); assert(group_wrap(-4, 5) == 1); assert(group_wrap(-3, 5) == 2); assert(group_wrap(-2, 5) == 3); assert(group_wrap(-1, 5) == 4); assert(group_wrap(0, 5) == 0); assert(group_wrap(1, 5) == 1); assert(group_wrap(2, 5) == 2); assert(group_wrap(3, 5) == 3); assert(group_wrap(4, 5) == 4); assert(group_wrap(5, 5) == 0); assert(group_wrap(6, 5) == 1); assert(group_wrap(7, 5) == 2); assert(group_wrap(8, 5) == 3); assert(group_wrap(9, 5) == 4); assert(group_wrap(10, 5) == 0); assert(group_wrap(11, 5) == 1); /* Check state group computation */ const struct { const char* keymap; xkb_layout_index_t layout_count; } keymaps[] = { { .keymap = "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n" "};", .layout_count = 0 }, { .keymap = "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n" " xkb_symbols {\n" " key <> { [a] };\n" " };\n" "};", .layout_count = 1 }, { .keymap = "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n" " xkb_symbols {\n" " key <> { [a], [b] };\n" " };\n" "};", .layout_count = 2 }, { .keymap = /* 3 groups */ "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n" " xkb_symbols {\n" " key <> { [a], [b], [c] };\n" " };\n" "};", .layout_count = 3 }, { .keymap = /* 4 groups */ "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n" " xkb_symbols {\n" " key <> { [a], [b], [c], [d] };\n" " };\n" "};", .layout_count = 4 }, { .keymap = "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n" " xkb_symbols {\n" " key <> { [a], [b], [c], [d], [e] };\n" " };\n" "};", .layout_count = 5 }, { .keymap = "default xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_types { type \"ONE_LEVEL\" { map[none] = 1; }; };\n" " xkb_symbols {\n" " key <> {\n" " [a], [b], [c], [d], [e], [f], [g], [h], [i], [j],\n" " [k], [l], [m], [n], [o], [p], [q], [r], [s], [t],\n" " [u], [v], [w], [x], [y], [z], [1], [2], [3], [4],\n" " [5], [6]\n" " };\n" " };\n" "};", .layout_count = XKB_MAX_GROUPS } }; static_assert(ARRAY_SIZE(keymaps) > XKB_MAX_GROUPS_X11, "Not enough maps"); for (int32_t k = 0; k < (int32_t)ARRAY_SIZE(keymaps); k++) { for (unsigned int f = (keymaps[k].layout_count < XKB_MAX_GROUPS_X11) ? 0 : 1; f < ARRAY_SIZE(keymap_formats); f++) { const enum xkb_keymap_format format = keymap_formats[f]; const int32_t g = (int32_t) keymaps[k].layout_count; fprintf(stderr, "------\n*** %s: #%"PRId32" groups, format %d ***\n", __func__, g, format); struct xkb_keymap *keymap = test_compile_buffer(ctx, format, keymaps[k].keymap, strlen(keymaps[k].keymap)); assert(keymap); assert(xkb_keymap_num_layouts(keymap) == keymaps[k].layout_count); struct xkb_state *state = xkb_state_new(keymap); assert(state); const xkb_keycode_t keycode = xkb_keymap_key_by_name(keymap, ""); assert(keycode == 1); for (int32_t base = -2*(g + 1); base <= 2*(g + 1); base++) { for (int32_t latched = -2*(g + 1); latched <= 2*(g + 1); latched++) { for (int32_t locked = -2*(g + 1); locked <= 2*(g + 2); locked++) { xkb_state_update_mask(state, 0, 0, 0, base, latched, locked); xkb_layout_index_t got; xkb_layout_index_t expected; /* Base layout should be unchanged */ got = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED); expected = (xkb_layout_index_t) base; assert_printf(got == expected, "Base layout: expected %"PRIu32", " "got: %"PRIu32"\n", expected, got); /* Latched layout should be unchanged */ got = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED); expected = (xkb_layout_index_t) latched; assert_printf(got == expected, "Latched layout: expected %"PRIu32", " "got: %"PRIu32"\n", expected, got); /* Locked layout should be wrapped */ got = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED); const xkb_layout_index_t locked_expected = group_wrap(locked, g); expected = locked_expected; assert_printf(got == expected, "Locked layout: expected %"PRIu32", " "got: %"PRIu32"\n", expected, got); /* Effective layout should be wrapped */ got = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); const xkb_layout_index_t effective_expected = group_wrap(base + latched + (int32_t) locked_expected, g); expected = effective_expected; assert_printf(got == expected, "Effective layout: expected %"PRIu32", " "got: %"PRIu32"\n", expected, got); /* * Ensure all API using a layout index do not segfault */ xkb_keymap_layout_get_name(keymap, base); const xkb_level_index_t num_levels = xkb_keymap_num_levels_for_key(keymap, keycode, base); const xkb_level_index_t num_levels_expected = (g > 0); assert_printf(num_levels == num_levels_expected, "Group=%"PRId32"/%"PRId32": " "Expected %"PRIu32", got: %"PRIu32"\n", base + 1, g, num_levels_expected, num_levels); xkb_mod_mask_t masks[1] = {0}; const size_t size = xkb_keymap_key_get_mods_for_level(keymap, keycode, base, 0, masks, ARRAY_SIZE(masks)); const size_t size_expected = (g > 0); assert(size == size_expected && masks[0] == 0); const xkb_keysym_t *keysyms = NULL; const int num_keysyms = xkb_keymap_key_get_syms_by_level(keymap, keycode, base, 0, &keysyms); const int num_keysyms_expected = (g > 0); assert(num_keysyms == num_keysyms_expected && (g == 0 || keysyms[0] != XKB_KEY_NoSymbol)); const xkb_level_index_t level = xkb_state_key_get_level(state, keycode, base); const xkb_level_index_t level_expected = is_valid_group(base, g) ? 0 : XKB_LEVEL_INVALID; assert_printf(level == level_expected, "Group=%"PRId32"/%"PRId32": " "Expected %"PRIu32", got: %"PRIu32"\n", base + 1, g, level_expected, level); int is_active, is_active_expected; is_active = xkb_state_layout_index_is_active( state, base, XKB_STATE_LAYOUT_DEPRESSED ); is_active_expected = is_valid_group(base, g) ? 1 : -1; assert(is_active == is_active_expected); is_active = xkb_state_layout_index_is_active( state, latched, XKB_STATE_LAYOUT_LATCHED ); is_active_expected = is_valid_group(latched, g) ? 1 : -1; assert(is_active == is_active_expected); is_active = xkb_state_layout_index_is_active( state, locked, XKB_STATE_LAYOUT_LOCKED ); is_active_expected = is_valid_group(locked, g) ? 1 : -1; assert(is_active == is_active_expected); is_active = xkb_state_layout_index_is_active( state, locked_expected, XKB_STATE_LAYOUT_LOCKED ); assert( is_valid_group((int32_t) locked_expected, g) == (g > 0) ); is_active_expected = is_valid_group((int32_t) locked_expected, g) ? 1 : -1; assert(is_active == is_active_expected); is_active = xkb_state_layout_index_is_active( state, effective_expected, XKB_STATE_LAYOUT_EFFECTIVE ); assert( is_valid_group((int32_t) effective_expected, g) == (g > 0) ); is_active_expected = is_valid_group((int32_t) effective_expected, g) ? 1 : -1; assert(is_active == is_active_expected); } } } xkb_state_unref(state); xkb_keymap_unref(keymap); }} } static inline xkb_mod_index_t _xkb_keymap_mod_get_index(struct xkb_keymap *keymap, const char *name) { xkb_mod_index_t mod = xkb_keymap_mod_get_index(keymap, name); assert(mod != XKB_MOD_INVALID); return mod; } static inline xkb_led_index_t _xkb_keymap_led_get_index(struct xkb_keymap *keymap, const char *name) { xkb_led_index_t led = xkb_keymap_led_get_index(keymap, name); assert(led != XKB_LED_INVALID); return led; } static void print_modifiers_serialization(struct xkb_state *state) { xkb_mod_mask_t base = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); xkb_mod_mask_t latched = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED); xkb_mod_mask_t locked = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED); xkb_mod_mask_t effective = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); fprintf(stderr, "\tMods: Base: 0x%x, Latched: 0x%x, Locked: 0x%x, Effective: 0x%x\n", base, latched, locked, effective); } static void print_layout_serialization(struct xkb_state *state) { xkb_mod_mask_t base = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_DEPRESSED); xkb_mod_mask_t latched = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED); xkb_mod_mask_t locked = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED); xkb_mod_mask_t effective = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); fprintf(stderr, "\tLayout: Base: 0x%x, Latched: 0x%x, Locked: 0x%x, Effective: 0x%x\n", base, latched, locked, effective); } static void print_state(struct xkb_state *state) { struct xkb_keymap *keymap; xkb_layout_index_t group; xkb_mod_index_t mod; xkb_led_index_t led; group = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE); mod = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); /* led = xkb_state_serialize_leds(state, XKB_STATE_LEDS); */ if (!group && !mod /* && !led */) { fprintf(stderr, "\tno state\n"); return; } keymap = xkb_state_get_keymap(state); for (group = 0; group < xkb_keymap_num_layouts(keymap); group++) { if (xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_LOCKED) <= 0) continue; fprintf(stderr, "\tgroup %s (%d): %s%s%s%s\n", xkb_keymap_layout_get_name(keymap, group), group, xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_EFFECTIVE) > 0 ? "effective " : "", xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_DEPRESSED) > 0 ? "depressed " : "", xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_LATCHED) > 0 ? "latched " : "", xkb_state_layout_index_is_active(state, group, XKB_STATE_LAYOUT_LOCKED) > 0 ? "locked " : ""); } for (mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { if (xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_EFFECTIVE | XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED) <= 0) continue; fprintf(stderr, "\tmod %s (%d): %s%s%s%s\n", xkb_keymap_mod_get_name(keymap, mod), mod, xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_EFFECTIVE) > 0 ? "effective " : "", xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_DEPRESSED) > 0 ? "depressed " : "", xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_LATCHED) > 0 ? "latched " : "", xkb_state_mod_index_is_active(state, mod, XKB_STATE_MODS_LOCKED) > 0 ? "locked " : ""); } for (led = 0; led < xkb_keymap_num_leds(keymap); led++) { if (xkb_state_led_index_is_active(state, led) <= 0) continue; fprintf(stderr, "\tled %s (%d): active\n", xkb_keymap_led_get_name(keymap, led), led); } } static inline bool check_serialize_layout(enum xkb_state_component components, struct xkb_state *expected, struct xkb_state *got) { return xkb_state_serialize_layout(expected, components) == xkb_state_serialize_layout(got, components); } static inline bool check_serialize_mods(enum xkb_state_component components, struct xkb_state *expected, struct xkb_state *got) { return xkb_state_serialize_mods(expected, components) == xkb_state_serialize_mods(got, components); } static bool check_state(struct xkb_state *expected, struct xkb_state *got) { bool ok = check_serialize_layout(XKB_STATE_LAYOUT_DEPRESSED, expected, got) && check_serialize_layout(XKB_STATE_LAYOUT_LATCHED, expected, got) && check_serialize_layout(XKB_STATE_LAYOUT_LOCKED, expected, got) && check_serialize_layout(XKB_STATE_LAYOUT_EFFECTIVE, expected, got) && check_serialize_mods(XKB_STATE_MODS_DEPRESSED, expected, got) && check_serialize_mods(XKB_STATE_MODS_LATCHED, expected, got) && check_serialize_mods(XKB_STATE_MODS_LOCKED, expected, got) && check_serialize_mods(XKB_STATE_MODS_EFFECTIVE, expected, got); struct xkb_keymap *keymap = xkb_state_get_keymap(expected); for (xkb_led_index_t led = 0; led < xkb_keymap_num_leds(keymap); led++) { if (xkb_state_led_index_is_active(expected, led) != xkb_state_led_index_is_active(got, led)) { ok = false; break; } } if (!ok) { fprintf(stderr, "Expected state:\n"); print_state(expected); print_layout_serialization(expected); print_modifiers_serialization(expected); fprintf(stderr, "Got state:\n"); print_state(got); print_layout_serialization(got); print_modifiers_serialization(got); } return ok; } /* Utils for checking modifier state */ typedef bool (* is_active_t)(int); static inline bool is_active(int x) { return x > 0; } static inline bool is_not_active(int x) { return x == 0; } static void test_update_key(struct xkb_keymap *keymap, bool pure_vmods) { struct xkb_state *state = xkb_state_new(keymap); const xkb_keysym_t *syms; xkb_keysym_t one_sym; int num_syms; is_active_t check_active = pure_vmods ? is_not_active : is_active; assert(state); xkb_mod_index_t ctrl = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); xkb_mod_index_t mod1 = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1); xkb_mod_index_t alt = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT); xkb_mod_index_t meta = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META); /* LCtrl down */ xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); fprintf(stderr, "dumping state for LCtrl down:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED) > 0); /* LCtrl + RAlt down */ xkb_state_update_key(state, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_DOWN); fprintf(stderr, "dumping state for LCtrl + RAlt down:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_DEPRESSED) > 0); assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_ALT, XKB_STATE_MODS_DEPRESSED) > 0); assert(check_active(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_MOD1, XKB_STATE_MODS_DEPRESSED))); assert(check_active(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_META, XKB_STATE_MODS_DEPRESSED))); if (pure_vmods) { assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, XKB_MOD_NAME_CTRL, XKB_VMOD_NAME_ALT, NULL) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, ctrl, alt, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, XKB_MOD_NAME_MOD1, XKB_VMOD_NAME_META, NULL) == 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, mod1, meta, XKB_MOD_INVALID) == 0); } else { assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_MOD1, XKB_VMOD_NAME_ALT, XKB_VMOD_NAME_META, NULL) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, ctrl, mod1, alt, meta, XKB_MOD_INVALID) > 0); } assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, XKB_MOD_NAME_MOD1, NULL) == 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, XKB_VMOD_NAME_ALT, NULL) == 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL, XKB_VMOD_NAME_META, NULL) == 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE, XKB_VMOD_NAME_ALT, NULL) > 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, (XKB_STATE_MATCH_ANY | XKB_STATE_MATCH_NON_EXCLUSIVE), XKB_VMOD_NAME_ALT, NULL) > 0); assert(check_active(xkb_state_mod_names_are_active( state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE, XKB_MOD_NAME_MOD1, NULL))); assert(check_active(xkb_state_mod_names_are_active( state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE, XKB_VMOD_NAME_META, NULL))); assert(check_active(xkb_state_mod_names_are_active( state, XKB_STATE_MODS_DEPRESSED, (XKB_STATE_MATCH_ANY | XKB_STATE_MATCH_NON_EXCLUSIVE), XKB_MOD_NAME_MOD1, NULL))); assert(check_active(xkb_state_mod_names_are_active( state, XKB_STATE_MODS_DEPRESSED, (XKB_STATE_MATCH_ANY | XKB_STATE_MATCH_NON_EXCLUSIVE), XKB_VMOD_NAME_META, NULL))); /* RAlt down */ xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_UP); fprintf(stderr, "dumping state for RAlt down:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_ALT, XKB_STATE_MODS_DEPRESSED) > 0); assert(check_active(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_MOD1, XKB_STATE_MODS_DEPRESSED))); assert(check_active(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_META, XKB_STATE_MODS_DEPRESSED))); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_DEPRESSED, XKB_STATE_MATCH_ANY, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_MOD1, XKB_VMOD_NAME_ALT, XKB_VMOD_NAME_META, NULL) > 0); assert(xkb_state_mod_names_are_active(state, XKB_STATE_MODS_LATCHED, XKB_STATE_MATCH_ANY, XKB_MOD_NAME_CTRL, XKB_MOD_NAME_MOD1, XKB_VMOD_NAME_ALT, XKB_VMOD_NAME_META, NULL) == 0); /* none down */ xkb_state_update_key(state, KEY_RIGHTALT + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_MOD1, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_META, XKB_STATE_MODS_EFFECTIVE) == 0); /* Caps locked */ xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_DEPRESSED) > 0); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); fprintf(stderr, "dumping state for Caps Lock:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_DEPRESSED) == 0); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED) > 0); assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_CAPS) > 0); num_syms = xkb_state_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms); assert(num_syms == 1 && syms[0] == XKB_KEY_Q); /* Num Lock locked */ xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP); fprintf(stderr, "dumping state for Caps Lock + Num Lock:\n"); print_state(state); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED) > 0); assert(xkb_state_mod_name_is_active(state, XKB_VMOD_NAME_NUM, XKB_STATE_MODS_LOCKED) > 0); assert(check_active(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_MOD2, XKB_STATE_MODS_LOCKED))); num_syms = xkb_state_key_get_syms(state, KEY_KP1 + EVDEV_OFFSET, &syms); assert(num_syms == 1 && syms[0] == XKB_KEY_KP_1); assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) > 0); /* Num Lock unlocked */ xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_NUMLOCK + EVDEV_OFFSET, XKB_KEY_UP); /* Switch to group 2 */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_led_name_is_active(state, "Group 2") > 0); assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_NUM) == 0); /* Switch back to group 1. */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); /* Caps unlocked */ xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CAPS, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_led_name_is_active(state, XKB_LED_NAME_CAPS) == 0); num_syms = xkb_state_key_get_syms(state, KEY_Q + EVDEV_OFFSET, &syms); assert(num_syms == 1 && syms[0] == XKB_KEY_q); /* Multiple symbols */ num_syms = xkb_state_key_get_syms(state, KEY_6 + EVDEV_OFFSET, &syms); assert(num_syms == 5 && syms[0] == XKB_KEY_H && syms[1] == XKB_KEY_E && syms[2] == XKB_KEY_L && syms[3] == XKB_KEY_L && syms[4] == XKB_KEY_O); one_sym = xkb_state_key_get_one_sym(state, KEY_6 + EVDEV_OFFSET); assert(one_sym == XKB_KEY_NoSymbol); xkb_state_update_key(state, KEY_6 + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_6 + EVDEV_OFFSET, XKB_KEY_UP); one_sym = xkb_state_key_get_one_sym(state, KEY_5 + EVDEV_OFFSET); assert(one_sym == XKB_KEY_5); xkb_state_unref(state); } enum test_entry_input_type { INPUT_TYPE_RESET = 0, INPUT_TYPE_COMPONENTS, INPUT_TYPE_KEY, }; struct test_state_components { enum test_entry_input_type input_type; union { struct { bool affect_latched_group; int32_t latched_group; bool affect_locked_group; int32_t locked_group; xkb_mod_mask_t affect_latched_mods; xkb_mod_mask_t latched_mods; xkb_mod_mask_t affect_locked_mods; xkb_mod_mask_t locked_mods; } input; struct { xkb_keycode_t keycode; enum key_seq_state direction; xkb_keysym_t keysym; } key; }; /* Same as state_components, but it is not public */ int32_t base_group; /**< depressed */ int32_t latched_group; int32_t locked_group; xkb_layout_index_t group; /**< effective */ xkb_mod_mask_t base_mods; /**< depressed */ xkb_mod_mask_t latched_mods; xkb_mod_mask_t locked_mods; xkb_mod_mask_t mods; /**< effective */ xkb_led_mask_t leds; enum xkb_state_component changes; }; #define COMPONENTS_ENTRY(...) \ .input_type = INPUT_TYPE_COMPONENTS, .input = { __VA_ARGS__ } #define KEY_ENTRY(_keycode, _direction, _keysym) \ .input_type = INPUT_TYPE_KEY, \ .key = { .keycode=(_keycode) + EVDEV_OFFSET, \ .direction=(_direction), \ .keysym=(_keysym) } #define RESET_STATE { .input_type = INPUT_TYPE_RESET } static bool check_update_state(struct xkb_keymap *keymap, const struct test_state_components *components, struct xkb_state *expected, struct xkb_state *got, xkb_keysym_t keysym, enum xkb_state_component changes) { xkb_state_update_mask(expected, mod_mask_get_effective(keymap, components->base_mods), mod_mask_get_effective(keymap, components->latched_mods), mod_mask_get_effective(keymap, components->locked_mods), components->base_group, components->latched_group, components->locked_group); if (changes != components->changes) { fprintf(stderr, "Expected state change: %u, but got: %u\n", components->changes, changes); fprintf(stderr, "Expected state:\n"); print_state(expected); fprintf(stderr, "Got state:\n"); print_state(got); return false; } else if (components->input_type == INPUT_TYPE_KEY) { if (keysym != components->key.keysym) { char buf[XKB_KEYSYM_NAME_MAX_SIZE]; xkb_keysym_get_name(components->key.keysym, buf, sizeof(buf)); fprintf(stderr, "Expected keysym: %s, ", buf); xkb_keysym_get_name(keysym, buf, sizeof(buf)); fprintf(stderr, "but got: %s\n", buf); return false; } } else if (keysym != XKB_KEY_NoSymbol) { return false; } return check_state(expected, got); } static bool run_state_update(struct xkb_keymap *keymap, const struct test_state_components *components, struct xkb_state **expected, struct xkb_state **got) { xkb_keysym_t keysym = XKB_KEY_NoSymbol; enum xkb_state_component changes = 0; switch (components->input_type) { case INPUT_TYPE_COMPONENTS: changes = xkb_state_update_latched_locked( *got, components->input.affect_latched_mods, components->input.latched_mods, components->input.affect_latched_group, components->input.latched_group, components->input.affect_locked_mods, components->input.locked_mods, components->input.affect_locked_group, components->input.locked_group ); break; case INPUT_TYPE_KEY: keysym = xkb_state_key_get_one_sym(*got, components->key.keycode); if (components->key.direction == DOWN || components->key.direction == BOTH) changes = xkb_state_update_key( *got, components->key.keycode, XKB_KEY_DOWN ); if (components->key.direction == UP || components->key.direction == BOTH) changes = xkb_state_update_key( *got, components->key.keycode, XKB_KEY_UP ); break; case INPUT_TYPE_RESET: xkb_state_unref(*got); xkb_state_unref(*expected); *got = xkb_state_new(keymap); *expected = xkb_state_new(keymap); assert(*got); assert(*expected); return true; default: assert_printf(false, "Unsupported input type: %d\n", components->input_type); } return check_update_state( keymap, components, *expected, *got, keysym, changes ); } static void test_update_latched_locked(struct xkb_keymap *keymap) { struct xkb_state *state = xkb_state_new(keymap); struct xkb_state *expected = xkb_state_new(keymap); assert(state); assert(expected); xkb_mod_mask_t shift = xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_SHIFT); xkb_mod_mask_t capslock = xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_CAPS); xkb_mod_mask_t control = xkb_keymap_mod_get_mask(keymap, XKB_MOD_NAME_CTRL); xkb_mod_mask_t level3 = xkb_keymap_mod_get_mask(keymap, XKB_VMOD_NAME_LEVEL3); xkb_led_index_t capslock_led_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_CAPS); xkb_led_index_t group2_led_idx = _xkb_keymap_led_get_index(keymap, "Group 2"); xkb_led_mask_t capslock_led = UINT32_C(1) << capslock_led_idx; xkb_led_mask_t group2_led = UINT32_C(1) << group2_led_idx; const struct test_state_components test_data[] = { { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 }, /* * Groups: lock */ #define GROUP_LOCK_ENTRY(group) \ COMPONENTS_ENTRY(.affect_locked_group = true, .locked_group = (group)) #define GROUP_LOCK_CHANGES \ (XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS) { GROUP_LOCK_ENTRY(1), .locked_group=1, .group=1, .leds=group2_led, .changes=GROUP_LOCK_CHANGES }, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_Cyrillic_ef), .locked_group=1, .group=1, .leds = group2_led, .changes = 0 }, { GROUP_LOCK_ENTRY(0), .locked_group=0, .group=0, .leds=0, .changes=GROUP_LOCK_CHANGES }, { GROUP_LOCK_ENTRY(0), .locked_group=0, .group=0, .leds=0, .changes=0 }, { GROUP_LOCK_ENTRY(-2), .locked_group=0, .group=0, /* Wrapped */ .leds=0, .changes=0 }, { GROUP_LOCK_ENTRY(-2), .locked_group=0, .group=0, /* Wrapped */ .leds=0, .changes=0 }, { GROUP_LOCK_ENTRY(-1), .locked_group=1, .group=1, /* Wrapped */ .leds=group2_led, .changes=GROUP_LOCK_CHANGES }, { GROUP_LOCK_ENTRY(-1), .locked_group=1, .group=1, /* Wrapped */ .leds=group2_led, .changes=0 }, { GROUP_LOCK_ENTRY(0), .locked_group=0, .group=0, .leds=0, .changes=GROUP_LOCK_CHANGES }, { GROUP_LOCK_ENTRY(1), .locked_group=1, .group=1, .leds=group2_led, .changes=GROUP_LOCK_CHANGES }, { GROUP_LOCK_ENTRY(1), .locked_group=1, .group=1, .leds=group2_led, .changes=0 }, { GROUP_LOCK_ENTRY(2), .locked_group=0, .group=0, /* Wrapped */ .leds=0, .changes=GROUP_LOCK_CHANGES }, { GROUP_LOCK_ENTRY(2), .locked_group=0, .group=0, /* Wrapped */ .leds=0, .changes=0 }, /* Invalid group */ { GROUP_LOCK_ENTRY(XKB_MAX_GROUPS), .locked_group=0, .group=0, .leds=0, .changes=0 }, /* Previous lock */ { KEY_ENTRY(KEY_COMPOSE, DOWN, XKB_KEY_ISO_Next_Group), .locked_group = 1, .group = 1, .leds = group2_led, .changes = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_COMPOSE, UP, XKB_KEY_ISO_Next_Group), .locked_group = 1, .group = 1, .leds = group2_led, .changes = 0 }, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_Cyrillic_ef), .locked_group=1, .group=1, .leds = group2_led, .changes = 0 }, { GROUP_LOCK_ENTRY(0), .locked_group=0, .group=0, .leds=group2_led, .changes=XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 }, { KEY_ENTRY(KEY_COMPOSE, DOWN, XKB_KEY_ISO_Next_Group), .locked_group = 1, .group = 1, .leds = group2_led, .changes = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_COMPOSE, UP, XKB_KEY_ISO_Next_Group), .locked_group = 1, .group = 1, .leds = group2_led, .changes = 0 }, /* * Groups: latch */ #define GROUP_LATCH_ENTRY(group) \ COMPONENTS_ENTRY(.affect_latched_group = true, .latched_group = (group)) RESET_STATE, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .base_group = 0, .latched_group = 0, .locked_group = 0, .group = 0, .base_mods = 0, .latched_mods = 0, .locked_mods = 0, .mods = 0, .leds = 0, .changes = 0 }, { GROUP_LATCH_ENTRY(1), .latched_group=1, .group=1, .leds=group2_led, .changes=XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_ef), .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .changes = 0 }, { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 }, { GROUP_LATCH_ENTRY(1), .latched_group=1, .group=1, .leds=group2_led, .changes=XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { GROUP_LATCH_ENTRY(1), .latched_group=1, .group=1, .leds=group2_led, .changes=0 }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_ef), .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .changes = 0 }, { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 }, /* Invalid group */ { GROUP_LATCH_ENTRY(XKB_MAX_GROUPS), .latched_group=XKB_MAX_GROUPS, .group=0, .leds=0, .changes=XKB_STATE_LAYOUT_LATCHED }, /* Pending latch is cancelled */ RESET_STATE, { KEY_ENTRY(KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Group_Latch), .latched_group = 1, .group = 1, .leds = group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED }, { GROUP_LATCH_ENTRY(2), .latched_group=2, .group=0, .leds = 0, .changes=XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .changes = XKB_STATE_LAYOUT_LATCHED }, /* Pending latch to lock is cancelled */ RESET_STATE, { KEY_ENTRY(KEY_RIGHTMETA, BOTH, XKB_KEY_ISO_Group_Latch), .latched_group = 1, .group = 1, .leds = group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED }, { GROUP_LATCH_ENTRY(2), .latched_group=2, .group=0, .leds = 0, .changes=XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .changes = XKB_STATE_LAYOUT_LATCHED }, /* Broken latch does not unlock if clearLocks is not set */ RESET_STATE, { GROUP_LOCK_ENTRY(1), .locked_group=1, .group=1, .leds=group2_led, .changes=XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_SCROLLLOCK, DOWN, XKB_KEY_ISO_Group_Latch), .base_group=1, .latched_group=0, .locked_group=1, .group=0, .leds=0, .changes=XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { /* Breaks latch */ KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .base_group=1, .latched_group=0, .locked_group=1, .group=0, .leds=0, .changes=0 }, { KEY_ENTRY(KEY_SCROLLLOCK, UP, XKB_KEY_ISO_Group_Latch), .base_group=0, .latched_group=0, .locked_group=1, .group=1, .leds=group2_led, .changes=XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, /* * Groups: latch + lock */ RESET_STATE, /* Empty state */ { COMPONENTS_ENTRY(.affect_latched_group = true, .latched_group = 1, .affect_locked_group = true, .locked_group = 1), .latched_group = 1, .locked_group = 1, .group = 0, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_LOCKED }, /* Pending latch */ RESET_STATE, { KEY_ENTRY(KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Group_Latch), .latched_group = 1, .group = 1, .leds = group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED }, { COMPONENTS_ENTRY(.affect_locked_group = true, .locked_group = 1), .latched_group = 1, .locked_group = 1, .group = 0, .changes = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .locked_group=1, .group=1, .leds = group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS }, /* * Modifiers: lock */ #define MOD_LOCK_ENTRY(mask, mods) \ COMPONENTS_ENTRY(.affect_locked_mods = (mask), .locked_mods = (mods)) #define UNDEFINED_MODMASK (UINT32_C(1) << (XKB_MAX_MODS - 1)) RESET_STATE, /* Invalid: mod not in the mask */ { MOD_LOCK_ENTRY(0, capslock), .changes=0 }, { MOD_LOCK_ENTRY(0, UNDEFINED_MODMASK), .changes=0 }, /* Set Caps */ { MOD_LOCK_ENTRY(capslock, capslock), .locked_mods=capslock, .mods=capslock, .leds=capslock_led, .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS }, { MOD_LOCK_ENTRY(capslock, capslock), .locked_mods=capslock, .mods=capslock, .leds=capslock_led, .changes=0 }, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_A), .locked_mods=capslock, .mods=capslock, .leds=capslock_led, .changes = 0 }, /* Add Control and keep Caps */ { MOD_LOCK_ENTRY(control, control), .locked_mods=control | capslock, .mods=control | capslock, .leds=capslock_led, .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_A), .locked_mods=control | capslock, .mods=control | capslock, .leds=capslock_led, .changes = 0 }, /* Remove Caps and keep Control */ { MOD_LOCK_ENTRY(capslock, 0), .locked_mods=control, .mods=control, .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .locked_mods=control, .mods=control, .leds=0, .changes = 0 }, /* Add Level3 and remove Control */ { MOD_LOCK_ENTRY(level3 | control, level3), .locked_mods=level3, .mods=level3, .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE }, /* Change undefined modifier */ { MOD_LOCK_ENTRY(level3, level3 | UNDEFINED_MODMASK), .locked_mods=level3, .mods=level3, .changes=0 }, { MOD_LOCK_ENTRY(level3 | UNDEFINED_MODMASK, level3 | UNDEFINED_MODMASK), .locked_mods=level3, .mods=level3, .changes=0 }, { MOD_LOCK_ENTRY(level3 | UNDEFINED_MODMASK, level3), .locked_mods=level3, .mods=level3, .changes=0 }, /* Previous lock */ RESET_STATE, { KEY_ENTRY(KEY_CAPSLOCK, BOTH, XKB_KEY_Caps_Lock), .locked_mods=capslock, .mods=capslock, .leds=capslock_led, .changes = XKB_STATE_MODS_DEPRESSED }, { MOD_LOCK_ENTRY(level3 | control, level3), .locked_mods=capslock | level3, .mods=capslock | level3, .leds=capslock_led, .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE }, { MOD_LOCK_ENTRY(capslock, 0), .locked_mods=level3, .mods=level3, .leds=0, .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS }, /* * Modifiers: latch */ #define MODS_LATCH_ENTRY(mask, mods) \ COMPONENTS_ENTRY(.affect_latched_mods = (mask), .latched_mods = (mods)) RESET_STATE, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 }, /* Invalid: mod not in the mask */ { MODS_LATCH_ENTRY(0, shift), .changes=0 }, { MODS_LATCH_ENTRY(0, UNDEFINED_MODMASK), .changes=0 }, /* Latch Shift */ { MODS_LATCH_ENTRY(shift, shift), .latched_mods=shift, .mods=shift, .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_A), .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 }, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 }, { MODS_LATCH_ENTRY(shift, shift), .latched_mods=shift, .mods=shift, .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { MODS_LATCH_ENTRY(shift, shift), .latched_mods=shift, .mods=shift, .changes=0 }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_A), .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 }, { KEY_ENTRY(KEY_A, BOTH, XKB_KEY_a), .changes = 0 }, /* Latch Shift, then Caps: latched shift is cancelled */ { MODS_LATCH_ENTRY(shift, shift), .latched_mods=shift, .mods=shift, .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { MODS_LATCH_ENTRY(capslock, capslock), .latched_mods=shift | capslock, .mods=shift | capslock, .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, UP, XKB_KEY_a), .changes = 0 }, /* Change undefined modifier */ { MODS_LATCH_ENTRY(level3, level3 | UNDEFINED_MODMASK), .latched_mods=level3, .mods=level3, .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { MODS_LATCH_ENTRY(level3 | UNDEFINED_MODMASK, level3 | UNDEFINED_MODMASK), .latched_mods=level3, .mods=level3, .changes=0 }, { MODS_LATCH_ENTRY(level3 | UNDEFINED_MODMASK, level3), .latched_mods=level3, .mods=level3, .changes=0 }, /* Pending latch is *not* cancelled if not in affected mods */ RESET_STATE, { KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch), .latched_mods=level3, .mods=level3, .changes = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED }, { MODS_LATCH_ENTRY(shift, shift), .latched_mods=shift | level3, .mods=shift | level3, .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_A), .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, /* Pending latch *is* cancelled if in affected mods */ RESET_STATE, { KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch), .latched_mods=level3, .mods=level3, .changes = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED }, { MODS_LATCH_ENTRY(shift | level3, shift), .latched_mods=shift, .mods=shift, .changes=XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_A), .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, /* Latch-to-lock */ RESET_STATE, { /* Set capslock, to ensure that when *mutating* the latch to a lock, * the `priv` field and refcnt fields are set accordingly. */ MOD_LOCK_ENTRY(capslock, capslock), .locked_mods=capslock, .mods=capslock, .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch), /* Pending latch */ .base_mods=0, .latched_mods=level3, .locked_mods=capslock, .mods=capslock | level3, .changes = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED }, { KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch), /* Mutate to a lock */ .base_mods=0, .latched_mods=0, .locked_mods=capslock | level3, .mods=capslock | level3, .changes = XKB_STATE_MODS_DEPRESSED }, { KEY_ENTRY(KEY_102ND, BOTH, XKB_KEY_ISO_Level3_Latch), /* Unlock via latch’s ACTION_LOCK_CLEAR */ .base_mods=0, .latched_mods=0, .locked_mods=capslock, .mods=capslock, .changes = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE }, /* Broken latch does not unlock if clearLocks is not set */ RESET_STATE, { /* Set capslock, to ensure that when *mutating* the latch to a lock, * the `priv` field and refcnt fields are set accordingly. */ MOD_LOCK_ENTRY(level3, level3), .locked_mods=level3, .mods=level3, .changes=XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_BACKSLASH, DOWN, XKB_KEY_ISO_Level3_Latch), .base_mods=level3, .latched_mods=0, .locked_mods=level3, .mods=level3, .changes = XKB_STATE_MODS_DEPRESSED }, { /* Breaks latch */ KEY_ENTRY(KEY_A, DOWN, XKB_KEY_a), .base_mods=level3, .latched_mods=0, .locked_mods=level3, .mods=level3, .changes = 0 }, { KEY_ENTRY(KEY_BACKSLASH, UP, XKB_KEY_ISO_Level3_Latch), .base_mods=0, .latched_mods=0, .locked_mods=level3, .mods=level3, .changes = XKB_STATE_MODS_DEPRESSED }, // TODO /* * Modifiers: latched + locked */ RESET_STATE, { COMPONENTS_ENTRY(.affect_latched_mods = shift, .latched_mods = shift, .affect_locked_mods = level3, .locked_mods = level3), .latched_mods = shift, .locked_mods = level3, .mods = shift | level3, .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE }, // TODO /* * Mix */ /* Lock mods & groups */ RESET_STATE, { COMPONENTS_ENTRY(.affect_locked_group=true, .locked_group=1, .affect_locked_mods=control, .locked_mods=control), .locked_group=1, .group=1, .locked_mods=control, .mods=control, .leds=group2_led, .changes = XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS }, /* When updating latches, mod/group changes should not affect each other */ RESET_STATE, { COMPONENTS_ENTRY(.affect_latched_group=true, .latched_group=1, .affect_latched_mods=control, .latched_mods=control), .latched_group=1, .group=1, .latched_mods=control, .mods=control, .leds=group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_ef), .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_LEDS | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, RESET_STATE, { KEY_ENTRY(KEY_LEFTMETA, BOTH, XKB_KEY_ISO_Group_Latch), .latched_group = 1, .group = 1, .leds = group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED }, /* Pending group latch */ { COMPONENTS_ENTRY(.affect_latched_mods=shift, .latched_mods=shift), .latched_group=1, .group=1, .latched_mods=shift, .mods=shift, .leds = group2_led, .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_EF), .leds = group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS }, { KEY_ENTRY(KEY_RIGHTMETA, BOTH, XKB_KEY_ISO_Group_Latch), .latched_group = 1, .group = 1, .leds = group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_DEPRESSED }, /* Pending group latch (with latch to lock + clear) */ { COMPONENTS_ENTRY(.affect_latched_mods=shift, .latched_mods=shift), .latched_group=1, .group=1, .latched_mods=shift, .mods=shift, .leds = group2_led, .changes = XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE }, { KEY_ENTRY(KEY_A, DOWN, XKB_KEY_Cyrillic_EF), .leds = group2_led, .changes = XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_EFFECTIVE | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS }, // TODO }; for (size_t k = 0; k < ARRAY_SIZE(test_data); k++) { assert_printf( run_state_update(keymap, &test_data[k], &expected, &state), "%s #%zu: type: %d\n", __func__, k, test_data[k].input_type ); } xkb_state_unref(expected); xkb_state_unref(state); #undef COMPONENTS_ENTRY } struct test_active_mods_entry { xkb_mod_mask_t state; xkb_mod_mask_t active; }; static void test_serialisation(struct xkb_keymap *keymap, bool pure_vmods) { struct xkb_state *state = xkb_state_new(keymap); xkb_mod_mask_t base_mods; xkb_mod_mask_t latched_mods; xkb_mod_mask_t locked_mods; xkb_mod_mask_t effective_mods; xkb_layout_index_t base_group = 0; xkb_layout_index_t latched_group = 0; xkb_layout_index_t locked_group = 0; assert(state); xkb_mod_index_t shiftIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); xkb_mod_index_t capsIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); xkb_mod_index_t ctrlIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); xkb_mod_index_t mod1Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1); xkb_mod_index_t mod2Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD2); xkb_mod_index_t mod3Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD3); xkb_mod_index_t mod4Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD4); xkb_mod_index_t mod5Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD5); xkb_mod_index_t altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT); xkb_mod_index_t metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META); xkb_mod_index_t superIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SUPER); xkb_mod_index_t hyperIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_HYPER); xkb_mod_index_t numIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_NUM); xkb_mod_index_t level3Idx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_LEVEL3); xkb_mod_index_t altGrIdx = _xkb_keymap_mod_get_index(keymap, "AltGr"); xkb_mod_mask_t shift = (UINT32_C(1) << shiftIdx); xkb_mod_mask_t caps = (UINT32_C(1) << capsIdx); xkb_mod_mask_t ctrl = (UINT32_C(1) << ctrlIdx); xkb_mod_mask_t mod1 = (UINT32_C(1) << mod1Idx); xkb_mod_mask_t mod2 = (UINT32_C(1) << mod2Idx); xkb_mod_mask_t mod3 = (UINT32_C(1) << mod3Idx); xkb_mod_mask_t mod4 = (UINT32_C(1) << mod4Idx); xkb_mod_mask_t mod5 = (UINT32_C(1) << mod5Idx); xkb_mod_mask_t alt = (UINT32_C(1) << altIdx); xkb_mod_mask_t meta = (UINT32_C(1) << metaIdx); xkb_mod_mask_t super = (UINT32_C(1) << superIdx); xkb_mod_mask_t hyper = (UINT32_C(1) << hyperIdx); xkb_mod_mask_t num = (UINT32_C(1) << numIdx); xkb_mod_mask_t level3 = (UINT32_C(1) << level3Idx); xkb_mod_mask_t altGr = (UINT32_C(1) << altGrIdx); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == 0); latched_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED); assert(latched_mods == 0); locked_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED); assert(locked_mods == caps); effective_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); assert(effective_mods == locked_mods); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); base_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED); assert(base_mods == shift); latched_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED); assert(latched_mods == 0); locked_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED); assert(locked_mods == caps); effective_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); assert(effective_mods == (base_mods | locked_mods)); base_mods |= ctrl; xkb_state_update_mask(state, base_mods, latched_mods, locked_mods, base_group, latched_group, locked_group); assert(xkb_state_mod_index_is_active(state, ctrlIdx, XKB_STATE_MODS_DEPRESSED) > 0); assert(xkb_state_mod_index_is_active(state, ctrlIdx, XKB_STATE_MODS_EFFECTIVE) > 0); const struct test_active_mods_entry test_data_real[] = { { .state = 0, .active = 0 }, { .state = shift, .active = shift }, { .state = caps, .active = caps }, { .state = ctrl, .active = ctrl }, { .state = mod1, .active = mod1 | alt | meta }, { .state = mod2, .active = mod2 | num }, { .state = mod3, .active = mod3 }, { .state = mod4, .active = mod4 | super | hyper }, { .state = mod5, .active = mod5 | level3 | altGr }, { .state = shift | mod1, .active = shift | mod1 | alt | meta }, { .state = shift | mod2, .active = shift | mod2 | num }, }; const struct test_active_mods_entry test_data_virtual[] = { { .state = 0, .active = 0 }, { .state = shift, .active = shift }, { .state = caps, .active = caps }, { .state = ctrl, .active = ctrl }, { .state = mod1, .active = mod1 }, { .state = mod2, .active = mod2 }, { .state = mod3, .active = mod3 }, { .state = mod4, .active = mod4 }, { .state = mod5, .active = mod5 }, { .state = alt, .active = alt }, { .state = meta, .active = meta }, { .state = super, .active = super }, { .state = hyper, .active = hyper }, { .state = num, .active = num }, { .state = level3, .active = level3 }, { .state = shift | mod1, .active = shift | mod1 }, { .state = mod1 | alt, .active = mod1 | alt }, { .state = alt | meta, .active = alt | meta }, { .state = alt | level3, .active = alt | level3 }, }; const struct test_active_mods_entry *test_data = pure_vmods ? test_data_virtual : test_data_real; unsigned int k_max = pure_vmods ? ARRAY_SIZE(test_data_virtual) : ARRAY_SIZE(test_data_real); for (unsigned int k = 0; k < k_max; k++) { const struct test_active_mods_entry *entry = &test_data[k]; #define check_mods(keymap, state_, entry, type) \ for (xkb_mod_index_t idx = 0; idx < xkb_keymap_num_mods(keymap); idx++) { \ xkb_mod_mask_t mask = UINT32_C(1) << idx; \ fprintf(stderr, "#%"PRIu32" State %#"PRIx32", mod: %s (%"PRIu32")\n", \ k, (entry)->state, xkb_keymap_mod_get_name(keymap, idx), idx); \ { \ xkb_mod_mask_t expected = mod_mask_get_effective(keymap, \ (entry)->state); \ xkb_mod_mask_t got = xkb_state_serialize_mods(state, type); \ assert_printf(got == expected, \ "xkb_state_serialize_mods, " STRINGIFY2(type) \ ", expected %#"PRIx32", got %#"PRIx32"\n", \ expected, got); \ } \ bool expected = !!(mask & (entry)->active); \ bool got = !!xkb_state_mod_index_is_active(state_, idx, type); \ assert_printf(got == expected, \ "xkb_state_mod_index_is_active, " STRINGIFY2(type) "\n"); \ got = !!xkb_state_mod_index_is_active(state_, idx, \ XKB_STATE_MODS_EFFECTIVE); \ assert_printf(got == expected, "xkb_state_mod_index_is_active, " \ STRINGIFY2(XKB_STATE_MODS_EFFECTIVE) "\n"); \ got = !!xkb_state_mod_indices_are_active( \ state_, type, \ XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE, \ idx, XKB_MOD_INVALID); \ assert_printf(got == expected, "xkb_state_mod_indices_are_active, " \ STRINGIFY2(type) "\n"); \ got = !!xkb_state_mod_indices_are_active( \ state_, XKB_STATE_MODS_EFFECTIVE, \ XKB_STATE_MATCH_ALL | XKB_STATE_MATCH_NON_EXCLUSIVE, \ idx, XKB_MOD_INVALID); \ assert_printf(got == expected, "xkb_state_mod_indices_are_active, " \ STRINGIFY2(XKB_STATE_MODS_EFFECTIVE) "\n"); \ } xkb_state_update_mask(state, entry->state, 0, 0, 0, 0, 0); check_mods(keymap, state, entry, XKB_STATE_MODS_DEPRESSED); xkb_state_update_mask(state, 0, entry->state, 0, 0, 0, 0); check_mods(keymap, state, entry, XKB_STATE_MODS_LATCHED); xkb_state_update_mask(state, 0, 0, entry->state, 0, 0, 0); check_mods(keymap, state, entry, XKB_STATE_MODS_LOCKED); } xkb_state_unref(state); } static inline xkb_mod_mask_t canonical_mask(bool is_pure, xkb_mod_mask_t vmod, xkb_mod_mask_t real) { return is_pure ? vmod : real; } static void test_update_mask_mods(struct xkb_keymap *keymap, bool pure_vmods) { enum xkb_state_component changed; struct xkb_state *state = xkb_state_new(keymap); assert(state); xkb_mod_index_t capsIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); xkb_mod_index_t shiftIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); xkb_mod_index_t mod1Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1); xkb_mod_index_t mod2Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD2); xkb_mod_index_t altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT); xkb_mod_index_t metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META); xkb_mod_index_t numIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_NUM); xkb_mod_mask_t caps = (UINT32_C(1) << capsIdx); xkb_mod_mask_t shift = (UINT32_C(1) << shiftIdx); xkb_mod_mask_t mod1 = (UINT32_C(1) << mod1Idx); xkb_mod_mask_t mod2 = (UINT32_C(1) << mod2Idx); xkb_mod_mask_t alt = (UINT32_C(1) << altIdx); xkb_mod_mask_t meta = (UINT32_C(1) << metaIdx); xkb_mod_mask_t num = (UINT32_C(1) << numIdx); changed = xkb_state_update_mask(state, caps, 0, 0, 0, 0, 0); assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == caps); changed = xkb_state_update_mask(state, caps, 0, shift, 0, 0, 0); assert(changed == (XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == (caps | shift)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED) == caps); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == shift); changed = xkb_state_update_mask(state, 0, 0, 0, 0, 0, 0); assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0); changed = xkb_state_update_mask(state, alt, 0, 0, 0, 0, 0); assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == canonical_mask(pure_vmods, alt, mod1)); changed = xkb_state_update_mask(state, meta, 0, 0, 0, 0, 0); assert(changed == (pure_vmods ? (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_EFFECTIVE) : 0 /* Same canonical modifier state */)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == canonical_mask(pure_vmods, meta, mod1)); changed = xkb_state_update_mask(state, 0, 0, num, 0, 0, 0); assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == canonical_mask(pure_vmods, num, mod2)); xkb_state_update_mask(state, 0, 0, 0, 0, 0, 0); changed = xkb_state_update_mask(state, mod2, 0, num, 0, 0, 0); assert(changed == (XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE | XKB_STATE_LEDS)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == canonical_mask(pure_vmods, mod2 | num, mod2)); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED) == mod2); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == canonical_mask(pure_vmods, num, mod2)); xkb_state_unref(state); } static void test_repeat(struct xkb_keymap *keymap) { assert(!xkb_keymap_key_repeats(keymap, KEY_LEFTSHIFT + EVDEV_OFFSET)); assert(xkb_keymap_key_repeats(keymap, KEY_A + EVDEV_OFFSET)); assert(xkb_keymap_key_repeats(keymap, KEY_8 + EVDEV_OFFSET)); assert(xkb_keymap_key_repeats(keymap, KEY_DOWN + EVDEV_OFFSET)); assert(xkb_keymap_key_repeats(keymap, KEY_KBDILLUMDOWN + EVDEV_OFFSET)); } static void test_consume(struct xkb_keymap *keymap, bool pure_vmods) { xkb_mod_mask_t mask; xkb_mod_index_t shiftIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); xkb_mod_index_t capsIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); xkb_mod_index_t ctrlIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); xkb_mod_index_t mod1Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1); xkb_mod_index_t mod2Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD2); xkb_mod_index_t mod5Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD5); xkb_mod_index_t altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT); xkb_mod_index_t metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META); xkb_mod_index_t numIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_NUM); xkb_mod_index_t level3Idx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_LEVEL3); xkb_mod_mask_t caps = (UINT32_C(1) << capsIdx); xkb_mod_mask_t shift = (UINT32_C(1) << shiftIdx); xkb_mod_mask_t ctrl = (UINT32_C(1) << ctrlIdx); xkb_mod_mask_t mod1 = (UINT32_C(1) << mod1Idx); xkb_mod_mask_t mod2 = (UINT32_C(1) << mod2Idx); xkb_mod_mask_t mod5 = (UINT32_C(1) << mod5Idx); xkb_mod_mask_t alt = (UINT32_C(1) << altIdx); xkb_mod_mask_t meta = (UINT32_C(1) << metaIdx); xkb_mod_mask_t num = (UINT32_C(1) << numIdx); xkb_mod_mask_t level3 = (UINT32_C(1) << level3Idx); struct xkb_state *state = xkb_state_new(keymap); assert(state); /* Test remove_consumed() */ xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_EQUAL + EVDEV_OFFSET, XKB_KEY_DOWN); fprintf(stderr, "dumping state for Alt-Shift-+\n"); print_state(state); mask = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); assert(mask == (canonical_mask(pure_vmods, alt, mod1) | shift)); mask = xkb_state_mod_mask_remove_consumed(state, KEY_EQUAL + EVDEV_OFFSET, mask); assert(mask == canonical_mask(pure_vmods, alt, mod1)); /* Test get_consumed_mods() */ mask = xkb_state_key_get_consumed_mods(state, KEY_EQUAL + EVDEV_OFFSET); assert(mask == shift); mask = xkb_state_key_get_consumed_mods(state, KEY_ESC + EVDEV_OFFSET); assert(mask == 0); assert(xkb_state_mod_index_is_consumed(state, KEY_EQUAL + EVDEV_OFFSET, shiftIdx) > 0); assert(xkb_state_mod_index_is_consumed(state, KEY_EQUAL + EVDEV_OFFSET, mod1Idx) == 0); assert(xkb_state_mod_index_is_consumed(state, KEY_EQUAL + EVDEV_OFFSET, altIdx) == 0); assert(xkb_state_mod_index_is_consumed(state, KEY_EQUAL + EVDEV_OFFSET, metaIdx) == 0); xkb_state_unref(state); /* Test is_consumed() - simple ALPHABETIC type. */ state = xkb_state_new(keymap); assert(state); mask = xkb_state_key_get_consumed_mods(state, KEY_A + EVDEV_OFFSET); assert(mask == (shift | caps)); assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, capsIdx) > 0); assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shiftIdx) > 0); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, capsIdx) > 0); assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shiftIdx) > 0); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, capsIdx) > 0); assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shiftIdx) > 0); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, capsIdx) > 0); assert(xkb_state_mod_index_is_consumed(state, KEY_A + EVDEV_OFFSET, shiftIdx) > 0); xkb_state_unref(state); /* More complicated - CTRL+ALT */ state = xkb_state_new(keymap); assert(state); mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET); assert(mask == (shift | canonical_mask(pure_vmods, alt, mod1) | ctrl | canonical_mask(pure_vmods, level3, mod5))); /* Shift is preserved. */ xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET); assert(mask == (canonical_mask(pure_vmods, alt, mod1) | ctrl | canonical_mask(pure_vmods, level3, mod5))); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); mask = xkb_state_key_get_consumed_mods(state, KEY_F1 + EVDEV_OFFSET); assert(mask == (shift | canonical_mask(pure_vmods, alt, mod1) | ctrl | canonical_mask(pure_vmods, level3, mod5))); xkb_state_unref(state); /* Test XKB_CONSUMED_MODE_GTK, CTRL+ALT */ state = xkb_state_new(keymap); assert(state); mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_GTK); assert(mask == 0); xkb_state_update_key(state, KEY_LEFTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_GTK); assert(mask == 0); xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN); mask = xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_GTK); assert(mask == (canonical_mask(pure_vmods, alt, mod1) | ctrl)); assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, shiftIdx) > 0); assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, ctrlIdx) > 0); assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, altIdx) > 0); if (pure_vmods) { assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, mod1Idx) == 0); assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, metaIdx) == 0); } else { assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, mod1Idx) > 0); assert(xkb_state_mod_index_is_consumed(state, KEY_F1 + EVDEV_OFFSET, metaIdx) > 0); } mask = ctrl | canonical_mask(pure_vmods, alt, mod1) | canonical_mask(pure_vmods, num, mod2); mask = xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, mask); assert(mask == canonical_mask(pure_vmods, num, mod2)); mask = ctrl | alt | canonical_mask(pure_vmods, alt, meta) | canonical_mask(pure_vmods, num, mod2); mask = xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, mask); assert(mask == canonical_mask(pure_vmods, num, mod2)); xkb_state_unref(state); /* Test XKB_CONSUMED_MODE_GTK, Simple Shift */ state = xkb_state_new(keymap); assert(state); mask = xkb_state_key_get_consumed_mods2(state, KEY_A + EVDEV_OFFSET, XKB_CONSUMED_MODE_GTK); assert(mask == (shift | caps)); xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN); mask = xkb_state_key_get_consumed_mods2(state, KEY_A + EVDEV_OFFSET, XKB_CONSUMED_MODE_GTK); assert(mask == (shift | caps)); xkb_state_unref(state); } static void test_overlapping_mods(struct xkb_context *context) { struct xkb_keymap *keymap; struct xkb_state *state; /* Super and Hyper are overlapping (full overlap) */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", NULL, "us", NULL, "overlapping_modifiers:super_hyper," "grp:win_space_toggle"); assert(keymap); xkb_mod_index_t shiftIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); xkb_mod_index_t capsIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); xkb_mod_index_t ctrlIdx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); xkb_mod_index_t mod1Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD1); xkb_mod_index_t mod3Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD3); xkb_mod_index_t mod4Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD4); xkb_mod_index_t mod5Idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_MOD5); xkb_mod_index_t altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT); xkb_mod_index_t metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META); xkb_mod_index_t superIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SUPER); xkb_mod_index_t hyperIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_HYPER); /* Note: not mapped */ xkb_mod_index_t scrollIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SCROLL); xkb_mod_mask_t shift = (UINT32_C(1) << shiftIdx); xkb_mod_mask_t ctrl = (UINT32_C(1) << ctrlIdx); xkb_mod_mask_t mod1 = (UINT32_C(1) << mod1Idx); xkb_mod_mask_t mod3 = (UINT32_C(1) << mod3Idx); xkb_mod_mask_t mod4 = (UINT32_C(1) << mod4Idx); xkb_mod_mask_t mod5 = (UINT32_C(1) << mod5Idx); xkb_mod_mask_t alt = (UINT32_C(1) << altIdx); xkb_mod_mask_t meta = (UINT32_C(1) << metaIdx); xkb_mod_mask_t super = (UINT32_C(1) << superIdx); xkb_mod_mask_t hyper = (UINT32_C(1) << hyperIdx); state = xkb_state_new(keymap); assert(state); const struct test_active_mods_entry test_data1[] = { { .state = 0, .active = 0 }, { .state = mod1, .active = mod1 | alt | meta }, { .state = mod3, .active = mod3 }, { .state = mod4, .active = mod4 }, { .state = alt, .active = mod1 | alt | meta }, { .state = meta, .active = mod1 | alt | meta }, { .state = super, .active = mod3 | mod4 | super | hyper }, { .state = hyper, .active = mod3 | mod4 | super | hyper }, { .state = mod3 | mod4, .active = mod3 | mod4 | super | hyper }, }; for (unsigned int k = 0; k < ARRAY_SIZE(test_data1); k++) { const struct test_active_mods_entry *entry = &test_data1[k]; xkb_state_update_mask(state, entry->state, 0, 0, 0, 0, 0); check_mods(keymap, state, entry, XKB_STATE_MODS_DEPRESSED); } assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == (mod3 | mod4)); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ANY, mod3Idx, mod4Idx, superIdx, hyperIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, mod3Idx, mod4Idx, superIdx, hyperIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) == (shift | ctrl | mod1 | mod5)); assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (mod1 | mod4 | mod5)) == mod4); assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (alt | super)) == (mod3 | mod4)); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, scrollIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_key_get_consumed_mods2(state, KEY_SPACE + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) == mod4); assert(xkb_state_mod_mask_remove_consumed(state, KEY_SPACE + EVDEV_OFFSET, (mod3 | mod4)) == mod3); assert(xkb_state_mod_mask_remove_consumed(state, KEY_SPACE + EVDEV_OFFSET, (super | hyper)) == mod3); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, scrollIdx, XKB_CONSUMED_MODE_XKB) == 0); xkb_state_update_mask(state, mod4, 0, 0, 0, 0, 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, scrollIdx, XKB_CONSUMED_MODE_XKB) == 0); xkb_state_unref(state); xkb_keymap_unref(keymap); /* Super and Hyper are overlapping (full overlap). * Alt overlaps with Meta (incomplete overlap) */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", NULL, "us", NULL, "overlapping_modifiers:meta," "grp:win_space_toggle"); assert(keymap); altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT); metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META); superIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SUPER); hyperIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_HYPER); alt = (UINT32_C(1) << altIdx); meta = (UINT32_C(1) << metaIdx); super = (UINT32_C(1) << superIdx); hyper = (UINT32_C(1) << hyperIdx); state = xkb_state_new(keymap); assert(state); const struct test_active_mods_entry test_data2[] = { { .state = 0, .active = 0 }, { .state = mod1, .active = mod1 | alt }, { .state = mod3, .active = mod3 }, { .state = mod4, .active = mod4 | hyper | super }, { .state = alt, .active = mod1 | alt }, { .state = meta, .active = mod1 | mod3 | alt | meta }, { .state = super, .active = mod4 | hyper | super }, { .state = hyper, .active = mod4 | hyper | super }, { .state = mod1 | mod3, .active = mod1 | mod3 | alt | meta }, { .state = mod1 | mod4, .active = mod1 | mod4 | alt | super | hyper }, { .state = mod3 | mod4, .active = mod3 | mod4 | super | hyper }, { .state = mod1 | mod3 | mod4, .active = mod1 | mod3 | mod4 | alt | meta | super | hyper }, }; for (unsigned int k = 0; k < ARRAY_SIZE(test_data2); k++) { const struct test_active_mods_entry *entry = &test_data2[k]; xkb_state_update_mask(state, entry->state, 0, 0, 0, 0, 0); check_mods(keymap, state, entry, XKB_STATE_MODS_DEPRESSED); } assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ANY, mod1Idx, mod3Idx, mod4Idx, altIdx, metaIdx, superIdx, hyperIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, mod1Idx, mod3Idx, mod4Idx, altIdx, metaIdx, superIdx, hyperIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) == (shift | ctrl | mod1 | mod5)); assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (mod1 | mod4 | mod5)) == mod4); assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (alt | super)) == mod4); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_key_get_consumed_mods2(state, KEY_SPACE + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) == mod4); assert(xkb_state_mod_mask_remove_consumed(state, KEY_SPACE + EVDEV_OFFSET, (mod3 | mod4)) == mod3); assert(xkb_state_mod_mask_remove_consumed(state, KEY_SPACE + EVDEV_OFFSET, (super | hyper)) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_SPACE + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) > 0); xkb_state_update_mask(state, mod1, 0, 0, 0, 0, 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ANY, mod1Idx, altIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, mod1Idx, altIdx, XKB_MOD_INVALID) > 0); xkb_state_update_mask(state, mod1 | mod3, 0, 0, 0, 0, 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ANY, mod1Idx, mod3Idx, altIdx, metaIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, mod1Idx, mod3Idx, altIdx, metaIdx, XKB_MOD_INVALID) > 0); xkb_state_unref(state); xkb_keymap_unref(keymap); /* Super and Hyper overlaps with Meta; Alt overlaps with Meta */ keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, "evdev", NULL, "us", NULL, "overlapping_modifiers:super_hyper," "overlapping_modifiers:meta"); assert(keymap); altIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_ALT); metaIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_META); superIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_SUPER); hyperIdx = _xkb_keymap_mod_get_index(keymap, XKB_VMOD_NAME_HYPER); alt = (UINT32_C(1) << altIdx); meta = (UINT32_C(1) << metaIdx); super = (UINT32_C(1) << superIdx); hyper = (UINT32_C(1) << hyperIdx); state = xkb_state_new(keymap); assert(state); const struct test_active_mods_entry test_data3[] = { { .state = 0, .active = 0 }, { .state = mod1, .active = mod1 | alt }, { .state = mod3, .active = mod3 }, { .state = mod4, .active = mod4 }, { .state = alt, .active = mod1 | alt }, { .state = meta, .active = mod1 | mod3 | alt | meta }, { .state = super, .active = mod3 | mod4 | super | hyper }, { .state = hyper, .active = mod3 | mod4 | super | hyper }, { .state = mod1 | mod3, .active = mod1 | mod3 | alt | meta }, { .state = mod1 | mod3, .active = mod1 | mod3 | alt | meta }, { .state = mod1 | mod4, .active = mod1 | mod4 | alt }, { .state = mod3 | mod4, .active = mod3 | mod4 | super | hyper }, { .state = mod1 | mod3 | mod4, .active = mod1 | mod3 | mod4 | alt | meta | super | hyper }, }; for (unsigned int k = 0; k < ARRAY_SIZE(test_data3); k++) { const struct test_active_mods_entry *entry = &test_data3[k]; xkb_state_update_mask(state, entry->state, 0, 0, 0, 0, 0); check_mods(keymap, state, entry, XKB_STATE_MODS_DEPRESSED); } assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ANY, mod1Idx, mod3Idx, mod4Idx, altIdx, metaIdx, superIdx, hyperIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, mod1Idx, mod3Idx, mod4Idx, altIdx, metaIdx, superIdx, hyperIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_key_get_consumed_mods2(state, KEY_F1 + EVDEV_OFFSET, XKB_CONSUMED_MODE_XKB) == (shift | ctrl | mod1 | mod5)); assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (mod1 | mod4 | mod5)) == mod4); assert(xkb_state_mod_mask_remove_consumed(state, KEY_F1 + EVDEV_OFFSET, (alt | super)) == (mod3 | mod4)); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, shiftIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, capsIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, ctrlIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod1Idx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, mod5Idx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, altIdx, XKB_CONSUMED_MODE_XKB) > 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, metaIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, superIdx, XKB_CONSUMED_MODE_XKB) == 0); assert(xkb_state_mod_index_is_consumed2(state, KEY_F1 + EVDEV_OFFSET, hyperIdx, XKB_CONSUMED_MODE_XKB) == 0); xkb_state_update_mask(state, mod1 | mod3, 0, 0, 0, 0, 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ANY, mod1Idx, mod3Idx, altIdx, metaIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, mod1Idx, mod3Idx, altIdx, metaIdx, XKB_MOD_INVALID) > 0); xkb_state_update_mask(state, mod1 | mod4, 0, 0, 0, 0, 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ANY, mod1Idx, mod4Idx, altIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, mod1Idx, mod4Idx, altIdx, XKB_MOD_INVALID) > 0); xkb_state_update_mask(state, mod3 | mod4, 0, 0, 0, 0, 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ANY, mod3Idx, mod4Idx, superIdx, hyperIdx, XKB_MOD_INVALID) > 0); assert(xkb_state_mod_indices_are_active(state, XKB_STATE_MODS_EFFECTIVE, XKB_STATE_MATCH_ALL, mod3Idx, mod4Idx, superIdx, hyperIdx, XKB_MOD_INVALID) > 0); xkb_state_unref(state); xkb_keymap_unref(keymap); } static void test_inactive_key_type_entry(struct xkb_context *context) { const char keymap_str[] = "xkb_keymap {\n" " xkb_keycodes {\n" " = 38;\n" " = 50;\n" " };\n" " xkb_types {\n" " virtual_modifiers Bound = Shift, Unbound;\n" " type \"X\" {\n" " modifiers = Bound+Unbound;\n" /* This entry should be ignored because it has an unbound modifier */ " map[Bound+Unbound] = Level1;\n" " map[Bound] = Level2;\n" " };\n" " };\n" " xkb_symbols {\n" " key { [ a, A ], type = \"X\" };\n" " key { [ SetMods(mods = Shift) ] };\n" " };\n" "};"; struct xkb_keymap *keymap = test_compile_buffer(context, XKB_KEYMAP_FORMAT_TEXT_V1, keymap_str, sizeof(keymap_str)); assert(keymap); struct xkb_state *state = xkb_state_new(keymap); assert(state); const xkb_mod_mask_t shift = (UINT32_C(1) << XKB_MOD_INDEX_SHIFT); assert(xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET) == XKB_KEY_a); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == shift); assert(xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET) == XKB_KEY_A); xkb_state_unref(state); xkb_keymap_unref(keymap); } static void key_iter(struct xkb_keymap *keymap, xkb_keycode_t key, void *data) { xkb_keycode_t *counter = data; assert(*counter == key); (*counter)++; } static void test_keycode_range(struct xkb_keymap *keymap) { xkb_keycode_t counter; assert(xkb_keymap_min_keycode(keymap) == 9); assert(xkb_keymap_max_keycode(keymap) == 569); counter = xkb_keymap_min_keycode(keymap); xkb_keymap_key_for_each(keymap, key_iter, &counter); assert(counter == xkb_keymap_max_keycode(keymap) + 1); } static void test_caps_keysym_transformation(struct xkb_context *context) { int nsyms; xkb_keysym_t sym; const xkb_keysym_t *syms; const char keymap_str[] = "xkb_keymap {\n" " xkb_keycodes { include \"evdev\" };\n" " xkb_compat { include \"basic\" };\n" " xkb_types { include \"complete\" };\n" " xkb_symbols {\n" " include \"pc+ch(fr)\"\n" " key { [{oe, ssharp}, {ae, s, s}] };" " key { [{3, ntilde}] };" " replace key { [{Control_R, ISO_Next_Group}] };" " };" "};"; struct xkb_keymap* const keymap = test_compile_buffer(context, XKB_KEYMAP_FORMAT_TEXT_V1, keymap_str, sizeof(keymap_str)); assert(keymap); xkb_mod_index_t shift = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); xkb_mod_index_t caps = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); struct xkb_state *state = xkb_state_new(keymap); assert(state); /* See xkb_state_key_get_one_sym() for what's this all about. */ assert(xkb_state_key_get_layout(state, KEY_A + EVDEV_OFFSET) == 0); assert(xkb_state_key_get_layout(state, KEY_SEMICOLON + EVDEV_OFFSET) == 0); /* Without caps, no transformation. */ assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_key_get_level(state, KEY_A + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET); assert(sym == XKB_KEY_a); assert(xkb_state_key_get_level(state, KEY_SEMICOLON + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + EVDEV_OFFSET); assert(sym == XKB_KEY_eacute); nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + EVDEV_OFFSET, &syms); assert(nsyms == 1 && syms[0] == XKB_KEY_eacute); assert(xkb_state_key_get_level(state, KEY_YEN + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_YEN + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_YEN + EVDEV_OFFSET, &syms); assert(nsyms == 2 && syms[0] == XKB_KEY_oe && syms[1] == XKB_KEY_ssharp); assert(xkb_state_key_get_level(state, KEY_RO + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_RO + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_RO + EVDEV_OFFSET, &syms); assert(nsyms == 2 && syms[0] == XKB_KEY_3 && syms[1] == XKB_KEY_ntilde); assert(xkb_state_key_get_level(state, KEY_RIGHTCTRL + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_RIGHTCTRL + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_RIGHTCTRL + EVDEV_OFFSET, &syms); assert(nsyms == 2 && syms[0] == XKB_KEY_Control_R && syms[1] == XKB_KEY_ISO_Next_Group); /* With shift, no transformation (only different level). */ xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) > 0); assert(xkb_state_key_get_level(state, KEY_A + EVDEV_OFFSET, 0) == 1); sym = xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET); assert(sym == XKB_KEY_A); sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + EVDEV_OFFSET); assert(sym == XKB_KEY_odiaeresis); nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + EVDEV_OFFSET, &syms); assert(nsyms == 1 && syms[0] == XKB_KEY_odiaeresis); assert(xkb_state_key_get_level(state, KEY_YEN + EVDEV_OFFSET, 0) == 1); sym = xkb_state_key_get_one_sym(state, KEY_YEN + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_YEN + EVDEV_OFFSET, &syms); assert(nsyms == 3 && syms[0] == XKB_KEY_ae && syms[1] == XKB_KEY_s && syms[2] == XKB_KEY_s); assert(xkb_state_key_get_level(state, KEY_RO + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_RO + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_RO + EVDEV_OFFSET, &syms); assert(nsyms == 2 && syms[0] == XKB_KEY_3 && syms[1] == XKB_KEY_ntilde); assert(xkb_state_key_get_level(state, KEY_RIGHTCTRL + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_RIGHTCTRL + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_RIGHTCTRL + EVDEV_OFFSET, &syms); assert(nsyms == 2 && syms[0] == XKB_KEY_Control_R && syms[1] == XKB_KEY_ISO_Next_Group); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); /* With caps, transform in same level. */ xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); assert(xkb_state_key_get_level(state, KEY_A + EVDEV_OFFSET, 0) == 1); sym = xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET); assert(sym == XKB_KEY_A); assert(xkb_state_key_get_level(state, KEY_SEMICOLON + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_SEMICOLON + EVDEV_OFFSET); assert(sym == XKB_KEY_Eacute); nsyms = xkb_state_key_get_syms(state, KEY_SEMICOLON + EVDEV_OFFSET, &syms); assert(nsyms == 1 && syms[0] == XKB_KEY_Eacute); assert(xkb_state_key_get_level(state, KEY_YEN + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_YEN + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_YEN + EVDEV_OFFSET, &syms); assert(nsyms == 2 && syms[0] == XKB_KEY_OE && syms[1] == XKB_KEY_Ssharp); assert(xkb_state_key_get_level(state, KEY_RO + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_RO + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_RO + EVDEV_OFFSET, &syms); assert(nsyms == 2 && syms[0] == XKB_KEY_3 && syms[1] == XKB_KEY_Ntilde); assert(xkb_state_key_get_level(state, KEY_RIGHTCTRL + EVDEV_OFFSET, 0) == 0); sym = xkb_state_key_get_one_sym(state, KEY_RIGHTCTRL + EVDEV_OFFSET); assert(sym == XKB_KEY_NoSymbol); nsyms = xkb_state_key_get_syms(state, KEY_RIGHTCTRL + EVDEV_OFFSET, &syms); assert(nsyms == 2 && syms[0] == XKB_KEY_Control_R && syms[1] == XKB_KEY_ISO_Next_Group); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_mod_index_is_active(state, shift, XKB_STATE_MODS_EFFECTIVE) == 0); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); xkb_state_unref(state); xkb_keymap_unref(keymap); } static void test_get_utf8_utf32(struct xkb_keymap *keymap) { char buf[256]; struct xkb_state *state = xkb_state_new(keymap); assert(state); #define TEST_KEY(key, expected_utf8, expected_utf32) do { \ assert(xkb_state_key_get_utf8(state, (key) + EVDEV_OFFSET, NULL, 0) == strlen(expected_utf8)); \ assert(xkb_state_key_get_utf8(state, (key) + EVDEV_OFFSET, buf, sizeof(buf)) == strlen(expected_utf8)); \ assert(memcmp(buf, expected_utf8, sizeof(expected_utf8)) == 0); \ assert(xkb_state_key_get_utf32(state, (key) + EVDEV_OFFSET) == (expected_utf32)); \ } while (0) /* Simple ASCII. */ TEST_KEY(KEY_A, "a", 0x61); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "1", 0x31); /* Invalid. */ TEST_KEY(XKB_KEYCODE_INVALID - 8, "", 0); TEST_KEY(300, "", 0); /* No string. */ TEST_KEY(KEY_LEFTCTRL, "", 0); TEST_KEY(KEY_NUMLOCK, "", 0); /* Multiple keysyms. */ TEST_KEY(KEY_6, "HELLO", 0); TEST_KEY(KEY_7, "YES THIS IS DOG", 0); /* Check truncation. */ memset(buf, 'X', sizeof(buf)); assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 0) == strlen("HELLO")); assert(memcmp(buf, "X", 1) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 1) == strlen("HELLO")); assert(memcmp(buf, "", 1) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 2) == strlen("HELLO")); assert(memcmp(buf, "H", 2) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 3) == strlen("HELLO")); assert(memcmp(buf, "HE", 3) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 5) == strlen("HELLO")); assert(memcmp(buf, "HELL", 5) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 6) == strlen("HELLO")); assert(memcmp(buf, "HELLO", 6) == 0); assert(xkb_state_key_get_utf8(state, KEY_6 + EVDEV_OFFSET, buf, 7) == strlen("HELLO")); assert(memcmp(buf, "HELLO\0X", 7) == 0); /* Switch to ru layout */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_key_get_layout(state, KEY_A + EVDEV_OFFSET) == 1); /* Non ASCII. */ TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_A, "ф", 0x0444); TEST_KEY(KEY_Z, "я", 0x044F); /* Switch back to us layout */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_key_get_layout(state, KEY_A + EVDEV_OFFSET) == 0); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); TEST_KEY(KEY_A, "A", 0x41); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "!", 0x21); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); TEST_KEY(KEY_6, "HELLO", 0); TEST_KEY(KEY_7, "YES THIS IS DOG", 0); xkb_state_unref(state); } static void test_ctrl_string_transformation(struct xkb_keymap *keymap) { char buf[256]; xkb_mod_index_t ctrl = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); struct xkb_state *state = xkb_state_new(keymap); assert(state); /* See xkb_state_key_get_utf8() for what's this all about. */ /* First without. */ TEST_KEY(KEY_A, "a", 0x61); TEST_KEY(KEY_B, "b", 0x62); TEST_KEY(KEY_C, "c", 0x63); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "1", 0x31); /* And with. */ xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0); TEST_KEY(KEY_A, "\x01", 0x01); TEST_KEY(KEY_B, "\x02", 0x02); TEST_KEY(KEY_C, "\x03", 0x03); TEST_KEY(KEY_ESC, "\x1B", 0x1B); TEST_KEY(KEY_1, "1", 0x31); xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_UP); /* Switch to ru layout */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_key_get_layout(state, KEY_A + EVDEV_OFFSET) == 1); /* Non ASCII. */ xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0); TEST_KEY(KEY_A, "\x01", 0x01); TEST_KEY(KEY_B, "\x02", 0x02); xkb_state_update_key(state, KEY_RIGHTCTRL + EVDEV_OFFSET, XKB_KEY_UP); xkb_state_unref(state); } static bool test_active_leds(struct xkb_state *state, xkb_led_mask_t leds_expected) { struct xkb_keymap *keymap = xkb_state_get_keymap(state); bool ret = true; xkb_led_mask_t leds_got = 0; for (xkb_led_index_t led = 0; led < xkb_keymap_num_leds(keymap); led++) { const int status = xkb_state_led_index_is_active(state, led); if (status < 0) continue; const xkb_led_mask_t mask = (UINT32_C(1) << led); const bool expected = !!(leds_expected & mask); if (status) leds_got |= mask; if (!!status ^ expected) { fprintf(stderr, "ERROR: LED \"%s\" status: expected %d, got %d\n", xkb_keymap_led_get_name(keymap, led), expected, !!status); ret = false; } } if (!ret) { fprintf(stderr, "ERROR: LEDs: expected 0x%x, got 0x%x\n", leds_expected, leds_got); } return ret; } static void test_leds(struct xkb_context *ctx) { const char buf[] = "xkb_keymap {\n" " xkb_keycodes { include \"evdev\" };\n" " xkb_types { include \"basic\" };\n" " xkb_compat {\n" " include \"leds(groups)\"\n" " interpret ISO_Group_Shift { action= SetGroup(group=+1); };\n" " interpret ISO_Group_Latch { action= LatchGroup(group=+1); };\n" " interpret ISO_Group_Lock { action= LockGroup(group=+1); };\n" " };\n" " xkb_symbols {\n" " key { [ q, Q ], [w, W], [e, E] };\n" " key { [ ISO_Group_Shift ] };\n" " key { [ ISO_Group_Latch ] };\n" " key { [ ISO_Group_Lock ] };\n" " };\n" "};"; struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, buf, ARRAY_SIZE(buf)); assert(keymap); const xkb_led_index_t caps_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_CAPS); const xkb_led_index_t num_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_NUM); const xkb_led_index_t scroll_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_SCROLL); const xkb_led_index_t compose_idx = _xkb_keymap_led_get_index(keymap, XKB_LED_NAME_COMPOSE); const xkb_led_index_t sleep_idx = _xkb_keymap_led_get_index(keymap, "Sleep"); const xkb_led_index_t mute_idx = _xkb_keymap_led_get_index(keymap, "Mute"); const xkb_led_index_t misc_idx = _xkb_keymap_led_get_index(keymap, "Misc"); const xkb_led_index_t mail_idx = _xkb_keymap_led_get_index(keymap, "Mail"); const xkb_led_index_t charging_idx = _xkb_keymap_led_get_index(keymap, "Charging"); const xkb_led_mask_t caps = UINT32_C(1) << caps_idx; const xkb_led_mask_t num = UINT32_C(1) << num_idx; const xkb_led_mask_t scroll = UINT32_C(1) << scroll_idx; const xkb_led_mask_t compose = UINT32_C(1) << compose_idx; const xkb_led_mask_t sleep = UINT32_C(1) << sleep_idx; const xkb_led_mask_t mute = UINT32_C(1) << mute_idx; const xkb_led_mask_t misc = UINT32_C(1) << misc_idx; const xkb_led_mask_t mail = UINT32_C(1) << mail_idx; const xkb_led_mask_t charging = UINT32_C(1) << charging_idx; struct xkb_state *state = xkb_state_new(keymap); assert(state); xkb_state_update_key(state, KEY_Q + EVDEV_OFFSET, XKB_KEY_UP); assert(test_active_leds(state, (caps | scroll))); /* SetGroup */ xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x1); assert(test_active_leds(state, (num | scroll | mute | misc))); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); /* LatchGroup */ xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_COMPOSE + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x1); assert(test_active_leds(state, (caps | compose | mute | misc | charging))); xkb_state_update_key(state, KEY_Q + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_Q + EVDEV_OFFSET, XKB_KEY_UP); /* LockGroup 2 */ xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x1); assert(test_active_leds(state, (caps | scroll | sleep | mute | mail))); /* LockGroup 2 + SetGroup */ xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x2); assert(test_active_leds(state, (num | scroll | sleep | mute | misc | mail | charging))); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); /* LockGroup 3 */ xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_DOWN); xkb_state_update_key(state, KEY_CAPSLOCK + EVDEV_OFFSET, XKB_KEY_UP); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x2); assert(test_active_leds(state, (caps | scroll | sleep | mute | charging))); /* LockGroup 3 + SetGroup */ xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0x0); assert(test_active_leds(state, (num | scroll | sleep | misc | charging))); xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_UP); xkb_state_unref(state); xkb_keymap_unref(keymap); } static void test_multiple_actions(struct xkb_context *ctx) { /* Check that we can trigger 2 actions on the same levels, with both * explicit (defined via the key statement) and explicit (defined via * interpret). The actions set the Control modifier and may change the * group. The idea is to enable keyboard shortcuts to always target the * same layout. Because SetGroup() does not work well with absolute values, * we define the modifiers on each 2 groups. */ const char keymap_str[] = "xkb_keymap {\n" " xkb_keycodes {\n" " = 24;\n" " = 37;\n" " = 105;\n" " };\n" " xkb_compat {\n" /* Right Control has its actions set implicitly via interpret */ " interpret 1 {\n" " action = {SetMods(modifiers=Control)};\n" " };\n" " interpret 2 {\n" " action = {SetMods(modifiers=Control), SetGroup(group=-1)};\n" " };\n" " interpret 3 {\n" " action = {SetMods(modifiers=Control), SetGroup(group=-2)};\n" " };\n" " interpret 4 {\n" " action = {SetMods(modifiers=Control), SetGroup(group=-3)};\n" " };\n" " };\n" " xkb_symbols {\n" " key { [q], [Arabic_dad], [c_h], [Thai_maiyamok] };\n" /* Left Control has its actions set explicitly */ " key {\n" " symbols[1] = [Control_L],\n" " actions[1] = [{SetMods(modifiers=Control)}],\n" " actions[2] = [{SetMods(modifiers=Control), SetGroup(group=-1)}],\n" " actions[3] = [{SetMods(modifiers=Control), SetGroup(group=-2)}],\n" " actions[4] = [{SetMods(modifiers=Control), SetGroup(group=-3)}]\n" " };\n" " key { [1], [2], [3], [4] };\n" " };\n" "};"; struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymap_str, sizeof(keymap_str)); assert(keymap); struct xkb_state *state = xkb_state_new(keymap); assert(state); const xkb_mod_index_t ctrl_idx = _xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CTRL); const xkb_mod_mask_t ctrl = UINT32_C(1) << ctrl_idx; const xkb_keycode_t lcontrol = KEY_LEFTCTRL + EVDEV_OFFSET; const xkb_keycode_t rcontrol = KEY_RIGHTCTRL + EVDEV_OFFSET; const xkb_keycode_t q = KEY_Q + EVDEV_OFFSET; xkb_mod_mask_t mods; const xkb_keycode_t mod_keys[] = {lcontrol, rcontrol}; const xkb_keysym_t ad01[] = { XKB_KEY_q, XKB_KEY_Arabic_dad, XKB_KEY_c_h, XKB_KEY_Thai_maiyamok }; for (xkb_layout_index_t layout = 0; layout < ARRAY_SIZE(ad01); layout++) { /* Lock layout */ xkb_state_update_mask(state, 0, 0, 0, 0, 0, layout); assert(xkb_state_key_get_layout(state, q) == layout); assert(xkb_state_key_get_one_sym(state, q) == ad01[layout]); for (unsigned int k = 0; k < ARRAY_SIZE(mod_keys); k++) { /* Temporarily switch to first layout + set Control modifier */ xkb_state_update_key(state, mod_keys[k], XKB_KEY_DOWN); assert(xkb_state_key_get_layout(state, q) == 0); mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); assert(mods == ctrl); assert(xkb_state_key_get_one_sym(state, q) == XKB_KEY_q); /* Restore layout, unset Control */ xkb_state_update_key(state, mod_keys[k], XKB_KEY_UP); assert(xkb_state_key_get_layout(state, q) == layout); mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); assert(mods == 0); assert(xkb_state_key_get_one_sym(state, q) == ad01[layout]); } } xkb_state_unref(state); xkb_keymap_unref(keymap); } static void test_void_action(struct xkb_context *ctx) { const char keymap_str[] = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { key <> { [VoidAction()], [VoidAction()] }; };\n" "};"; struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymap_str, sizeof(keymap_str)); assert(keymap); struct xkb_state *state = xkb_state_new(keymap); assert(state); xkb_state_update_latched_locked(state, 0x1, 0x1, true, 1, 0, 0, false, 0); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 1); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0x1); xkb_state_update_key(state, 1, XKB_KEY_DOWN); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0); xkb_state_unref(state); xkb_keymap_unref(keymap); } static void test_extended_layout_indices(struct xkb_context *ctx) { const char keymap_str[] = "xkb_keymap \"extended-layout-indices\" {\n" " xkb_keycodes {\n" " <> = 1;\n" " = 10;\n" " = 11;\n" " = 12;\n" " = 20;\n" " = 21;\n" " = 22;\n" " = 30;\n" " = 31;\n" " = 32;\n" " };\n" " xkb_types { type \"ONE_LEVEL\" {}; };\n" " xkb_symbols {\n" " key <> {\n" " [a], [b], [c], [d], [e], [f], [g], [h], [i], [j],\n" " [k], [l], [m], [n], [o], [p], [q], [r], [s], [t],\n" " [u], [v], [w], [x], [y], [z], [1], [2], [3], [4],\n" " [5], [6]\n" " };\n" " key { [ISO_Group_Shift], [SetGroup(group=-1)] };\n" " key { [ISO_Group_Shift], [SetGroup(group=+1)] };\n" " key { [ISO_Group_Shift], [SetGroup(group=32)] };\n" " key { [ISO_Group_Latch], [LatchGroup(group=-1)] };\n" " key { [ISO_Group_Latch], [LatchGroup(group=+1)] };\n" " key { [ISO_Group_Latch], [LatchGroup(group=32)] };\n" " key { [ISO_Group_Lock], [LockGroup(group=-1)] };\n" " key { [ISO_Group_Lock], [LockGroup(group=+1)] };\n" " key { [ISO_Group_Lock], [LockGroup(group=32)] };\n" " };\n" "};"; struct xkb_keymap *keymap = test_compile_buffer( ctx, XKB_KEYMAP_FORMAT_TEXT_V2, keymap_str, sizeof(keymap_str) ); assert(keymap); const int32_t num_layouts = (int32_t) xkb_keymap_num_layouts(keymap); assert(num_layouts == XKB_MAX_GROUPS); struct xkb_state *state = xkb_state_new(keymap); assert(state); for (int32_t l = -num_layouts - 1; l < num_layouts + 1; l++) { const xkb_layout_index_t expected_layout = (xkb_layout_index_t) group_wrap(l, num_layouts); /* Out-of-bounds latches update */ enum xkb_state_component expected_changes = (XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_EFFECTIVE) | ((l == 0) ? 0 : XKB_STATE_LAYOUT_LATCHED) | ((expected_layout == 0) ? 0 : XKB_STATE_LAYOUT_EFFECTIVE); enum xkb_state_component got_changes = xkb_state_update_latched_locked( state, 0x1, 0x1, true, l, 0, 0, false, 0 ); assert(got_changes == expected_changes); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED) == (xkb_layout_index_t) l); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == expected_layout); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0x1); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0x1); /* Break latches by key press */ got_changes = xkb_state_update_key(state, 1, XKB_KEY_DOWN); assert(got_changes == expected_changes); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED) == 0); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0); /* Check key release changes nothing */ assert(xkb_state_update_key(state, 1, XKB_KEY_UP) == 0); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LATCHED) == 0); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED) == 0); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0); /* Out-of-bounds locks update */ got_changes = xkb_state_update_latched_locked( state, 0, 0, false, 0, 0x2, 0x2, true, l ); expected_changes = (XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE) | ((expected_layout == 0) ? 0 : (XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE)); assert(got_changes == expected_changes); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED) == expected_layout); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == expected_layout); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == 0x2); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0x2); /* Out-of-bounds locks reset */ assert(got_changes == xkb_state_update_latched_locked( state, 0, 0, false, 0, 0x2, 0, true, 0 )); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED) == 0); assert(xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE) == 0); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED) == 0); assert(xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE) == 0); } const xkb_layout_index_t last_layout = (xkb_layout_index_t) num_layouts - 1; const struct test_state_components tests[] = { /* * Set */ { KEY_ENTRY(10 - EVDEV_OFFSET, DOWN, XKB_KEY_ISO_Group_Shift), .base_group=-1, .group=last_layout, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE }, { KEY_ENTRY(1 - EVDEV_OFFSET, BOTH, XKB_KEY_6), .base_group=-1, .group=last_layout, .changes = 0 }, { KEY_ENTRY(10 - EVDEV_OFFSET, UP, XKB_KEY_ISO_Group_Shift), .base_group=0, .group=0, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE }, { KEY_ENTRY(12 - EVDEV_OFFSET, DOWN, XKB_KEY_ISO_Group_Shift), .base_group=num_layouts - 1, .group=last_layout, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE }, { KEY_ENTRY(11 - EVDEV_OFFSET, DOWN, XKB_KEY_ISO_Group_Shift), .base_group=num_layouts, .group=0, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE }, { KEY_ENTRY(11 - EVDEV_OFFSET, UP, XKB_KEY_ISO_Group_Shift), .base_group=num_layouts - 1, .group=last_layout, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE }, { KEY_ENTRY(12 - EVDEV_OFFSET, UP, XKB_KEY_ISO_Group_Shift), .base_group=0, .group=0, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_EFFECTIVE }, /* * Lock */ { KEY_ENTRY(30 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Lock), .locked_group=num_layouts - 1, .group=last_layout, .changes = 0 }, { KEY_ENTRY(31 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Lock), .locked_group=0, .group=0, .changes = 0 }, { KEY_ENTRY(32 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Lock), .locked_group=num_layouts-1, .group=last_layout, .changes = 0 }, /* * Latch */ { KEY_ENTRY(21 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Latch), .latched_group=1, .locked_group=num_layouts-1, .group=0, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED }, { KEY_ENTRY(1 - EVDEV_OFFSET, BOTH, XKB_KEY_a), .latched_group=0, .locked_group=num_layouts-1, .group=0, .changes = 0 }, { KEY_ENTRY(31 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Lock), .locked_group=0, .group=0, .changes = 0 }, { KEY_ENTRY(20 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Latch), .latched_group=-1, .group=last_layout, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED }, { KEY_ENTRY(1 - EVDEV_OFFSET, BOTH, XKB_KEY_6), .latched_group=0, .group=0, .changes = 0 }, { KEY_ENTRY(22 - EVDEV_OFFSET, BOTH, XKB_KEY_ISO_Group_Latch), .latched_group=num_layouts-1, .group=last_layout, .changes = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED }, { KEY_ENTRY(1 - EVDEV_OFFSET, BOTH, XKB_KEY_6), .latched_group=0, .group=0, .changes = 0 }, }; struct xkb_state *expected_state = xkb_state_new(keymap); assert(expected_state); for (size_t k = 0; k < ARRAY_SIZE(tests); k++) { assert_printf( run_state_update(keymap, &tests[k], &expected_state, &state), "%s #%zu: type: %d\n", __func__, k, tests[k].input_type ); } xkb_state_unref(state); xkb_state_unref(expected_state); xkb_keymap_unref(keymap); } int main(void) { test_init(); struct xkb_context *context = test_get_context(CONTEXT_NO_FLAG); struct xkb_keymap *keymap; assert(context); /* Make sure these are allowed. */ xkb_context_unref(NULL); xkb_keymap_unref(NULL); xkb_state_unref(NULL); test_group_wrap(context); const char* rules[] = {"evdev", "evdev-pure-virtual-mods"}; for (size_t r = 0; r < ARRAY_SIZE(rules); r++) { fprintf(stderr, "=== Rules set: %s ===\n", rules[r]); keymap = test_compile_rules(context, XKB_KEYMAP_FORMAT_TEXT_V1, rules[r], "pc104", "us,ru", NULL, "grp:menu_toggle,grp:lwin_latch," "grp:rwin_latch_lock_clear," "grp:sclk_latch_no_lock," "lv3:lsgt_latch,lv3:bksl_latch_no_lock"); assert(keymap); const bool pure_vmods = !!r; test_update_key(keymap, pure_vmods); test_update_latched_locked(keymap); test_serialisation(keymap, pure_vmods); test_update_mask_mods(keymap, pure_vmods); test_repeat(keymap); test_consume(keymap, pure_vmods); test_keycode_range(keymap); test_get_utf8_utf32(keymap); test_ctrl_string_transformation(keymap); xkb_keymap_unref(keymap); } test_inactive_key_type_entry(context); test_overlapping_mods(context); test_caps_keysym_transformation(context); test_leds(context); test_multiple_actions(context); test_void_action(context); test_extended_layout_indices(context); xkb_context_unref(context); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/stringcomp.c000066400000000000000000000265751510033435100222120ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "test.h" #include "test/utils-text.h" #include "utils.h" #include "keymap-compare.h" static void test_keymap_comparison(struct xkb_context *ctx) { static const struct { const char* keymap1; const char* keymap2; enum xkb_keymap_compare_property properties; bool same; } tests[] = { { .keymap1 = "xkb_keymap {};", .keymap2 = "xkb_keymap {};", .properties = XKB_KEYMAP_CMP_ALL, .same = true }, { .keymap1 = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" "};", .keymap2 = "xkb_keymap {};", .properties = XKB_KEYMAP_CMP_ALL, .same = false }, { .keymap1 = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " = 2;\n" " };\n" " xkb_compat { include \"caps\" };\n" " xkb_types { include \"basic+iso9995\" };\n" " xkb_symbols {\n" " key { [a, A] };\n" " key { [Caps_Lock] };\n" /* implicit action */ " };\n" "};", .keymap2 = "xkb_keymap {\n" " xkb_keycodes {\n" " = 1;\n" " = 2;\n" " };\n" " xkb_compat {};\n" /* empty */ " xkb_types { include \"basic\" };\n" /* less types */ " xkb_symbols {\n" /* Change key order + explicit actions and types */ " key {\n" " [Caps_Lock],\n" " [LockMods(modifiers = Lock)],\n" " type=\"ONE_LEVEL\"\n" " };\n" " key { [a, A], type=\"ALPHABETIC\" };\n" /* Definition in different section */ " virtual_modifiers LevelThree;\n" " };\n" "};", .properties = (XKB_KEYMAP_CMP_ALL & ~(XKB_KEYMAP_CMP_POSSIBLY_DROPPED)), .same = true }, }; for (size_t t = 0; t < ARRAY_SIZE(tests); t++) { fprintf(stderr, "------\n%s: #%zu\n", __func__, t); struct xkb_keymap * const keymap1 = test_compile_string( ctx, XKB_KEYMAP_FORMAT_TEXT_V1, tests[t].keymap1 ); assert(keymap1); struct xkb_keymap * const keymap2 = test_compile_string( ctx, XKB_KEYMAP_FORMAT_TEXT_V1, tests[t].keymap2 ); assert(keymap2); assert(xkb_keymap_compare(ctx, keymap1, keymap2, tests[t].properties) == tests[t].same); xkb_keymap_unref(keymap1); xkb_keymap_unref(keymap2); } } static void test_explicit_actions(struct xkb_context *ctx) { struct xkb_keymap *keymap; char *original = test_read_file("keymaps/explicit-actions.xkb"); assert(original); char *tmp = uncomment(original, strlen(original), "//"); assert(tmp); char *expected = strip_lines(tmp, strlen(tmp), "//"); free(tmp); assert(expected); char *got = NULL; /* Try original */ keymap = test_compile_string(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, original); free(original); assert(keymap); got = xkb_keymap_get_as_string2(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT, TEST_KEYMAP_SERIALIZE_FLAGS); xkb_keymap_unref(keymap); assert_streq_not_null("Check output from original", expected, got); free(got); /* Try round-trip */ keymap = test_compile_string(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, expected); assert(keymap); got = xkb_keymap_get_as_string2(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT, TEST_KEYMAP_SERIALIZE_FLAGS); xkb_keymap_unref(keymap); assert_streq_not_null("Check roundtrip", expected, got); free(got); free(expected); } static struct xkb_keymap* compile_string(struct xkb_context *context, enum xkb_keymap_format format, const char *buf, size_t len, void *private) { return test_compile_string(context, format, buf); } int main(int argc, char *argv[]) { test_init(); bool update_output_files = false; if (argc > 1) { if (streq(argv[1], "update")) { /* Update files with *obtained* results */ update_output_files = true; } else { fprintf(stderr, "ERROR: unsupported argument: \"%s\".\n", argv[1]); exit(EXIT_FAILURE); } } struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); struct xkb_keymap *keymap; char *dump, *dump2; assert(ctx); /* Make sure we can't (falsely claim to) compile an empty string. */ keymap = test_compile_string(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, ""); assert(!keymap); /* Load in a prebuilt keymap, make sure we can compile it from a string, * then compare it to make sure we get the same result when dumping it * to a string. */ static const struct { const char* path; enum xkb_keymap_format format; enum xkb_keymap_serialize_flags serialize_flags; } data[] = { { .path = "keymaps/stringcomp-v1.xkb", .format = XKB_KEYMAP_FORMAT_TEXT_V1, .serialize_flags = TEST_KEYMAP_SERIALIZE_FLAGS }, { .path = "keymaps/stringcomp-v1-no-prettyfied.xkb", .format = XKB_KEYMAP_FORMAT_TEXT_V1, .serialize_flags = TEST_KEYMAP_SERIALIZE_FLAGS & ~XKB_KEYMAP_SERIALIZE_PRETTY }, { .path = "keymaps/stringcomp-v1-no-flags.xkb", .format = XKB_KEYMAP_FORMAT_TEXT_V1, .serialize_flags = XKB_KEYMAP_SERIALIZE_NO_FLAGS }, { .path = "keymaps/stringcomp-v2.xkb", .format = XKB_KEYMAP_FORMAT_TEXT_V2, .serialize_flags = TEST_KEYMAP_SERIALIZE_FLAGS }, }; for (unsigned int k = 0; k < ARRAY_SIZE(data); k++) { fprintf(stderr, "------\nTest roundtrip of: %s\n", data[k].path); char *original = test_read_file(data[k].path); assert(original); /* Check round-trip with same serialize flags */ assert(test_compile_output2(ctx, data[k].format, XKB_KEYMAP_USE_ORIGINAL_FORMAT, data[k].serialize_flags, compile_string, NULL, "Round-trip with same serialize flags", original, 0 /* unused */, data[k].path, update_output_files)); /* * Check round-trip by dropping/keeping unused keymap items * We obviously cannot compare the serializations, so only keymap * objects are compared. */ keymap = xkb_keymap_new_from_string(ctx, original, data[k].format, XKB_KEYMAP_COMPILE_NO_FLAGS); assert(keymap); free(original); const enum xkb_keymap_serialize_flags test_serialize_flags[] = { (data[k].serialize_flags & ~XKB_KEYMAP_SERIALIZE_KEEP_UNUSED), (data[k].serialize_flags | XKB_KEYMAP_SERIALIZE_KEEP_UNUSED) }; for (size_t f = 0; f < ARRAY_SIZE(test_serialize_flags); f++) { original = xkb_keymap_get_as_string2(keymap, data[k].format, test_serialize_flags[f]); assert(original); struct xkb_keymap *keymap2 = xkb_keymap_new_from_string( ctx, original, data[k].format, XKB_KEYMAP_COMPILE_NO_FLAGS ); assert(keymap2); free(original); assert(xkb_keymap_compare(ctx, keymap, keymap2, (XKB_KEYMAP_CMP_ALL & ~(XKB_KEYMAP_CMP_POSSIBLY_DROPPED)))); xkb_keymap_unref(keymap2); } /* * Check pretty/no-pretty round-trip, i.e. check that changing the * pretty-print flags results in the same keymap, for both keymap * objects and serializations. */ const enum xkb_keymap_serialize_flags serialize_flags = (data[k].serialize_flags & XKB_KEYMAP_SERIALIZE_PRETTY) ? (data[k].serialize_flags & ~XKB_KEYMAP_SERIALIZE_PRETTY) : (data[k].serialize_flags | XKB_KEYMAP_SERIALIZE_PRETTY); original = xkb_keymap_get_as_string2(keymap, data[k].format, serialize_flags); assert(original); struct xkb_keymap *keymap2 = xkb_keymap_new_from_string( ctx, original, data[k].format, XKB_KEYMAP_COMPILE_NO_FLAGS ); assert(keymap2); assert(xkb_keymap_compare(ctx, keymap, keymap2, XKB_KEYMAP_CMP_ALL)); xkb_keymap_unref(keymap2); assert(test_compile_output2(ctx, data[k].format, XKB_KEYMAP_USE_ORIGINAL_FORMAT, data[k].serialize_flags, compile_string, NULL, "Round-trip with different serialize flags", original, 0 /* unused */, data[k].path, update_output_files)); free(original); xkb_keymap_unref(keymap); } /* Make sure we can recompile our output for a normal keymap from rules. */ keymap = test_compile_rules(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, NULL, NULL, "ru,ca,de,us", ",multix,neo,intl", NULL); assert(keymap); dump = xkb_keymap_get_as_string2(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT, TEST_KEYMAP_SERIALIZE_FLAGS); assert(dump); xkb_keymap_unref(keymap); keymap = test_compile_string(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, dump); assert(keymap); /* Now test that the dump of the dump is equal to the dump! */ dump2 = xkb_keymap_get_as_string2(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT, TEST_KEYMAP_SERIALIZE_FLAGS); assert(dump2); assert(streq(dump, dump2)); /* Test response to invalid formats and flags. */ assert(!xkb_keymap_new_from_string(ctx, dump, 0, 0)); assert(!xkb_keymap_new_from_string(ctx, dump, -1, 0)); assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_USE_ORIGINAL_FORMAT, 0)); assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V2+1, 0)); assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1, -1)); assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1, 1414)); assert(!xkb_keymap_get_as_string2(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT, -1)); assert(!xkb_keymap_get_as_string2(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT, 3333)); assert(!xkb_keymap_get_as_string2(keymap, 0, TEST_KEYMAP_SERIALIZE_FLAGS)); assert(!xkb_keymap_get_as_string2(keymap, 4893, TEST_KEYMAP_SERIALIZE_FLAGS)); xkb_keymap_unref(keymap); free(dump); free(dump2); test_keymap_comparison(ctx); test_explicit_actions(ctx); xkb_context_unref(ctx); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/symbols-leak-test.py000077500000000000000000000027411510033435100236020ustar00rootroot00000000000000#!/usr/bin/env python3 """Check that all exported symbols are specified in the symbol version scripts. If this fails, please update the appropriate .map file (adding new version nodes as needed). """ import os import pathlib import re import sys top_srcdir = pathlib.Path(os.environ["top_srcdir"]) def symbols_from_map(path): return re.findall(r"^\s+(xkb_.*);", path.read_text("utf-8"), re.MULTILINE) def symbols_from_src(path): return re.findall(r"\bXKB_EXPORT\b.*\n(xkb_.*)\(", path.read_text("utf-8")) def diff(map_path, src_paths): map_symbols = set(symbols_from_map(map_path)) src_symbols = set.union(set(), *(symbols_from_src(path) for path in src_paths)) return sorted(map_symbols - src_symbols), sorted(src_symbols - map_symbols) exit = 0 # xkbcommon symbols left, right = diff( top_srcdir / "xkbcommon.map", [ top_srcdir / "include/xkbcommon/xkbcommon.h", top_srcdir / "include/xkbcommon/xkbcommon-compose.h", ], ) if left: print("xkbcommon map has extra symbols:", " ".join(left)) exit = 1 if right: print("xkbcommon src has extra symbols:", " ".join(right)) exit = 1 # xkbcommon-x11 symbols left, right = diff( top_srcdir / "xkbcommon-x11.map", [ top_srcdir / "include/xkbcommon/xkbcommon-x11.h", ], ) if left: print("xkbcommon-x11 map has extra symbols:", " ".join(left)) exit = 1 if right: print("xkbcommon-x11 src has extra symbols:", " ".join(right)) exit = 1 sys.exit(exit) xkbcommon-libxkbcommon-54ee7ac/test/test-keysym.py000077500000000000000000000042311510033435100225150ustar00rootroot00000000000000#!/usr/bin/env python3 # # This script creates a custom layout, overriding the TDLE key with the first # argument given. import argparse import tempfile from pathlib import Path import subprocess import os import re import sys # Template to force our key to TLDE template = """ default xkb_symbols "basic" {{ include "us(basic)" replace key {{ [ {} ] }}; }}; """ parser = argparse.ArgumentParser( description="Tool to verify whether a keysym is resolved" ) parser.add_argument("keysym", type=str, help="XKB keysym") parser.add_argument( "--tool", type=str, nargs=1, default=["xkbcli", "compile-keymap"], help="Full path to the xkbcli-compile-keymap tool", ) args = parser.parse_args() with tempfile.TemporaryDirectory() as tmpdir: symfile = Path(tmpdir) / "symbols" / "keytest" symfile.parent.mkdir() with symfile.open(mode="w") as f: f.write(template.format(args.keysym)) try: cmd = [ *args.tool, "--layout", "keytest", ] env = os.environ.copy() env["XKB_CONFIG_EXTRA_PATH"] = tmpdir result = subprocess.run( cmd, env=env, capture_output=True, universal_newlines=True ) if result.returncode != 0: print("ERROR: Failed to compile:") print(result.stderr) sys.exit(1) # grep for TLDE actually being remapped for l in result.stdout.split("\n"): match = re.match(r"\s+key \\s+{\s+\[\s+(?P\w+)\s+\]\s+}", l) if match: if args.keysym == match.group("keysym"): sys.exit(0) elif match.group("keysym") == "NoSymbol": print("ERROR: key {} not resolved:".format(args.keysym), l) else: print("ERROR: key {} mapped to wrong key:".format(args.keysym), l) sys.exit(1) print(result.stdout) print("ERROR: above keymap is missing key mapping for {}".format(args.keysym)) sys.exit(1) except FileNotFoundError as err: print("ERROR: invalid or missing tool: {}".format(err)) sys.exit(1) xkbcommon-libxkbcommon-54ee7ac/test/test.h000066400000000000000000000123351510033435100207760ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #pragma once #include "config.h" #include #include /* Don't use compat names in internal code. */ #define _XKBCOMMON_COMPAT_H #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-compose.h" #include "src/messages-codes.h" #include "utils.h" /* Automake test exit code to signify SKIP (à la PASS, FAIL, etc). * See: https://www.gnu.org/software/automake/manual/html_node/Scripts_002dbased-Testsuites.html */ #define SKIP_TEST 77 #define TEST_SETUP_FAILURE 99 #define assert_printf(cond, ...) do { \ const bool __cond = (cond); \ if (!__cond) { \ fprintf(stderr, "Assertion failure: " __VA_ARGS__); \ assert(__cond); \ }} while (0) #define assert_streq_not_null(test_name, expected, got) \ assert_printf(streq_not_null(expected, got), \ test_name ". Expected \"%s\", got: \"%s\"\n", expected, got) #define assert_eq(test_name, expected, got, format, ...) \ assert_printf(expected == got, \ test_name ". Expected " format ", got: " format "\n", \ ##__VA_ARGS__, expected, got) #define TEST_KEYMAP_SERIALIZE_FLAGS \ (XKB_KEYMAP_SERIALIZE_PRETTY | XKB_KEYMAP_SERIALIZE_KEEP_UNUSED) void test_init(void); void print_detailed_state(struct xkb_state *state); /* The offset between KEY_* numbering, and keycodes in the XKB evdev * dataset. */ #define EVDEV_OFFSET 8 enum key_seq_state { DOWN, REPEAT, UP, BOTH, NEXT, FINISH, }; int test_key_seq(struct xkb_keymap *keymap, ...); int test_key_seq_va(struct xkb_keymap *keymap, va_list args); char * test_makedir(const char *parent, const char *path); char * test_maketempdir(const char *template); char * test_get_path(const char *path_rel); char * read_file(const char *path, FILE *file); char * test_read_file(const char *path_rel); enum test_context_flags { CONTEXT_NO_FLAG = 0, CONTEXT_ALLOW_ENVIRONMENT_NAMES = (1 << 0), }; struct xkb_context * test_get_context(enum test_context_flags flags); struct xkb_keymap * test_compile_file(struct xkb_context *context, enum xkb_keymap_format format, const char *path_rel); struct xkb_keymap * test_compile_string(struct xkb_context *context, enum xkb_keymap_format format, const char *string); struct xkb_keymap * test_compile_buffer(struct xkb_context *context, enum xkb_keymap_format format, const char *buf, size_t len); typedef struct xkb_keymap * (*test_compile_buffer_t)(struct xkb_context *context, enum xkb_keymap_format format, const char *buf, size_t len, void *private); bool test_compile_output(struct xkb_context *ctx, enum xkb_keymap_format input_format, enum xkb_keymap_format output_format, test_compile_buffer_t compile_buffer, void *compile_buffer_private, const char *test_title, const char *keymap_str, size_t keymap_len, const char *rel_path, bool update_output_files); bool test_compile_output2(struct xkb_context *ctx, enum xkb_keymap_format input_format, enum xkb_keymap_format output_format, enum xkb_keymap_serialize_flags serialize_flags, test_compile_buffer_t compile_buffer, void *compile_buffer_private, const char *test_title, const char *keymap_str, size_t keymap_len, const char *rel_path, bool update_output_files); typedef int (*test_third_party_compile_buffer_t)(const char *buf, size_t len, void *private, char **out, size_t *size_out); bool test_third_pary_compile_output(test_third_party_compile_buffer_t compile_buffer, void *compile_buffer_private, const char *test_title, const char *keymap_str, size_t keymap_len, const char *rel_path, bool update_output_files); struct xkb_keymap * test_compile_rmlvo(struct xkb_context *context, enum xkb_keymap_format format, const char *rules, const char *model, const char *layout, const char *variant, const char *options); struct xkb_keymap * test_compile_rules(struct xkb_context *context, enum xkb_keymap_format format, const char *rules, const char *model, const char *layout, const char *variant, const char *options); static inline void xkb_enable_quiet_logging(struct xkb_context *ctx) { xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); xkb_context_set_log_verbosity(ctx, XKB_LOG_VERBOSITY_MINIMAL); } #ifdef _WIN32 #define setenv(varname, value, overwrite) _putenv_s((varname), (value)) #define unsetenv(varname) _putenv_s(varname, "") #endif xkbcommon-libxkbcommon-54ee7ac/test/tool-option-parsing.py000077500000000000000000000606251510033435100241540ustar00rootroot00000000000000#!/usr/bin/env python3 # # Copyright © 2020 Red Hat, Inc. # SPDX-License-Identifier: MIT import concurrent.futures import itertools import logging import os import resource import subprocess import sys import tempfile import unittest from abc import ABCMeta, abstractmethod from collections.abc import Callable, Generator from dataclasses import dataclass from functools import reduce from pathlib import Path from typing import ClassVar try: top_builddir = Path(os.environ["top_builddir"]) top_srcdir = Path(os.environ["top_srcdir"]) except KeyError: print( "Required environment variables not found: top_srcdir/top_builddir", file=sys.stderr, ) top_srcdir = Path(".") try: top_builddir = next(Path(".").glob("**/meson-logs/")).parent except StopIteration: sys.exit(1) print( 'Using srcdir "{}", builddir "{}"'.format(top_srcdir, top_builddir), file=sys.stderr, ) TIMEOUT = 10.0 # seconds # Unset some environment variables, so that testing --enable-environment-names # does not actually depend on the current environment. for key in ( "XKB_DEFAULT_RULES", "XKB_DEFAULT_MODEL", "XKB_DEFAULT_LAYOUT", "XKB_DEFAULT_VARIANT", "XKB_DEFAULT_OPTIONS", ): if key in os.environ: del os.environ[key] # Ensure locale is C, so we can check error messages in English os.environ["LC_ALL"] = "C.UTF-8" logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger("test") logger.setLevel(logging.DEBUG) def powerset(iterable): "Subsequences of the iterable from shortest to longest." # powerset([1,2,3]) → () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3) s = tuple(iterable) return itertools.chain.from_iterable( itertools.combinations(s, r) for r in range(len(s) + 1) ) # Permutation of RMLVO that we use in multiple tests rmlvo_options = ( "--rules=evdev", "--model=pc104", "--layout=ch", "--options=eurosign:5", "--enable-environment-names", ) rmlvos = tuple( map( list, itertools.chain( itertools.permutations(rmlvo_options[:-1]), powerset(rmlvo_options), ), ) ) @dataclass class RMLVO: rules: str | None = None model: str | None = None layout: str | None = None variant: str | None = None options: str | None = None env: bool = False def __iter__(self) -> Generator[tuple[str, ...]]: if self.rules is not None: yield "--rules", self.rules if self.model is not None: yield "--model", self.model if self.layout is not None: yield "--layout", self.layout if self.variant is not None: yield "--variant", self.variant if self.options is not None: yield "--options", self.options if self.env: yield ("--enable-environment-names",) @property def args(self) -> list[str]: return list(itertools.chain.from_iterable(self)) class Target(metaclass=ABCMeta): @property @abstractmethod def args(self) -> list[str]: ... @property def stdin(self) -> str | None: return None class RmlvoTarget(Target): @property def args(self) -> list[str]: return ["--rmlvo"] class KccgstTarget(Target): @property def args(self) -> list[str]: return ["--kccgst"] class KccgstYamlTarget(Target): @property def args(self) -> list[str]: return ["--kccgst-yaml"] @dataclass class KeymapTarget(Target, RMLVO): arg: bool = False path: Path | None = None stdin: str | None = None def _args(self) -> Generator[str]: yield from itertools.chain.from_iterable(self) if self.arg: yield "--keymap" if self.path: yield str(self.path) @property def args(self) -> list[str]: return list(self._args()) @property def use_rmlvo(self) -> bool: return ( not self.arg and not self.path and ( bool(self.rules) or bool(self.model) or bool(self.layout) or bool(self.variant) or bool(self.options) or bool(self.env) or not self.stdin ) ) def _disable_coredump(): resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) def run_command(args, input: str | None = None) -> tuple[int, str, str]: logger.debug("run command: {}".format(" ".join(args))) try: p = subprocess.run( args, preexec_fn=_disable_coredump, capture_output=True, input=input, text=True, timeout=0.7, ) return p.returncode, p.stdout, p.stderr except subprocess.TimeoutExpired as e: return ( 0, e.stdout.decode("utf-8") if e.stdout else "", e.stderr.decode("utf-8") if e.stderr else "", ) @dataclass class XkbcliTool: xkbcli_tool: ClassVar[str] = "xkbcli" tool_path: ClassVar[Path] = top_builddir subtool: str | None = None skipIf: tuple[tuple[bool, str], ...] = () skipError: tuple[tuple[Callable[[int, str, str], bool], str], ...] = () def run_command(self, args, input: str | None = None) -> tuple[int, str, str]: for condition, reason in self.skipIf: if condition: raise unittest.SkipTest(reason) if self.subtool is not None: tool = "{}-{}".format(self.xkbcli_tool, self.subtool) else: tool = self.xkbcli_tool args = [os.path.join(self.tool_path, tool)] + args return run_command(args, input=input) def run_command_success(self, args, input: str | None = None) -> tuple[str, str]: rc, stdout, stderr = self.run_command(args, input=input) if rc != 0: for testfunc, reason in self.skipError: if testfunc(rc, stdout, stderr): raise unittest.SkipTest(reason) assert rc == 0, (rc, stdout, stderr) return stdout, stderr def run_command_invalid( self, args, input: str | None = None ) -> tuple[int, str, str]: rc, stdout, stderr = self.run_command(args, input=input) assert rc == 2, (rc, stdout, stderr) return rc, stdout, stderr def run_command_unrecognized_option(self, args): rc, stdout, stderr = self.run_command(args) assert rc == 2, (rc, stdout, stderr) assert stdout.startswith("Usage") or stdout == "" assert "unrecognized option" in stderr def run_command_missing_arg(self, args): rc, stdout, stderr = self.run_command(args) assert rc == 2, (rc, stdout, stderr) assert stdout.startswith("Usage") or stdout == "" assert "requires an argument" in stderr def __str__(self): return str(self.subtool) class TestXkbcli(unittest.TestCase): xkbcli: ClassVar[XkbcliTool] xkbcli_list: ClassVar[XkbcliTool] xkbcli_how_to_type: ClassVar[XkbcliTool] xkbcli_compile_keymap: ClassVar[XkbcliTool] xkbcli_compile_compose: ClassVar[XkbcliTool] xkbcli_interactive_evdev: ClassVar[XkbcliTool] xkbcli_interactive_x11: ClassVar[XkbcliTool] xkbcli_interactive_wayland: ClassVar[XkbcliTool] xkbcli_interactive: ClassVar[XkbcliTool] xkbcli_dump_keymap_x11: ClassVar[XkbcliTool] xkbcli_dump_keymap_wayland: ClassVar[XkbcliTool] xkbcli_dump_keymap: ClassVar[XkbcliTool] all_tools: ClassVar[list[XkbcliTool]] @classmethod def setUpClass(cls): cls.xkbcli = XkbcliTool() cls.xkbcli_list = XkbcliTool( "list", skipIf=( ( not int(os.getenv("HAVE_XKBCLI_LIST", "1")), "xkbregistory not enabled", ), ), ) cls.xkbcli_how_to_type = XkbcliTool("how-to-type") cls.xkbcli_compile_keymap = XkbcliTool("compile-keymap") cls.xkbcli_compile_compose = XkbcliTool("compile-compose") no_interactive_evdev = ( ( not int(os.getenv("HAVE_XKBCLI_INTERACTIVE_EVDEV", "1")), "evdev not enabled", ), (not os.path.exists("/dev/input/event0"), "event node required"), ( not os.access("/dev/input/event0", os.R_OK), "insufficient permissions", ), ) cls.xkbcli_interactive_evdev = XkbcliTool( "interactive-evdev", skipIf=no_interactive_evdev, skipError=( ( lambda rc, stdout, stderr: "Couldn't find any keyboards" in stderr, "No keyboards available", ), ), ) no_interactive_x11 = ( ( not int(os.getenv("HAVE_XKBCLI_INTERACTIVE_X11", "1")), "x11 not enabled", ), (not os.getenv("DISPLAY"), "DISPLAY not set"), ) cls.xkbcli_interactive_x11 = XkbcliTool( "interactive-x11", skipIf=no_interactive_x11, ) no_interactive_wayland = ( ( not int(os.getenv("HAVE_XKBCLI_INTERACTIVE_WAYLAND", "1")), "wayland not enabled", ), (not os.getenv("WAYLAND_DISPLAY"), "WAYLAND_DISPLAY not set"), ) cls.xkbcli_interactive_wayland = XkbcliTool( "interactive-wayland", skipIf=no_interactive_wayland, ) # NOTE: `interactive` cannot be tested, because it hardcodes the paths # of the `xkbcli-interactive-{wayland,x11}` tools it calls to the # *install* directory, while we need to use those of the *build* # directory. cls.xkbcli_dump_keymap_x11 = XkbcliTool( "dump-keymap-x11", skipIf=no_interactive_x11, ) cls.xkbcli_dump_keymap_wayland = XkbcliTool( "dump-keymap-wayland", skipIf=no_interactive_wayland, ) # NOTE: `dump-keymap` cannot be tested, because it hardcodes the paths # of the `xkbcli-dump-keymap-{wayland,x11}` tools it calls to the # *install* directory, while we need to use those of the *build* # directory. cls.all_tools = [ cls.xkbcli, cls.xkbcli_list, cls.xkbcli_how_to_type, cls.xkbcli_compile_keymap, cls.xkbcli_compile_compose, cls.xkbcli_interactive_evdev, cls.xkbcli_interactive_x11, cls.xkbcli_interactive_wayland, cls.xkbcli_dump_keymap_x11, cls.xkbcli_dump_keymap_wayland, ] def test_help(self): # --help is supported by all tools for tool in self.all_tools: with self.subTest(tool=tool): stdout, stderr = tool.run_command_success(["--help"]) assert stdout.startswith("Usage:") assert stderr == "" def test_invalid_option(self): # --foobar generates "Usage:" for all tools for tool in self.all_tools: with self.subTest(tool=tool): tool.run_command_unrecognized_option(["--foobar"]) def test_xkbcli_version(self): # xkbcli --version stdout, stderr = self.xkbcli.run_command_success(["--version"]) assert stdout.startswith("1") assert stderr == "" def test_xkbcli_too_many_args(self): self.xkbcli.run_command_invalid(["a"] * 64) def test_compile_keymap_args(self): xkb_root = Path(os.environ["XKB_CONFIG_ROOT"]) keymap_path = xkb_root / "keymaps/masks.xkb" keymap_string = keymap_path.read_text(encoding="utf-8") test_option = "--test" target: Target for target in ( RmlvoTarget(), KccgstTarget(), KccgstYamlTarget(), # Keymap from RMLVO KeymapTarget(), # Keymap from RMLVO (stdin ignored) KeymapTarget(layout="us", stdin=keymap_string), KeymapTarget(env=True, stdin=keymap_string), # Keymap parsed from keymap file KeymapTarget(arg=False, path=keymap_path), KeymapTarget(arg=True, path=keymap_path), # Keymap parsed from stdin KeymapTarget(arg=False, stdin=keymap_string), KeymapTarget(arg=True, stdin=keymap_string), ): for options in powerset(("--verbose", test_option)): args = list(options) + target.args with self.subTest(args=args): stdout, stderr = self.xkbcli_compile_keymap.run_command_success( args, input=target.stdin ) if test_option in options: # Expect no output assert stdout == "", (target, stdout) if isinstance(target, KeymapTarget) and test_option not in options: # Check keymap output for excepted bits: # - is not defined in mask.xkb # - virtual_modifiers Test01 is only defined in masks.xkb assert ("" in stdout) ^ (not target.use_rmlvo), ( target, stdout, stderr, ) assert ("virtual_modifiers Test01" in stdout) ^ ( target.use_rmlvo ), (target, stdout, stderr) def test_compile_keymap_mutually_exclusive_args(self): xkb_root = Path(os.environ["XKB_CONFIG_ROOT"]) keymap_path = xkb_root / "keymaps/basic.xkb" keymap_string = keymap_path.read_text(encoding="utf-8") keymap_from_stdin = KeymapTarget(arg=True, stdin=keymap_string) keymap_from_path1 = KeymapTarget(arg=True, path=Path(keymap_path)) keymap_from_path2 = KeymapTarget(arg=False, path=Path(keymap_path)) rmlvo = RmlvoTarget() kccgst = KccgstTarget() kccgstYaml = KccgstYamlTarget() for entry in ( # --keymap does not use RMLVO options ("--rules", "some-rules", keymap_from_stdin), ("--model", "some-model", keymap_from_stdin), ("--layout", "some-layout", keymap_from_stdin), ("--variant", "some-variant", keymap_from_stdin), ("--options", "some-option", keymap_from_stdin), ("--rules", "some-rules", keymap_from_path1), ("--model", "some-model", keymap_from_path1), ("--layout", "some-layout", keymap_from_path1), ("--variant", "some-variant", keymap_from_path1), ("--options", "some-option", keymap_from_path1), # Trailing keymap file with RMLVO options ("--rules", "some-rules", keymap_from_path2), ("--model", "some-model", keymap_from_path2), ("--layout", "some-layout", keymap_from_path2), ("--variant", "some-variant", keymap_from_path2), ("--options", "some-option", keymap_from_path2), # Incompatible output types (rmlvo, keymap_from_stdin), (rmlvo, keymap_from_path1), (rmlvo, keymap_from_path2), (kccgst, kccgstYaml), (kccgst, keymap_from_stdin), (kccgst, keymap_from_path1), (kccgst, keymap_from_path2), (kccgst, rmlvo), (kccgst, rmlvo, keymap_from_stdin), (kccgst, rmlvo, keymap_from_path1), (kccgst, rmlvo, keymap_from_path2), (kccgstYaml, keymap_from_stdin), (kccgstYaml, keymap_from_path1), (kccgstYaml, keymap_from_path2), (kccgstYaml, rmlvo), (kccgstYaml, rmlvo, keymap_from_stdin), (kccgstYaml, rmlvo, keymap_from_path1), (kccgstYaml, rmlvo, keymap_from_path2), ): with self.subTest(args=entry): args: list[str] = list( itertools.chain.from_iterable( arg.args if isinstance(arg, Target) else arg for arg in entry ) ) input: str | None = reduce( lambda acc, arg: acc or (arg.stdin if isinstance(arg, Target) else None), args, None, ) self.xkbcli_compile_keymap.run_command_invalid(args, input=input) def test_compile_keymap_rmlvo(self): def run(target, rmlvo): return self.xkbcli_compile_keymap.run_command_success(target + rmlvo) with concurrent.futures.ThreadPoolExecutor() as executor: futures = { executor.submit(run, target.args, rmlvo): (target, rmlvo) for target in ( RmlvoTarget(), KccgstTarget(), KccgstYamlTarget(), KeymapTarget(), ) for rmlvo in rmlvos } for future in concurrent.futures.as_completed(futures, TIMEOUT): target, rmlvo = futures[future] with self.subTest(target=target, rmlvo=rmlvo): future.result() def test_compile_keymap_include(self): for args in ( ["--include", ".", "--include-defaults"], ["--include", "/tmp", "--include-defaults"], ): with self.subTest(args=args): # Succeeds thanks to include-defaults self.xkbcli_compile_keymap.run_command_success(args) def test_compile_keymap_include_invalid(self): # A non-directory is rejected by default args = ["--include", "/proc/version"] rc, stdout, stderr = self.xkbcli_compile_keymap.run_command(args) assert rc == 1, (stdout, stderr) assert "There are no include paths to search" in stderr # A non-existing directory is rejected by default args = ["--include", "/tmp/does/not/exist"] rc, stdout, stderr = self.xkbcli_compile_keymap.run_command(args) assert rc == 1, (stdout, stderr) assert "There are no include paths to search" in stderr # Valid dir, but missing files args = ["--include", "/tmp"] rc, stdout, stderr = self.xkbcli_compile_keymap.run_command(args) assert rc == 1, (stdout, stderr) assert "Couldn't look up rules" in stderr def test_compile_compose(self): for args in (["--verbose"],): with self.subTest(args=args): self.xkbcli_compile_compose.run_command_success(args) def test_how_to_type(self): for args in (["--verbose", "1"],): with self.subTest(args=args): self.xkbcli_how_to_type.run_command_success(args) @dataclass class Entry: args: list[str] name: str value: int for entry in ( # Unicode codepoint conversions, we support whatever strtol does Entry(args=["123"], name="braceleft", value=0x007B), Entry(args=["0123"], name="braceleft", value=0x007B), Entry(args=["0a"], name="Linefeed", value=0xFF0A), Entry(args=["0x123"], name="gcedilla", value=0x03BB), Entry(args=["U+123"], name="gcedilla", value=0x03BB), # Characters Entry(args=["1"], name="1", value=0x0031), Entry(args=["a"], name="a", value=0x0061), Entry(args=["á"], name="aacute", value=0x00E1), # Keysyms names (fallback without --keysym option) Entry(args=["acute"], name="acute", value=0x00B4), Entry(args=["U123"], name="U0123", value=0x1000123), # Keysyms names (with --keysym) Entry(args=["--keysym", "1"], name="1", value=0x0031), Entry(args=["--keysym", "a"], name="a", value=0x0061), Entry(args=["--keysym", "acute"], name="acute", value=0x00B4), Entry(args=["--keysym", "U123"], name="U0123", value=0x1000123), # Keysym values Entry(args=["--keysym", "123"], name="braceleft", value=0x007B), Entry(args=["--keysym", "0x123"], name="0x00000123", value=0x0123), ): with self.subTest(args=args): stdout, _stderr = self.xkbcli_how_to_type.run_command_success( entry.args ) expected = f"keysym: {entry.name} (0x{entry.value:04x})" lines = stdout.splitlines() assert len(lines) >= 1 assert lines[0] == expected, ( entry, f'expected: "{expected}", but got: "{lines[0]}"', ) def test_how_to_type_rmlvo(self): def run(rmlvo): args = rmlvo + ["0x1234"] return self.xkbcli_how_to_type.run_command_success(args) with concurrent.futures.ThreadPoolExecutor() as executor: futures = {executor.submit(run, rmlvo): rmlvo for rmlvo in rmlvos} for future in concurrent.futures.as_completed(futures, TIMEOUT): rmlvo = futures[future] with self.subTest(rmlvo=rmlvo): future.result() def test_list_rmlvo(self): for args in ( ["--verbose"], ["-v"], ["--verbose", "--load-exotic"], ["--load-exotic"], ["--ruleset=evdev"], ["--ruleset=base"], ): with self.subTest(args=args): self.xkbcli_list.run_command_success(args) def test_list_rmlvo_includes(self): args = ["/tmp/"] self.xkbcli_list.run_command_success(args) def test_list_rmlvo_includes_invalid(self): args = ["/proc/version"] rc, stdout, stderr = self.xkbcli_list.run_command(args) assert rc == 1 assert "Failed to append include path" in stderr def test_list_rmlvo_includes_no_defaults(self): args = ["--skip-default-paths", "/tmp"] rc, stdout, stderr = self.xkbcli_list.run_command(args) assert rc == 1 assert "Failed to parse XKB description" in stderr def test_interactive_evdev_rmlvo(self): def run(rmlvo): return self.xkbcli_interactive_evdev.run_command_success(rmlvo) with concurrent.futures.ThreadPoolExecutor() as executor: futures = {executor.submit(run, rmlvo): rmlvo for rmlvo in rmlvos} for future in concurrent.futures.as_completed(futures, TIMEOUT): rmlvo = futures[future] with self.subTest(rmlvo=rmlvo): future.result() def test_interactive_evdev(self): # Note: --enable-compose fails if $prefix doesn't have the compose tables # installed for args in ( ["--verbose"], ["--uniline"], ["--multiline"], ["--report-state-changes"], ["--enable-compose"], ["--consumed-mode=xkb"], ["--consumed-mode=gtk"], ["--without-x11-offset"], ): with self.subTest(args=args): self.xkbcli_interactive_evdev.run_command_success(args) def test_interactive_x11(self): for args in ( ["--verbose"], ["--uniline"], ["--multiline"], ): with self.subTest(args=args): self.xkbcli_interactive_x11.run_command_success(args) def test_interactive_wayland(self): for args in ( ["--verbose"], ["--uniline"], ["--multiline"], ): with self.subTest(args=args): self.xkbcli_interactive_wayland.run_command_success(args) if __name__ == "__main__": with tempfile.TemporaryDirectory() as tmpdir: # Use our own test xkeyboard-config copy. os.environ["XKB_CONFIG_ROOT"] = str(top_srcdir / "test/data") # Use our own X11 locale copy. os.environ["XLOCALEDIR"] = str(top_srcdir / "test/data/locale") # Use our own locale. os.environ["LC_CTYPE"] = "en_US.UTF-8" # libxkbcommon has fallbacks when XDG_CONFIG_HOME isn't set so we need # to override it with a known (empty) directory. Otherwise our test # behavior depends on the system the test is run on. os.environ["XDG_CONFIG_HOME"] = tmpdir # Prevent the legacy $HOME/.xkb from kicking in. del os.environ["HOME"] # This needs to be separated if we do specific extra path testing os.environ["XKB_CONFIG_EXTRA_PATH"] = tmpdir unittest.main() xkbcommon-libxkbcommon-54ee7ac/test/utf8.c000066400000000000000000000125051510033435100206770ustar00rootroot00000000000000/* * Copyright © 2014 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include "src/keysym.h" #include "test.h" #include "utf8.h" #include "utf8-decoding.h" #include "utils.h" #define VALID(lit) assert(is_valid_utf8(lit, sizeof(lit)-1)) #define INVALID(lit) assert(!is_valid_utf8(lit, sizeof(lit)-1)) static void test_is_valid_utf8(void) { /* * Mostly taken from: * https://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt */ VALID("ascii"); VALID("\xCE\xBA\xE1\xBD\xB9\xCF\x83\xCE\xBC\xCE\xB5"); VALID(""); VALID("\x00"); VALID("\x00\x00"); VALID("\x50"); VALID("\xC2\x80"); VALID("\xE0\xA0\x80"); VALID("\xF0\x90\x80\x80"); /* 5/6-byte continuations aren't allowed (unlike UTF-8-test). */ INVALID("\xF8\x88\x80\x80\x80"); INVALID("\xFC\x84\x80\x80\x80\x80"); VALID("\x7F"); VALID("\xDF\xBF"); VALID("\xEF\xBF\xBF"); /* VALID("\xF7\xBF\xBF\xBF"); */ /* 5/6-byte continuations aren't allowed (unlike UTF-8-test). */ INVALID("\xFB\xBF\xBF\xBF\xBF"); INVALID("\xFD\xBFxBF\xBF\xBF"); VALID("\xED\x9F\xBF"); VALID("\xEE\x80\x80"); VALID("\xEF\xBF\xBD"); VALID("\xF4\x8F\xBF\xBF"); /* VALID("\xF4\x90\x80\x80"); */ INVALID("\x80"); INVALID("\xBF"); INVALID("\x80\xBF"); INVALID("\x80\xBF\x80"); INVALID("\x80\xBF\x80\xBF"); INVALID("\x80\xBF\x80\xBF\x80"); INVALID("\x80\xBF\x80\xBF\x80\xBF"); INVALID("\x80\xBF\x80\xBF\x80\xBF\x80"); INVALID("\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F" "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F" "\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF" "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF"); INVALID("\xC0 \xC1 \xC2 \xC3 \xC4 \xC5 \xC6 \xC7 \xC8 \xC9 \xCA \xCB \xCC " "\xCD \xCE \xCF " "\xD0 \xD1 \xD2 \xD3 \xD4 \xD5 \xD6 \xD7 \xD8 \xD9 \xDA \xDB \xDD " "\xDD \xDE \xDF "); INVALID("\xF0 \xF1 \xF2 \xF3 \xF4 \xF5 \xF6 \xF7 "); INVALID("\xF8 \xF9 \xFA \xFB "); INVALID("\xFC \xFD "); INVALID("\xC0"); INVALID("\xE0\x80"); INVALID("\xF0\x80\x80"); INVALID("\xF8\x80\x80\x80"); INVALID("\xFC\x80\x80\x80\x80"); INVALID("\xDF"); INVALID("\xEF\xBF"); INVALID("\xF7\xBF\xBF"); INVALID("\xFB\xBF\xBF\xBF"); INVALID("\xFD\xBF\xBF\xBF\xBF"); INVALID("\xC0\xE0\x80\xF0\x80\x80\xF8\x80\x80\x80\xFC\x80\x80\x80\x80" "\xDF\xEF\xBF\xF7\xBF\xBF\xFB\xBF\xBF\xBF\xFD\xBF\xBF\xBF\xBF"); INVALID("\xFE"); INVALID("\xFF"); INVALID("\xFE\xFE\xFF\xFF"); INVALID("\xC0\xAF"); INVALID("\xE0\x80\xAF"); INVALID("\xF0\x80\x80\xAF"); INVALID("\xF8\x80\x80\x80\xAF"); INVALID("\xFC\x80\x80\x80\x80\xAF"); INVALID("\xC1\xBF"); INVALID("\xE0\x9F\xBF"); INVALID("\xF0\x8F\xBF\xBF"); INVALID("\xF8\x87\xBF\xBF\xBF"); INVALID("\xFC\x83\xBF\xBF\xBF\xBF"); INVALID("\xC0\x80"); INVALID("\xE0\x80\x80"); INVALID("\xF0\x80\x80\x80"); INVALID("\xF8\x80\x80\x80\x80"); INVALID("\xFC\x80\x80\x80\x80\x80"); INVALID("\xED\xA0\x80"); INVALID("\xED\xAD\xBF"); INVALID("\xED\xAE\x80"); INVALID("\xED\xAF\xBF"); INVALID("\xED\xB0\x80"); INVALID("\xED\xBE\x80"); INVALID("\xED\xBF\xBF"); INVALID("\xED\xA0\x80\xED\xB0\x80"); INVALID("\xED\xA0\x80\xED\xBF\xBF"); INVALID("\xED\xAD\xBF\xED\xB0\x80"); INVALID("\xED\xAD\xBF\xED\xBF\xBF"); INVALID("\xED\xAE\x80\xED\xB0\x80"); INVALID("\xED\xAE\x80\xED\xBF\xBF"); INVALID("\xED\xAF\xBF\xED\xB0\x80"); INVALID("\xED\xAF\xBF\xED\xBF\xBF"); /* INVALID("\xEF\xBF\xBE"); */ /* INVALID("\xEF\xBF\xBF"); */ } static void check_utf32_to_utf8(uint32_t unichar, int expected_length, const char *expected) { char buffer[XKB_KEYSYM_UTF8_MAX_SIZE]; int length; length = utf32_to_utf8(unichar, buffer); assert(length == expected_length); assert(streq(buffer, expected)); } static void test_utf32_to_utf8(void) { check_utf32_to_utf8(0x0, 2, ""); check_utf32_to_utf8(0x40, 2, "\x40"); check_utf32_to_utf8(0xA1, 3, "\xc2\xa1"); check_utf32_to_utf8(0x2701, 4, "\xe2\x9c\x81"); check_utf32_to_utf8(0xd800, 0, ""); // Unicode surrogates check_utf32_to_utf8(0xdfff, 0, ""); // Unicode surrogates check_utf32_to_utf8(0x1f004, 5, "\xf0\x9f\x80\x84"); check_utf32_to_utf8(0x110000, 0, ""); check_utf32_to_utf8(0xffffffff, 0, ""); } static void /* Check roundtrip UTF-32 → UTF-8 → UTF-32 */ test_utf8_to_utf32(void) { char buffer[XKB_KEYSYM_UTF8_MAX_SIZE]; for (uint32_t cp = 0; cp < 0x10ffff; cp++) { int length = utf32_to_utf8(cp, buffer) - 1; /* Check surrogates */ if (is_surrogate(cp)) { assert(length == -1); } else { assert(length > 0); size_t length2 = 0; uint32_t cp2 = utf8_next_code_point(buffer, (size_t)length, &length2); assert(cp2 != INVALID_UTF8_CODE_POINT && cp2 == cp && length2 == (size_t)length); } } } int main(void) { test_init(); test_is_valid_utf8(); test_utf32_to_utf8(); test_utf8_to_utf32(); return 0; } xkbcommon-libxkbcommon-54ee7ac/test/utils-text.c000066400000000000000000000117401510033435100221330ustar00rootroot00000000000000/* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "src/darray.h" #include "src/utils.h" #include "test/utils-text.h" /* For each line, drop substring starting from a given needle, then drop * the line if the rest are only whitespaces. The needle must not contain * "\n". */ char * strip_lines(const char *input, size_t input_length, const char *prefix) { darray_char buf = darray_new(); const size_t prefix_len = strlen(prefix); const char *start = input; const char *end = input + input_length; const char *next = strstr(start, prefix); size_t count; while (start < end && next != NULL) { count = (size_t)(next - start); next = start + count + prefix_len; /* Find previous non-space */ size_t i; for (i = count; i > 0; i--) { if (start[i - 1] != ' ' && start[i - 1] != '\t') break; } bool dropped = false; /* Drop line if only whitespaces */ if (i == 0 || start[i - 1] == '\n') { count = i; dropped = true; } /* Append string */ darray_append_items(buf, start, (darray_size_t) count); /* Find end of line */ if (next >= end) { start = end; break; } start = strchr(next, 0x0a); if (start == NULL) { start = end; break; } if (dropped) start++; next = strstr(start, prefix); } /* Append remaining */ if (start < end) { count = (size_t)(end - start); darray_append_items(buf, start, (darray_size_t) count); } darray_append(buf, '\0'); return darray_items(buf); } char * uncomment(const char *input, size_t input_length, const char *prefix) { darray_char buf = darray_new(); const size_t prefix_len = strlen(prefix); const char *start = input; const char *end = input + input_length; char *next = strstr(start, prefix); size_t count; while (start < end && next != NULL) { count = (size_t)(next - start); darray_append_items(buf, start, (darray_size_t) count); /* Skip prefix */ start += count + prefix_len; /* Find end of line */ if (start >= end) break; next = strchr(start, 0x0a); if (next == NULL) break; next = strstr(next, prefix); } /* Append remaining */ if (start < end) { count = (size_t)(end - start); darray_append_items(buf, start, (darray_size_t) count); } darray_append(buf, '\0'); return darray_items(buf); } /* Split string into lines */ size_t split_lines(const char *input, size_t input_length, struct text_line *output, size_t output_length) { const char *start = input; char *next; size_t l; size_t i = 0; for (l = 0; i < input_length && l < output_length && *start != '\0'; l++) { /* Look for newline character */ next = strchr(start, 0x0a); output[l].start = start; if (next == NULL) { /* Not found: add the rest of the string */ output[l++].length = strlen(start); break; } output[l].length = (size_t)(next - start) + 1; start = next + 1; i += output[l].length; } return l; } size_t concat_lines(struct text_line *lines, size_t length, const char *sep, char *output) { char *out = output; size_t sep_len = strlen(sep); for (size_t i = 0; i < length; i++) { if (i > 0) { memcpy(out, sep, sep_len); out += sep_len; } memcpy(out, lines[i].start, lines[i].length); out += lines[i].length; } *out = '\0'; return (size_t)(out - output); } size_t shuffle_lines(struct text_line *lines, size_t length, char *output) { /* Shuffle lines in-place using Fisher–Yates algorithm. * See: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle */ assert(length < RAND_MAX); char *out = output; if (length > 1) { /* 1. Set the current i to the last line. * 2. Take a random line j before the current line i. * 3. Swap the lines i and j. * 4. Append line i to the output. * 5. If i is the first line, stop. Else decrease i and go to 2). */ for (size_t i = length - 1; i > 0; i--) { /* Swap current line with random line before it */ size_t j = rand() % (i+1); struct text_line tmp = lines[j]; lines[j] = lines[i]; lines[i] = tmp; /* Append current line */ memcpy(out, lines[i].start, lines[i].length); out += lines[i].length; /* Ensure line ends with newline */ if (out[-1] != '\n') { out[0] = '\n'; out++; } } } return (size_t)(out - output); } xkbcommon-libxkbcommon-54ee7ac/test/utils-text.h000066400000000000000000000012711510033435100221360ustar00rootroot00000000000000/* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include #include char * strip_lines(const char *input, size_t input_length, const char *prefix); char * uncomment(const char *input, size_t input_length, const char *prefix); struct text_line { const char *start; size_t length; }; size_t split_lines(const char *input, size_t input_length, struct text_line *output, size_t output_length); size_t concat_lines(struct text_line *lines, size_t length, const char *sep, char *output); size_t shuffle_lines(struct text_line *lines, size_t length, char *output); xkbcommon-libxkbcommon-54ee7ac/test/utils.c000066400000000000000000000412711510033435100211530ustar00rootroot00000000000000/* * Copyright © 2019 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include "test.h" #include "utils.h" #include "utils-numbers.h" #include "utils-paths.h" #include "test/utils-text.h" static void test_string_functions(void) { char buffer[10]; assert(!snprintf_safe(buffer, 0, "foo")); assert(!snprintf_safe(buffer, 1, "foo")); assert(!snprintf_safe(buffer, 3, "foo")); assert(snprintf_safe(buffer, 10, "foo")); assert(streq(buffer, "foo")); assert(!snprintf_safe(buffer, 10, "%s", "1234567890")); assert(snprintf_safe(buffer, 10, "%s", "123456789")); assert(streq_null("foo", "foo")); assert(!streq_null("foobar", "foo")); assert(!streq_null("foobar", NULL)); assert(!streq_null(NULL, "foobar")); assert(streq_null(NULL, NULL)); const char text[] = "123; // abc\n" " // def\n" "456 // ghi // jkl\n" "// mno\n" "//\n" "ok; // pqr\n" "foo\n"; char *out; out = strip_lines(text, ARRAY_SIZE(text), "//"); assert_streq_not_null( "strip_lines", "123; \n" "456 \n" "ok; \n" "foo\n", out ); free(out); out = uncomment(text, ARRAY_SIZE(text), "//"); assert_streq_not_null( "uncomment", "123; abc\n" " def\n" "456 ghi // jkl\n" " mno\n" "\n" "ok; pqr\n" "foo\n", out ); free(out); } static void test_path_functions(void) { /* Absolute paths */ assert(!is_absolute_path("")); #ifdef _WIN32 assert(!is_absolute_path("path\\test")); assert(is_absolute_path("c:\\test")); assert(!is_absolute_path("c:test")); assert(is_absolute_path("c:\\")); assert(is_absolute_path("c:/")); assert(!is_absolute_path("c:")); assert(is_absolute_path("\\\\foo")); assert(is_absolute_path("\\\\?\\foo")); assert(is_absolute_path("\\\\?\\UNC\\foo")); assert(is_absolute_path("/foo")); assert(is_absolute_path("\\foo")); #else assert(!is_absolute_path("test/path")); assert(is_absolute_path("/test" )); assert(is_absolute_path("/" )); #endif } static uint32_t rand_uint32(void) { /* First decide how many bits we’ll actually use (1-32) */ int bits = 1 + (rand() % 32); /* Generate a number with that many bits */ uint32_t result = 0; while (bits > 0) { int bits_this_round = bits > 16 ? 16 : bits; result = (result << bits_this_round) | (rand() & ((1U << bits_this_round) - 1)); bits -= bits_this_round; } return result; } static uint64_t rand_uint64(void) { /* First decide how many bits we’ll actually use (1-64) */ int bits = 1 + (rand() % 64); /* Generate a number with that many bits */ uint64_t result = 0; while (bits > 0) { int bits_this_round = bits > 16 ? 16 : bits; result = (result << bits_this_round) | (rand() & ((1U << bits_this_round) - 1)); bits -= bits_this_round; } return result; } /* NOLINTBEGIN(google-readability-function-size) */ static void test_number_parsers(void) { /* Check the claim that it always works on normal strings using SIZE_MAX and * that it always stops on the first NULL byte */ { static const struct { const char* input; struct { int count; uint64_t val; } dec; struct { int count; uint64_t val; } hex; } tests[] = { { .input = "", .dec = { 0, UINT64_C(0) }, .hex = { 0, UINT64_C(0) } }, { .input = "\0""123", .dec = { 0, UINT64_C(0) }, .hex = { 0, UINT64_C(0) } }, { .input = "/", .dec = { 0, UINT64_C(0) }, .hex = { 0, UINT64_C(0) } }, { .input = ";", .dec = { 0, UINT64_C(0) }, .hex = { 0, UINT64_C(0) } }, { .input = "x", .dec = { 0, UINT64_C(0) }, .hex = { 0, UINT64_C(0) } }, { .input = "/1", .dec = { 0, UINT64_C(0) }, .hex = { 0, UINT64_C(0) } }, { .input = ";1", .dec = { 0, UINT64_C(0) }, .hex = { 0, UINT64_C(0) } }, { .input = "x1", .dec = { 0, UINT64_C(0) }, .hex = { 0, UINT64_C(0) } }, { .input = "0", .dec = { 1, UINT64_C(0) }, .hex = { 1, UINT64_C(0) } }, { .input = "1", .dec = { 1, UINT64_C(1) }, .hex = { 1, UINT64_C(1) } }, { .input = "123", .dec = { 3, UINT64_C(123) }, .hex = { 3, UINT64_C(0x123)} }, { .input = "123x", .dec = { 3, UINT64_C(123) }, .hex = { 3, UINT64_C(0x123)} }, { .input = "123""\0""456", .dec = { 3, UINT64_C(123) }, .hex = { 3, UINT64_C(0x123)} }, { .input = "18446744073709551615", .dec = { 20, UINT64_MAX }, .hex = { -1, UINT64_C(0x1844674407370955)} }, { .input = "18446744073709551616", .dec = { -1, UINT64_C(1844674407370955161)}, .hex = { -1, UINT64_C(0x1844674407370955) } }, { .input = "99999999999999999999", .dec = { -1, UINT64_C(9999999999999999999)}, .hex = { -1, UINT64_C(0x9999999999999999) } }, { .input = "184467440737095516150", .dec = { -1, UINT64_MAX }, .hex = { -1, UINT64_C(0x1844674407370955)} }, { .input = "00000000000000000", .dec = { 17, UINT64_C(0) }, .hex = { 17, UINT64_C(0) } }, { .input = "00000000000000001", .dec = { 17, UINT64_C(1) }, .hex = { 17, UINT64_C(1) } }, { .input = "ffffffffffffffff", .dec = { 0 , 0 }, .hex = { 16, UINT64_MAX} }, { .input = "ffffffffffffffff0", .dec = { 0 , 0 }, .hex = { -1, UINT64_MAX} }, { .input = "10000000000000000", .dec = { 17, UINT64_C(10000000000000000) }, .hex = { -1, UINT64_C(0x1000000000000000)} }, { .input = "fffffffffffffffff", .dec = { 0 , 0 }, .hex = { -1, UINT64_MAX} }, }; for (size_t k = 0; k < ARRAY_SIZE(tests); k++) { const size_t len = strlen(tests[k].input); /* Try different lengths */ const struct {const char* label; size_t len;} sizes[] = { { .label = "buffer" , .len = len }, { .label = "string" , .len = len + 1 }, { .label = "SIZE_MAX", .len = SIZE_MAX} }; for (unsigned int s = 0; s < ARRAY_SIZE(sizes); s++) { int count; /* Decimal */ uint64_t dec = 0; count = parse_dec_to_uint64_t(tests[k].input, sizes[s].len, &dec); assert_printf(count == tests[k].dec.count, "Dec %s #%zu \"%s\" (%zu), " "expected: %d, got: %d\n", sizes[s].label, k, tests[k].input, sizes[s].len, tests[k].dec.count, count); assert_printf(dec == tests[k].dec.val, "Dec %s #%zu \"%s\", " "expected: %"PRIu64", got: %"PRIu64"\n", sizes[s].label, k, tests[k].input, tests[k].dec.val, dec); /* Hexadecimal */ uint64_t hex = 0; count = parse_hex_to_uint64_t(tests[k].input, sizes[s].len, &hex); assert_printf(count == tests[k].hex.count, "Hex %s #%zu \"%s\" (%zu), " "expected: %d, got: %d\n", sizes[s].label, k, tests[k].input, sizes[s].len, tests[k].hex.count, count); assert_printf(hex == tests[k].hex.val, "Hex %s #%zu \"%s\", " "expected: %#"PRIx64", got: %#"PRIx64"\n", sizes[s].label, k, tests[k].input, tests[k].hex.val, hex); } } } #define PRIuint64_t PRIx64 #define PRIuint32_t PRIx32 #define test_parse_to(type, format, input, count, expected) do { \ type n = 0; \ int r = parse_##format##_to_##type(input, ARRAY_SIZE(input), &n);\ assert_printf(r == (count), \ "Buffer: expected count: %d, " \ "got: %d (value: %#"PRI##type", string: %.*s)\n", \ count, r, n, (int) ARRAY_SIZE(input), (input)); \ assert_printf(n == (expected), \ "Buffer: expected value: %#"PRI##type", got: " \ "%#"PRI##type"\n", expected, n); \ } while (0) /* Test syntax variants */ const uint64_t values[] = { UINT64_C(0), UINT64_C(1), UINT64_C(10), UINT64_C(0xA), UINT64_C(0xF), UINT64_C(123), UINT32_MAX / 10, UINT32_MAX / 10 + 9, UINT32_MAX >> 4, UINT32_MAX >> 4 | 0xf, UINT32_MAX - 1, UINT32_MAX, UINT32_MAX + UINT64_C(1), UINT64_C(9999999999999999999), UINT64_MAX / 10, UINT64_MAX / 10 + 9, UINT64_MAX >> 4, UINT64_MAX >> 4 | 0xf, UINT64_MAX - 1, UINT64_MAX, }; char buffer[30] = {0}; for (size_t k = 0; k < ARRAY_SIZE(values); k++) { int count; /* Basic: decimal */ count = snprintf(buffer, sizeof(buffer), "%"PRIu32, (uint32_t) values[k]); assert(count > 0); test_parse_to(uint32_t, dec, buffer, count, (uint32_t) values[k]); count = snprintf(buffer, sizeof(buffer), "%"PRIu64, values[k]); assert(count > 0); test_parse_to(uint64_t, dec, buffer, count, values[k]); /* Basic: hex lower case */ count = snprintf(buffer, sizeof(buffer), "%"PRIx32, (uint32_t) values[k]); assert(count > 0); test_parse_to(uint32_t, hex, buffer, count, (uint32_t) values[k]); count = snprintf(buffer, sizeof(buffer), "%"PRIx64, values[k]); assert(count > 0); test_parse_to(uint64_t, hex, buffer, count, values[k]); /* Basic: hex upper case */ count = snprintf(buffer, sizeof(buffer), "%"PRIX32, (uint32_t) values[k]); assert(count > 0); test_parse_to(uint32_t, hex, buffer, count, (uint32_t) values[k]); count = snprintf(buffer, sizeof(buffer), "%"PRIX64, values[k]); assert(count > 0); test_parse_to(uint64_t, hex, buffer, count, values[k]); /* Prefix with some zeroes */ for (int z = 0; z < 10 ; z++) { /* Decimal */ count = snprintf(buffer, sizeof(buffer), "%0*"PRIu32, z, (uint32_t) values[k]); assert(count > 0); test_parse_to(uint32_t, dec, buffer, count, (uint32_t) values[k]); count = snprintf(buffer, sizeof(buffer), "%0*"PRIu64, z, values[k]); assert(count > 0); test_parse_to(uint64_t, dec, buffer, count, values[k]); /* Hexadecimal */ count = snprintf(buffer, sizeof(buffer), "%0*u%"PRIx32, z, 0, (uint32_t) values[k]); assert(count > 0); test_parse_to(uint32_t, hex, buffer, count, (uint32_t) values[k]); count = snprintf(buffer, sizeof(buffer), "%0*u%"PRIx64, z, 0, values[k]); assert(count > 0); test_parse_to(uint64_t, hex, buffer, count, values[k]); /* Append some garbage */ for (int c = 0; c < 0x100 ; c++) { if (c < '0' || c > '9') { /* Decimal */ count = snprintf(buffer, sizeof(buffer), "%0*u%"PRIu32"%c", z, 0, (uint32_t) values[k], (char) c); assert(count > 0); test_parse_to(uint32_t, dec, buffer, count - 1, (uint32_t) values[k]); count = snprintf(buffer, sizeof(buffer), "%0*u%"PRIu64"%c", z, 0, values[k], (char) c); assert(count > 0); test_parse_to(uint64_t, dec, buffer, count - 1, values[k]); } if (!is_xdigit((char) c)) { /* Hexadecimal */ count = snprintf(buffer, sizeof(buffer), "%0*u%"PRIx32"%c", z, 0, (uint32_t) values[k], (char) c); assert(count > 0); test_parse_to(uint32_t, hex, buffer, count - 1, (uint32_t) values[k]); count = snprintf(buffer, sizeof(buffer), "%0*u%"PRIx64"%c", z, 0, values[k], (char) c); assert(count > 0); test_parse_to(uint64_t, hex, buffer, count - 1, values[k]); } } } } /* Random */ for (unsigned int k = 0; k < 10000; k++) { const uint32_t x32 = rand_uint32(); const uint64_t x64 = rand_uint64(); int count; /* Hex: Lower case */ count = snprintf(buffer, sizeof(buffer), "%"PRIx32, x32); assert(count > 0); test_parse_to(uint32_t, hex, buffer, count, x32); count = snprintf(buffer, sizeof(buffer), "%"PRIx64, x64); assert(count > 0); test_parse_to(uint64_t, hex, buffer, count, x64); /* Hex: Upper case (32 bits) */ count = snprintf(buffer, sizeof(buffer), "%"PRIX32, x32); assert(count > 0); test_parse_to(uint32_t, hex, buffer, count, x32); /* Hex: some garbage after */ buffer[count] = (char) (((unsigned int) rand()) % '0'); test_parse_to(uint32_t, hex, buffer, count, x32); /* Hex: Upper case (64 bits) */ count = snprintf(buffer, sizeof(buffer), "%"PRIX64, x64); assert(count > 0); test_parse_to(uint64_t, hex, buffer, count, x64); /* Hex: some garbage after */ buffer[count] = (char) (((unsigned int) rand()) % '0'); test_parse_to(uint64_t, hex, buffer, count, x64); /* Decimal (32 bits) */ count = snprintf(buffer, sizeof(buffer), "%"PRIu32, x32); assert(count > 0); test_parse_to(uint32_t, dec, buffer, count, x32); /* Decimal: some garbage after */ buffer[count] = (char) (((unsigned int) rand()) % '0'); test_parse_to(uint32_t, dec, buffer, count, x32); /* Decimal (64 bits) */ count = snprintf(buffer, sizeof(buffer), "%"PRIu64, x64); assert(count > 0); test_parse_to(uint64_t, dec, buffer, count, x64); buffer[count] = (char) (((unsigned int) rand()) % '0'); test_parse_to(uint64_t, dec, buffer, count, x64); } } /* NOLINTEND(google-readability-function-size) */ /* CLI positional arguments: * 1. Seed for the pseudo-random generator: * - Leave it unset or set it to “-” to use current time. * - Use an integer to set it explicitly. */ int main(int argc, char *argv[]) { test_init(); /* Initialize pseudo-random generator with program arg or current time */ unsigned int seed; if (argc >= 2 && !streq(argv[1], "-")) { seed = (unsigned int) atoi(argv[1]); } else { seed = (unsigned int) time(NULL); } fprintf(stderr, "Seed for the pseudo-random generator: %u\n", seed); srand(seed); test_string_functions(); test_path_functions(); test_number_parsers(); return EXIT_SUCCESS; } xkbcommon-libxkbcommon-54ee7ac/test/x11.c000066400000000000000000000036741510033435100204310ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include "test.h" #include "xvfb-wrapper.h" #include "xkbcommon/xkbcommon-x11.h" X11_TEST(test_basic) { struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); xcb_connection_t *conn; int ret; int32_t device_id; struct xkb_keymap *keymap; struct xkb_state *state; char *dump; int exit_code = EXIT_SUCCESS; /* * The next two steps depend on a running X server with XKB support. * If it fails, it's not necessarily an actual problem with the code. * So we don't want a FAIL here. */ conn = xcb_connect(display, NULL); if (!conn || xcb_connection_has_error(conn)) { exit_code = TEST_SETUP_FAILURE; goto err_conn; } ret = xkb_x11_setup_xkb_extension(conn, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, NULL, NULL); if (!ret) { exit_code = TEST_SETUP_FAILURE; goto err_conn; } device_id = xkb_x11_get_core_keyboard_device_id(conn); assert(device_id != -1); keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); assert(keymap); state = xkb_x11_state_new_from_device(keymap, conn, device_id); assert(state); dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); assert(dump); fputs(dump, stdout); /* TODO: Write some X11-specific tests. */ free(dump); xkb_state_unref(state); xkb_keymap_unref(keymap); err_conn: xcb_disconnect(conn); xkb_context_unref(ctx); return exit_code; } int main(void) { test_init(); return x11_tests_run(); } xkbcommon-libxkbcommon-54ee7ac/test/x11comp.c000066400000000000000000000423101510033435100212760ustar00rootroot00000000000000/* * Copyright © 2014 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-keysyms.h" #include "xkbcommon/xkbcommon-names.h" #include "xkbcommon/xkbcommon-x11.h" #include "evdev-scancodes.h" #include "test.h" #include "tools/tools-common.h" #include "utils.h" #include "utils-text.h" #include "xvfb-wrapper.h" /* Offset between evdev keycodes (where KEY_ESCAPE is 1), and the evdev XKB * keycode set (where ESC is 9). */ #define EVDEV_OFFSET 8 enum update_files { NO_UPDATE = 0, UPDATE_USING_TEST_INPUT, UPDATE_USING_TEST_OUTPUT }; static enum update_files update_test_files = NO_UPDATE; static char * prepare_keymap(const char *original, bool strip_all_comments) { if (strip_all_comments) { return strip_lines(original, strlen(original), "//"); } else { char *tmp = uncomment(original, strlen(original), "//"); char *ret = strip_lines(tmp, strlen(tmp), "//"); free(tmp); return ret; } } /* * Reset keymap to `empty` on the server. * It seems that xkbcomp does not fully set the keymap on the server and * the conflicting leftovers may raise errors. */ static int reset_keymap(const char* display) { char *envp[] = { NULL }; const char* setxkbmap_argv[] = { "setxkbmap", "-display", display, "-geometry", "pc", "-keycodes", "evdev", "-compat", "basic", "-types", "basic+numpad", /* Avoid extra types */ "-symbols", "us", // "-v", "10", NULL }; /* Launch xkbcomp */ pid_t setxkbmap_pid; int ret = posix_spawnp(&setxkbmap_pid, "setxkbmap", NULL, NULL, (char* const*)setxkbmap_argv, envp); if (ret != 0) { fprintf(stderr, "[ERROR] Cannot run setxkbmap. posix_spawnp error %d: %s\n", ret, strerror(ret)); if (ret == ENOENT) { fprintf(stderr, "[ERROR] setxkbmap may be missing. " "Please install the corresponding package, " "e.g. \"setxkbmap\" or \"x11-xkb-utils\".\n"); } return TEST_SETUP_FAILURE; } int status; ret = waitpid(setxkbmap_pid, &status, 0); return (ret < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) ? TEST_SETUP_FAILURE : EXIT_SUCCESS; } // TODO: unused for now // /* Use xkbcomp to load a keymap from a file */ // static int // run_xkbcomp_file(const char* display, xcb_connection_t *conn, int32_t device_id, // const char *xkb_path) // { // /* Prepare xkbcomp parameters */ // char *envp[] = { NULL }; // const char* xkbcomp_argv[] = {"xkbcomp", "-I", xkb_path, display, NULL}; // // /* Launch xkbcomp */ // pid_t xkbcomp_pid; // int ret = posix_spawnp(&xkbcomp_pid, "xkbcomp", NULL, NULL, // (char* const*)xkbcomp_argv, envp); // if (ret != 0) { // fprintf(stderr, // "[ERROR] Cannot run xkbcomp. posix_spawnp error %d: %s\n", // ret, strerror(ret)); // if (ret == ENOENT) { // fprintf(stderr, // "[ERROR] xkbcomp may be missing. " // "Please install the corresponding package, " // "e.g. \"xkbcomp\" or \"x11-xkb-utils\".\n"); // } // return TEST_SETUP_FAILURE; // } // // /* Wait for xkbcomp to complete */ // int status; // ret = waitpid(xkbcomp_pid, &status, 0); // return (ret < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) // ? TEST_SETUP_FAILURE // : EXIT_SUCCESS; // } enum { PIPE_READ = 0, PIPE_WRITE = 1 }; /* Use xkbcomp to load a keymap from a string */ static int run_xkbcomp_str(const char* display, const char *include_path, const char *keymap) { int ret = EXIT_FAILURE; assert(keymap); /* Prepare xkbcomp parameters */ char *envp[] = { NULL }; char include_path_arg[PATH_MAX+2] = "-I"; const char *xkbcomp_argv[] = { "xkbcomp", "-I" /* reset include path*/, include_path_arg, "-opt", "g", "-w", "10", "-" /* stdin */, display, NULL }; if (include_path) { ret = snprintf(include_path_arg, ARRAY_SIZE(include_path_arg), "-I%s", include_path); if (ret < 0 || ret >= (int)ARRAY_SIZE(include_path_arg)) { return TEST_SETUP_FAILURE; } } /* Prepare input */ int stdin_pipe[2]; posix_spawn_file_actions_t action; if (pipe(stdin_pipe) == -1) { perror("pipe"); ret = TEST_SETUP_FAILURE; goto pipe_error; } if (posix_spawn_file_actions_init(&action)) { perror("spawn_file_actions_init error"); goto posix_spawn_file_actions_init_error; } /* Make spawned process close unused write-end of pipe, else it will not * receive EOF when write-end of the pipe is closed below and it will result * in a deadlock. */ if (posix_spawn_file_actions_addclose(&action, stdin_pipe[PIPE_WRITE])) goto posix_spawn_file_actions_error; /* Make spawned process replace stdin with read end of the pipe */ if (posix_spawn_file_actions_adddup2(&action, stdin_pipe[PIPE_READ], STDIN_FILENO)) goto posix_spawn_file_actions_error; /* Launch xkbcomp */ pid_t xkbcomp_pid; ret = posix_spawnp(&xkbcomp_pid, "xkbcomp", &action, NULL, (char* const*)xkbcomp_argv, envp); if (ret != 0) { fprintf(stderr, "[ERROR] Cannot run xkbcomp. posix_spawnp error %d: %s\n", ret, strerror(ret)); if (ret == ENOENT) { fprintf(stderr, "[ERROR] xkbcomp may be missing. " "Please install the corresponding package, " "e.g. \"xkbcomp\" or \"x11-xkb-utils\".\n"); } goto posix_spawn_file_actions_init_error; } /* Close unused read-end of pipe */ close(stdin_pipe[PIPE_READ]); const ssize_t count = write(stdin_pipe[PIPE_WRITE], keymap, strlen(keymap)); /* Close write-end of the pipe, to emit EOF */ close(stdin_pipe[PIPE_WRITE]); if (count == -1) { perror("Cannot write keymap to stdin"); kill(xkbcomp_pid, SIGTERM); } /* Wait for xkbcomp to complete */ int status; ret = waitpid(xkbcomp_pid, &status, 0); ret = (ret < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) ? TEST_SETUP_FAILURE : EXIT_SUCCESS; goto cleanup; posix_spawn_file_actions_error: perror("posix_spawn_file_actions_* error"); posix_spawn_file_actions_init_error: close(stdin_pipe[PIPE_WRITE]); close(stdin_pipe[PIPE_READ]); ret = TEST_SETUP_FAILURE; cleanup: posix_spawn_file_actions_destroy(&action); pipe_error: return ret; } // TODO: implement tests to ensure compatibility with xkbcomp // struct compile_buffer_private { // const char* display; // xcb_connection_t *conn; // int32_t device_id; // }; // // static struct xkb_keymap * // compile_buffer(struct xkb_context *ctx, const char *buf, size_t len, // void *private) // { // const struct compile_buffer_private *config = private; // assert(buf[len - 1] == '\0'); // // char *include_path = test_get_path(""); // int ret = run_xkbcomp_str(config->display, config->conn, // config->device_id, include_path, buf); // free(include_path); // // if (ret != EXIT_SUCCESS) // return NULL; // // return xkb_x11_keymap_new_from_device(ctx, config->conn, config->device_id, // XKB_KEYMAP_COMPILE_NO_FLAGS); // } static int test_keymap_roundtrip(struct xkb_context *ctx, const char* display, xcb_connection_t *conn, int32_t device_id, bool print_keymap, bool tweak, enum xkb_keymap_serialize_flags serialize_flags, const char *keymap_path) { /* Get raw keymap */ FILE *file = NULL; if (isempty(keymap_path) || strcmp(keymap_path, "-") == 0) { /* Read stdin */ file = tools_read_stdin(); if (!file) return TEST_SETUP_FAILURE; } else { /* Read file from path */ file = fopen(keymap_path, "rb"); if (!file) { perror("Unable to read file"); return TEST_SETUP_FAILURE; } } char *original = read_file(keymap_path, file); fclose(file); if (!original) return TEST_SETUP_FAILURE; /* Pre-process keymap string */ char* expected = prepare_keymap(original, tweak); free(original); if (!expected) { return TEST_SETUP_FAILURE; } /* Prepare X server */ int ret = reset_keymap(display); if (ret != EXIT_SUCCESS) { #ifdef __APPLE__ /* Brew may not provide setxkbmap */ #else goto xkbcomp_error; #endif } /* Load keymap into X server */ ret = run_xkbcomp_str(display, NULL, expected); if (ret != EXIT_SUCCESS) goto xkbcomp_error; /* Get keymap from X server */ struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); assert(keymap); if (!keymap) { ret = EXIT_FAILURE; fprintf(stderr, "ERROR: Failed to get keymap from X server.\n"); goto xkbcomp_error; } /* Dump keymap and compare to expected */ char *got = xkb_keymap_get_as_string2(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT, serialize_flags); if (!got) { ret = EXIT_FAILURE; fprintf(stderr, "ERROR: Failed to dump keymap.\n"); } else { if (print_keymap) fprintf(stdout, "%s\n", got); if (!streq(got, expected)) { ret = EXIT_FAILURE; fprintf(stderr, "ERROR: roundtrip failed. " "Lengths difference: got %zu, expected %zu.\n", strlen(got), strlen(expected)); } else { ret = EXIT_SUCCESS; fprintf(stderr, "Roundtrip succeed.\n"); } free(got); } xkb_keymap_unref(keymap); xkbcomp_error: free(expected); return ret; } static int init_x11_connection(const char *display, xcb_connection_t **conn_rtrn, int32_t *device_id_rtrn) { xcb_connection_t *conn = xcb_connect(display, NULL); if (xcb_connection_has_error(conn)) { return TEST_SETUP_FAILURE; } int ret = xkb_x11_setup_xkb_extension(conn, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, NULL, NULL); if (!ret) goto err_xcb; int32_t device_id = xkb_x11_get_core_keyboard_device_id(conn); if (device_id == -1) goto err_xcb; *conn_rtrn = conn; *device_id_rtrn = device_id; return EXIT_SUCCESS; err_xcb: xcb_disconnect(conn); return TEST_SETUP_FAILURE; } X11_TEST(test_basic) { if (update_test_files != NO_UPDATE) return EXIT_SUCCESS; xcb_connection_t *conn = NULL; int32_t device_id = 0; int ret = init_x11_connection(display, &conn, &device_id); if (ret != EXIT_SUCCESS) { ret = TEST_SETUP_FAILURE; goto err_xcb; } struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); assert(ctx); static const struct { const char *path; enum xkb_keymap_serialize_flags serialize_flags; } keymaps[] = { { .path = "keymaps/host-no-pretty.xkb", .serialize_flags = TEST_KEYMAP_SERIALIZE_FLAGS & ~XKB_KEYMAP_SERIALIZE_PRETTY }, /* This last keymap will be used for the next tests */ { .path = "keymaps/host.xkb", .serialize_flags = TEST_KEYMAP_SERIALIZE_FLAGS }, }; for (size_t k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, k); char *keymap_path = test_get_path(keymaps[k].path); assert(keymap_path); ret = test_keymap_roundtrip(ctx, display, conn, device_id, false, false, keymaps[k].serialize_flags, keymap_path); assert(ret == EXIT_SUCCESS); free(keymap_path); } struct xkb_keymap *keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); /* Check capitalization transformation */ struct xkb_state *state = xkb_x11_state_new_from_device(keymap, conn, device_id); assert(state); xkb_keysym_t sym; sym = xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET); assert(sym == XKB_KEY_a); sym = xkb_state_key_get_one_sym(state, KEY_LEFT + EVDEV_OFFSET); assert(sym == XKB_KEY_Left); const xkb_mod_index_t caps_idx = xkb_keymap_mod_get_index(keymap, XKB_MOD_NAME_CAPS); assert(caps_idx != XKB_MOD_INVALID); const xkb_mod_mask_t caps = UINT32_C(1) << caps_idx; xkb_state_update_mask(state, 0, 0, caps, 0, 0, 0); sym = xkb_state_key_get_one_sym(state, KEY_A + EVDEV_OFFSET); assert(sym == XKB_KEY_A); sym = xkb_state_key_get_one_sym(state, KEY_LEFT + EVDEV_OFFSET); assert(sym == XKB_KEY_Left); xkb_state_unref(state); xkb_keymap_unref(keymap); xkb_context_unref(ctx); ret = EXIT_SUCCESS; err_xcb: if (conn != NULL) xcb_disconnect(conn); return ret; } struct xkbcomp_roundtrip_data { const char *path; bool tweak_comments; enum xkb_keymap_serialize_flags serialize_flags; }; static int xkbcomp_roundtrip(const char *display, void *private) { const struct xkbcomp_roundtrip_data *priv = private; xcb_connection_t *conn = NULL; int32_t device_id = 0; int ret = init_x11_connection(display, &conn, &device_id); if (ret != EXIT_SUCCESS) { ret = TEST_SETUP_FAILURE; goto error_xcb; } struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!ctx) { ret = EXIT_FAILURE; goto error_context; } ret = test_keymap_roundtrip(ctx, display, conn, device_id, true, priv->tweak_comments, priv->serialize_flags, priv->path); xkb_context_unref(ctx); error_context: error_xcb: xcb_disconnect(conn); return ret; } static void usage(FILE *fp, char *progname) { fprintf(fp, "Usage: %s [--update] [--update-obtained] " "[--keymap KEYMAP_FILE] [--tweak] [--no-pretty] [--help]\n", progname); } int main(int argc, char **argv) { test_init(); enum options { OPT_UPDATE_GOLDEN_TEST_WITH_OUTPUT, OPT_UPDATE_GOLDEN_TEST_WITH_INPUT, OPT_FILE, OPT_TWEAK_COMMENTS, OPT_NO_PRETTY, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"update-obtained", no_argument, 0, OPT_UPDATE_GOLDEN_TEST_WITH_OUTPUT}, {"update", no_argument, 0, OPT_UPDATE_GOLDEN_TEST_WITH_INPUT}, {"keymap", required_argument, 0, OPT_FILE}, {"tweak", no_argument, 0, OPT_TWEAK_COMMENTS}, {"no-pretty", no_argument, 0, OPT_NO_PRETTY}, {0, 0, 0, 0}, }; bool tweak_comments = false; const char *path = NULL; enum xkb_keymap_serialize_flags serialize_flags = (enum xkb_keymap_serialize_flags) TEST_KEYMAP_SERIALIZE_FLAGS; while (1) { int opt; int option_index = 0; opt = getopt_long(argc, argv, "h", opts, &option_index); if (opt == -1) break; switch (opt) { case OPT_UPDATE_GOLDEN_TEST_WITH_OUTPUT: update_test_files = UPDATE_USING_TEST_OUTPUT; break; case OPT_UPDATE_GOLDEN_TEST_WITH_INPUT: update_test_files = UPDATE_USING_TEST_INPUT; break; case OPT_FILE: path = optarg; break; case OPT_TWEAK_COMMENTS: tweak_comments = optarg; break; case OPT_NO_PRETTY: serialize_flags &= ~XKB_KEYMAP_SERIALIZE_PRETTY; break; case 'h': usage(stdout, argv[0]); return EXIT_SUCCESS; default: usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } } if (update_test_files != NO_UPDATE && path != NULL) { fprintf(stderr, "ERROR: --update* and --keymap are mutually exclusive.\n"); usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } if (path == NULL) { return x11_tests_run(); } else { struct xkbcomp_roundtrip_data priv = { .path = path, .tweak_comments = tweak_comments, .serialize_flags = serialize_flags }; return xvfb_wrapper(xkbcomp_roundtrip, &priv); } } xkbcommon-libxkbcommon-54ee7ac/test/xkeyboard-config-test.py.in000077500000000000000000000534571510033435100250520ustar00rootroot00000000000000#!/usr/bin/env python3 from __future__ import annotations import argparse import gzip import itertools import json import multiprocessing import os import shlex import subprocess import sys import xml.etree.ElementTree as ET from abc import ABCMeta, abstractmethod from dataclasses import dataclass from functools import partial from pathlib import Path from typing import ( TYPE_CHECKING, BinaryIO, ClassVar, Iterable, Iterator, NoReturn, Protocol, Sequence, TextIO, TypeVar, cast, ) # TODO: import unconditionally Self from typing once we raise Python requirement to 3.11+ if TYPE_CHECKING: from typing_extensions import Self WILDCARD = "*" DEFAULT_XKB_ROOT = Path("@XKB_CONFIG_ROOT@") # Meson needs to fill this in so we can call the tool in the buildir. EXTRA_PATH = "@MESON_BUILD_ROOT@" os.environ["PATH"] = ":".join(filter(bool, (EXTRA_PATH, os.getenv("PATH")))) # Environment variable to get the right level of log os.environ["XKB_LOG_LEVEL"] = "warning" os.environ["XKB_LOG_VERBOSITY"] = "10" @dataclass class RMLVO: DEFAULT_RULES: ClassVar[str] = "evdev" DEFAULT_MODEL: ClassVar[str] = "pc105" DEFAULT_LAYOUT: ClassVar[str] = "us" rules: str model: str layout: str variant: str | None option: str | None def __iter__(self) -> Iterator[str | None]: yield self.rules yield self.model yield self.layout yield self.variant yield self.option @property def rmlvo(self) -> Iterator[tuple[str, str]]: yield ("rules", self.rules) yield ("model", self.model) yield ("layout", self.layout) # Keep only defined and non-empty values if self.variant is not None: yield ("variant", self.variant) if self.option is not None: yield ("option", self.option) @classmethod def from_rmlvo( cls, rules: str | None = None, model: str | None = None, layout: str | None = None, variant: str | None = None, option: str | None = None, ) -> Self: return cls( # We need to force a value for RML components rules or cls.DEFAULT_RULES, model or cls.DEFAULT_MODEL, layout or cls.DEFAULT_LAYOUT, variant, option, ) @dataclass class Invocation(RMLVO, metaclass=ABCMeta): exitstatus: int = 77 # default to “skipped” error: str | None = None keymap: bytes = b"" command: str = "" # The fully compiled keymap def __str_iter(self) -> Iterator[str]: yield f"- rmlvo: {self.to_yaml(self.rmlvo)}" yield f" cmd: {json.dumps(self.command)}" yield f" status: {self.exitstatus}" if self.error: yield f" error: {json.dumps(self.error.strip())}" def __str__(self) -> str: return "\n".join(self.__str_iter()) @property def short(self) -> Iterator[tuple[str, str | int]]: yield from self.rmlvo yield ("status", self.exitstatus) if self.error is not None: yield ("error", self.error) @staticmethod def to_yaml(xs: Iterable[tuple[str, str | int]]) -> str: fields = ", ".join(f"{k}: {json.dumps(v)}" for k, v in xs) return f"{{ {fields} }}" def _write(self, fd: BinaryIO) -> None: fd.write(f"// {self.to_yaml(self.rmlvo)}\n".encode("utf-8")) fd.write(self.keymap) def _write_keymap(self, output_dir: Path, compress: int) -> None: layout = self.layout if self.variant: layout += f"({self.variant})" if self.option: layout += f"+{self.option}" (output_dir / self.model).mkdir(exist_ok=True) keymap_file = output_dir / self.model / layout if compress: keymap_file = keymap_file.with_suffix(".gz") with gzip.open(keymap_file, "wb", compresslevel=compress) as fd: self._write(fd) fd.close() else: with keymap_file.open("wb") as fd: self._write(fd) def _print_result(self, short: bool, verbose: bool) -> None: if self.exitstatus != 0: target = sys.stderr else: target = sys.stdout if verbose else None if target: if short: print("-", self.to_yaml(self.short), file=target) else: print(self, file=target) @classmethod @abstractmethod def run( cls, i: Self, xkb_root: Path, output_dir: Path | None, compress: int, *args, **kwargs, ) -> Self: ... @classmethod def run_all( cls, xkb_root: Path, combos: Iterable[Self], combos_count: int, njobs: int, keymap_output_dir: Path | None, verbose: bool, short: bool, progress_bar: ProgressBar[Iterable[Self]], chunksize: int, compress: int, **kwargs, ) -> bool: if keymap_output_dir: try: keymap_output_dir.mkdir(parents=True) except FileExistsError as e: print(e, file=sys.stderr) return False failed = False with multiprocessing.Pool(njobs) as p: f = partial( cls.run, xkb_root=xkb_root, output_dir=keymap_output_dir, compress=compress, ) results = p.imap_unordered(f, combos, chunksize=chunksize) for invocation in progress_bar( results, total=combos_count, file=sys.stdout ): if invocation.exitstatus != 0: failed = True invocation._print_result(short, verbose) return failed @dataclass class XkbCompInvocation(Invocation): @classmethod def run( cls, i: Self, xkb_root: Path, output_dir: Path | None, compress: int, *args, **kwargs, ) -> Self: i._run(xkb_root, not output_dir) if output_dir: i._write_keymap(output_dir, compress) return i def _run(self, xkb_root: Path, test: bool) -> None: setxkbmap_args = ( "setxkbmap", "-print", # Informative only; we set CWD to ensure proper rules are loaded "-I", str(xkb_root), *itertools.chain.from_iterable((f"-{k}", v) for k, v in self.rmlvo), ) xkbcomp_args = ("xkbcomp", "-I", f"-I{xkb_root}", "-xkb", "-", "-") self.command = shlex.join(itertools.chain(setxkbmap_args, "|", xkbcomp_args)) setxkbmap = subprocess.Popen( setxkbmap_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, cwd=xkb_root, ) stdout, stderr = setxkbmap.communicate() if "Cannot open display" in stderr: self.error = stderr self.exitstatus = 90 else: xkbcomp = subprocess.Popen( xkbcomp_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, ) stdout, stderr = xkbcomp.communicate(stdout) if xkbcomp.returncode != 0: self.error = ( "failed to compile keymap:\n" f"------\nstderr:\n{stderr}\n" f"------\nstdout:\n{stdout}\n" ) self.exitstatus = xkbcomp.returncode else: self.keymap = stdout.encode("utf-8") self.exitstatus = 0 @dataclass class XkbCompToXkbcommonInvocation(XkbCompInvocation): """ Use setxkbcomp & xkbcomp, then pipe the result to xkbcli in order to enable comparison with direct xkbcli compilation with the same format. """ def _run(self, xkb_root: Path, test: bool) -> None: super()._run(xkb_root, test) if self.exitstatus: return if test: return args = ( "xkbcli-compile-keymap", # this is run in the builddir # Not used: keymap is already compiled # "--include", xkb_root, # Not needed, because we set XKB_LOG_LEVEL and XKB_LOG_VERBOSITY in env # "--verbose", "--keymap", ) try: completed = subprocess.run( args, check=True, capture_output=True, input=self.keymap, ) except subprocess.CalledProcessError as err: self.error = ( "failed to compile keymap:\n" f"------\nstderr:\n{err.stderr}\n" f"------\nstdout:\n{err.stdout}\n" f"------\nstdin:\n{self.keymap.decode('utf-8')}\n" ) self.exitstatus = err.returncode else: self.keymap = completed.stdout @dataclass class XkbcommonInvocation(Invocation): UNRECOGNIZED_KEYSYM_ERROR: ClassVar[str] = "XKB-107" def _check_stderr(self, stderr: str) -> bool: if self.UNRECOGNIZED_KEYSYM_ERROR in stderr: for line in stderr.splitlines(): if self.UNRECOGNIZED_KEYSYM_ERROR in line: self.error = line break self.exitstatus = 99 # tool doesn't generate this one return False else: self.exitstatus = 0 return True @classmethod def run( cls, i: Self, xkb_root: Path, output_dir: Path | None, compress: int, *args, **kwargs, ) -> Self: i._run(xkb_root, output_dir, not output_dir, compress) return i def _run( self, xkb_root: Path, output_dir: Path | None, test: bool, compress: int ) -> None: args = ( "xkbcli-compile-keymap", # this is run in the builddir "--include", str(xkb_root), # Not needed, because we set XKB_LOG_LEVEL and XKB_LOG_VERBOSITY in env # "--verbose", *itertools.chain.from_iterable((f"--{k}", v) for k, v in self.rmlvo), ) if test: args += ("--test",) self.command = shlex.join(args) try: completed = subprocess.run(args, text=True, check=True, capture_output=True) except subprocess.CalledProcessError as err: self.error = ( "failed to compile keymap:\n" f"------\nstderr:\n{err.stderr}\n" f"------\nstdout:\n{err.stdout}\n" ) self.exitstatus = err.returncode else: if self._check_stderr(completed.stderr): self.keymap = completed.stdout.encode("utf-8") if output_dir: self._write_keymap(output_dir, compress) @dataclass class XkbcommonToXkbcompInvocation(XkbcommonInvocation): """ Use xkbcli, then pipe the result to xkbcomp in order to check that xkbcomp can parse xkbcommon output. """ def _run( self, xkb_root: Path, output_dir: Path | None, test: bool, compress: int ) -> None: super()._run(xkb_root, output_dir, False, compress) if self.exitstatus: return args = ("xkbcomp", "-xkb", "-opt", "g", "-", "-") try: completed = subprocess.run( args, check=True, capture_output=True, input=self.keymap, ) except subprocess.CalledProcessError as err: self.error = ( "failed to compile keymap:\n" f"------\nstderr:\n{err.stderr}\n" f"------\nstdout:\n{err.stdout}\n" f"------\nstdin:\n{self.keymap.decode('utf-8')}\n" ) self.exitstatus = err.returncode else: self.keymap = completed.stdout if output_dir: self._write_keymap(output_dir, compress) @dataclass class Layout: name: str variants: list[str | None] @classmethod def parse(cls, e: ET.Element, variant: list[str] | None = None) -> Self: if (name_elem := e.find("configItem/name")) is None or name_elem is None: raise ValueError("Layout name not found") if not variant: variants = [None] + [ cls.parse_text(v) for v in e.findall("variantList/variant/configItem/name") ] else: variants = cast(list[str | None], variant) return cls(cls.parse_text(e.find("configItem/name")), variants) @staticmethod def parse_text(e: ET.Element | None) -> str: if e is None or not e.text: raise ValueError("Name not found") return e.text class Registry: @classmethod def parse_path(cls, xkb_root: Path, path: Path) -> Path: if path.is_file(): # File exists: return unchanged return path elif len(path.parts) == 1: # Lookup XML file in XKB root _path = ( path if path.suffix == ".xml" # NOTE: If we got evdev.extras, we want to keep the current suffix else path.with_suffix(f"{path.suffix}.xml") ) _path = xkb_root / "rules" / _path if _path.is_file(): return _path raise ValueError(f"Cannot resolve registry file: {path}") @classmethod def parse( cls, paths: Sequence[Path], tool: type[Invocation], rules: str | None, model: str | None, layout: str | None, variant: str | None, option: str | None, ) -> tuple[int, Iterator[Invocation]]: models: tuple[str, ...] = () layouts: tuple[Layout, ...] = () options: tuple[str, ...] = () if variant and not layout: raise ValueError("Variant must be set together with layout") for path in paths: root = ET.fromstring(path.read_text(encoding="utf-8")) # Models if model is None: models += tuple( e.text for e in root.findall("modelList/model/configItem/name") if e.text ) elif not models: models += (model,) # Layouts/variants if layout: if variant is None: layouts += tuple( map( Layout.parse, ( e for e in root.findall("layoutList/layout") if e.find(f"configItem/name[.='{layout}']") is not None ), ) ) elif not layouts: layouts += ( Layout(layout, cast(list[str | None], variant.split(":"))), ) else: layouts += tuple(map(Layout.parse, root.findall("layoutList/layout"))) # Options if option is None: options += tuple( e.text for e in root.findall("optionList/group/option/configItem/name") if e.text ) elif not options and option: options += (option,) # Some registry may be only partial, e.g.: *.extras.xml if not models: models = (RMLVO.DEFAULT_MODEL,) if not layouts: layouts = (Layout(RMLVO.DEFAULT_LAYOUT, [None]),) count = len(models) * sum(len(l.variants) for l in layouts) * (1 + len(options)) # The list of combos can be huge, so better to use a generator instead def iter_combos() -> Iterator[Invocation]: for m in models: for l in layouts: for v in l.variants: yield tool.from_rmlvo( rules=rules, model=m, layout=l.name, variant=v, option=None ) for opt in options: yield tool.from_rmlvo( rules=rules, model=m, layout=l.name, variant=v, option=opt, ) return count, iter_combos() T = TypeVar("T") # Needed because Callable does not handle keywords args class ProgressBar(Protocol[T]): def __call__(self, x: T, total: int, file: TextIO | None) -> T: ... # The function generating the progress bar (if any). def create_progress_bar(verbose: bool) -> ProgressBar[T]: def noop_progress_bar(x: T, total: int, file: TextIO | None = None) -> T: return x progress_bar: ProgressBar[T] = noop_progress_bar if not verbose and os.isatty(sys.stdout.fileno()): try: from tqdm import tqdm progress_bar = cast(ProgressBar[T], tqdm) except ImportError: pass return progress_bar def main() -> NoReturn: parser = argparse.ArgumentParser( description=""" This tool compiles a keymap for each layout, variant and options combination in the given rules XML file. The output of this tool is YAML, use your favorite YAML parser to extract error messages. Errors are printed to stderr. """ ) parser.add_argument( "paths", metavar="/path/to/rules.xml", nargs="*", type=Path, default=(), help="Path to xkeyboard-config's XML registry file", ) parser.add_argument( "--xkb-root", default=DEFAULT_XKB_ROOT, type=Path, help="XKB root directory", ) DEFAULT_TOOL = "xkbcommon" tools: dict[str, type[Invocation]] = { DEFAULT_TOOL: XkbcommonInvocation, "xkbcommon-xkbcomp": XkbcommonToXkbcompInvocation, "xkbcomp": XkbCompInvocation, "xkbcomp-xkbcommon": XkbCompToXkbcommonInvocation, } parser.add_argument( "--tool", choices=tools.keys(), type=str, default=DEFAULT_TOOL, help="parsing tool to use", ) parser.add_argument( "--jobs", "-j", type=int, default=4 * (os.cpu_count() or 1), help="number of processes to use", ) parser.add_argument("--chunksize", default=1, type=int) parser.add_argument("--verbose", "-v", default=False, action="store_true") parser.add_argument( "--short", default=False, action="store_true", help="Concise output" ) parser.add_argument( "--keymap-output-dir", default=None, type=Path, help="Directory to print compiled keymaps to", ) parser.add_argument( "--compress", type=int, default=0, help="Compression level of keymaps files" ) parser.add_argument( "--rules", default=RMLVO.DEFAULT_RULES, type=str, help="Rule set to use" ) parser.add_argument( "--model", default="", type=str, help="Only test the given model" ) parser.add_argument( "--layout", default=WILDCARD, type=str, help="Only test the given layout" ) parser.add_argument( "--variant", default=WILDCARD, type=str, help="Only test the given variants (colon-separated list)", ) parser.add_argument( "--option", default=WILDCARD, type=str, help="Only test the given option" ) parser.add_argument( "--no-iterations", "-1", action="store_true", help="Only test one combo" ) args = parser.parse_args() xkb_root: Path = args.xkb_root verbose: bool = args.verbose short = args.short keymapdir = args.keymap_output_dir progress_bar: ProgressBar[Iterable[Invocation]] = create_progress_bar(verbose) tool = tools[args.tool] # NOTE: We test only one set of rules; handle wild card only for consistency # with other components. rules: str | None = None if args.rules == WILDCARD else args.rules model: str | None = None if args.model == WILDCARD else args.model layout: str | None = None if args.layout == WILDCARD else args.layout variant: str | None = None if args.variant == WILDCARD else args.variant option: str | None = None if args.option == WILDCARD else args.option if not args.paths: # If there is no given registry, fallback to the given rules, # else fallback to the default rules. path = xkb_root / "rules" / (rules or RMLVO.DEFAULT_RULES) paths = (path.with_suffix(f"{path.suffix}.xml"),) else: paths = tuple(Registry.parse_path(xkb_root, p) for p in args.paths) # This need to be valid YAML. Currently unused, so left as comments print("# xkb root:", json.dumps(str(xkb_root)), file=sys.stderr) print("# paths:", json.dumps(tuple(map(str, paths))), file=sys.stderr) if args.no_iterations: combos = ( tool.from_rmlvo( rules=rules, model=model, layout=layout, variant=variant, option=option ), ) count = len(combos) iter_combos = iter(combos) else: count, iter_combos = Registry.parse( paths, tool, rules, model, layout, variant, option ) failed = tool.run_all( xkb_root=xkb_root, combos=iter_combos, combos_count=count, njobs=args.jobs, keymap_output_dir=keymapdir, verbose=verbose, short=short, progress_bar=progress_bar, chunksize=args.chunksize, compress=args.compress, ) sys.exit(failed) if __name__ == "__main__": try: main() except KeyboardInterrupt: print("# Exiting after Ctrl+C") xkbcommon-libxkbcommon-54ee7ac/test/xvfb-wrapper.c000066400000000000000000000135071510033435100224370ustar00rootroot00000000000000/* * Copyright © 2014 Ran Benita * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include #include "test.h" #include "xvfb-wrapper.h" static volatile bool xvfb_is_ready; static void sigusr1_handler(int signal) { xvfb_is_ready = true; } int xvfb_wrapper(x11_test_func_t test_func, void *private) { int ret = EXIT_SUCCESS; FILE * display_fd; char display_fd_string[32]; sigset_t mask; struct sigaction sa; char *xvfb_argv[] = { (char *) "Xvfb", (char *) "-displayfd", display_fd_string, NULL }; char *envp[] = { NULL }; pid_t xvfb_pid = 0; size_t counter = 0; char display[32] = ":"; size_t length; /* File descriptor to retrieve the display number */ display_fd = tmpfile(); if (display_fd == NULL){ fprintf(stderr, "Unable to create temporary file.\n"); goto err_display_fd; } snprintf(display_fd_string, sizeof(display_fd_string), "%d", fileno(display_fd)); /* Set SIGUSR1 to SIG_IGN so Xvfb will send us that signal when it's ready * to accept connections. In order to avoid race condition, we block the * until we are ready to process it. */ sigemptyset(&mask); sigaddset(&mask, SIGUSR1); sigprocmask(SIG_BLOCK, &mask, NULL); sa.sa_handler = sigusr1_handler; sa.sa_flags = SA_RESTART; sigemptyset(&sa.sa_mask); struct sigaction sa_old; sigaction(SIGUSR1, &sa, &sa_old); xvfb_is_ready = false; /* * Xvfb command: let the server find an available display. * * Note that it may generate multiple times the following output in stderr: * _XSERVTransSocketUNIXCreateListener: ...SocketCreateListener() failed * It is expected: this is the server trying the ports until it finds one * that works. */ ret = posix_spawnp(&xvfb_pid, "Xvfb", NULL, NULL, xvfb_argv, envp); if (ret != 0) { fprintf(stderr, "[ERROR] Cannot run Xvfb. posix_spawnp error %d: %s\n", ret, strerror(ret)); if (ret == ENOENT) { fprintf(stderr, "[ERROR] Xvfb may be missing. " "Please install the corresponding package, " "e.g. \"xvfb\" or \"xorg-x11-server-Xvfb\".\n"); } ret = TEST_SETUP_FAILURE; goto err_xvfd; } sigprocmask(SIG_UNBLOCK, &mask, NULL); /* Now wait for the SIGUSR1 signal that Xvfb is ready */ while (!xvfb_is_ready) { usleep(1000); if (++counter >= 3000) /* 3 seconds max wait */ break; } sigaction(SIGUSR1, &sa_old, NULL); /* Check if Xvfb is still alive */ pid_t pid = waitpid(xvfb_pid, NULL, WNOHANG); if (pid != 0) { fprintf(stderr, "ERROR: Xvfb not alive\n"); ret = TEST_SETUP_FAILURE; goto err_xvfd; } /* Retrieve the display number: Xvfd writes the display number as a newline- * terminated string; copy this number to form a proper display string. */ fseek(display_fd, 0, SEEK_SET); length = fread(&display[1], 1, sizeof(display) - 2, display_fd); if (length <= 0) { fprintf(stderr, "fread error: length=%zu\n", length); ret = TEST_SETUP_FAILURE; goto err_xvfd; } else { /* Drop the newline character */ display[length] = '\0'; } /* Run the function requiring a running X server. * Because it may call abort() via assert(), we fork to be able to * exit gracefully and not hang waiting for Xvfb. */ pid_t test_pid = fork(); switch (test_pid) { case -1: perror("fork"); ret = TEST_SETUP_FAILURE; break; case 0: fprintf(stderr, "Running test using Xvfb wrapper...\n"); ret = test_func(display, private); fprintf(stderr, "Test using Xvfb wrapper finished with code %d.\n", ret); _exit(ret); default: { int test_status = 0; pid_t test_pid2 = waitpid(test_pid, &test_status, 0); ret = (test_pid2 > 0 && WIFEXITED(test_status)) ? WEXITSTATUS(test_status) : EXIT_FAILURE; fprintf(stderr, "Test finished with code %d. " "Shutting down Xvfb (pid: %d)...\n", ret, xvfb_pid); } } err_xvfd: if (xvfb_pid > 0) { fprintf(stderr, "Sending SIGTERM to Xvfb...\n"); kill(xvfb_pid, SIGTERM); fprintf(stderr, "Waiting for Xvfb to exit (pid: %d)...\n", xvfb_pid); int xvfb_status = 0; if (waitpid(xvfb_pid, &xvfb_status, 0) <= 0) { perror("Xvfb waitpid failed."); } else if (WIFEXITED(xvfb_status)) { fprintf(stderr, "Xvfb shut down (pid: %d) with exit code %d.\n", xvfb_pid, WEXITSTATUS(xvfb_status)); } else { fprintf(stderr, "Xvfb shut down (pid: %d) abnormally.\n", xvfb_pid); } } fclose(display_fd); err_display_fd: return ret; } /* All X11_TEST functions are in the test_func_sec ELF section. * __start and __stop point to the start and end of that section. See the * __attribute__(section) documentation. */ DECLARE_TEST_ELF_SECTION_POINTERS(TEST_ELF_SECTION); int x11_tests_run(void) { int rc = 0; for (const struct test_function *t = &__start_test_func_sec; t < &__stop_test_func_sec; t++) { fprintf(stderr, "------ Running test: %s from %s ------\n", t->name, t->file); rc = xvfb_wrapper(t->func, NULL); if (rc != EXIT_SUCCESS) { break; } } return rc; } xkbcommon-libxkbcommon-54ee7ac/test/xvfb-wrapper.h000066400000000000000000000042311510033435100224360ustar00rootroot00000000000000/* * Copyright © 2014 Ran Benita * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ /* *This is a wrapper around X11 tests to make it faster to use for the simple * type of test cases. * * Use with the X11_TEST macro like this: * * X11_TEST(some_test) { * return 0; * } * * int main(void) { * return x11_tests_run(void); * } * */ #pragma once #include "config.h" typedef int (* x11_test_func_t)(const char* display, void *private); int xvfb_wrapper(x11_test_func_t f, void *private); int x11_tests_run(void); struct test_function { const char *name; /* function name */ const char *file; /* file name */ x11_test_func_t func; /* test function */ } __attribute__((aligned(16))); /** * Defines a struct test_function in a custom ELF section that we can then * loop over in x11_tests_run() to extract the tests. This removes the * need of manually adding the tests to a suite or listing them somewhere. */ #define TEST_ELF_SECTION test_func_sec #if defined(__APPLE__) && defined(__MACH__) #define SET_TEST_ELF_SECTION(_section) \ __attribute__((retain,used)) \ __attribute__((section("__DATA," STRINGIFY(_section)))) /* Custom section pointers. See: https://stackoverflow.com/a/22366882 */ #define DECLARE_TEST_ELF_SECTION_POINTERS(_section) \ extern const struct test_function CONCAT2(__start_, _section) \ __asm("section$start$__DATA$" STRINGIFY2(_section)); \ extern const struct test_function CONCAT2(__stop_, _section) \ __asm("section$end$__DATA$" STRINGIFY2(_section)) #else #define SET_TEST_ELF_SECTION(_section) \ __attribute__((retain,used)) \ __attribute__((section(STRINGIFY(_section)))) #define DECLARE_TEST_ELF_SECTION_POINTERS(_section) \ extern const struct test_function \ CONCAT2(__start_, _section), CONCAT2(__stop_, _section) #endif #define X11_TEST(_func) \ static int _func(const char* display, void *private); \ static const struct test_function _test_##_func \ SET_TEST_ELF_SECTION(TEST_ELF_SECTION) = { \ .name = #_func, \ .func = (_func), \ .file = __FILE__, \ }; \ static int _func(const char* display, void *private) xkbcommon-libxkbcommon-54ee7ac/tools/000077500000000000000000000000001510033435100200235ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/tools/check-messages.c000066400000000000000000000036041510033435100230540ustar00rootroot00000000000000/* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include "messages-codes.h" #include "messages.h" static xkb_message_code_t parse_message_code(char *raw_code) { xkb_message_code_t code; code = atoi(raw_code); if (!code && strstr(raw_code, "XKB-")) { return atoi(&(raw_code[4])); } else { return code; } } static void usage(char **argv) { printf("Usage: %s MESSAGE_CODES\n" "\n" "Check whether the given message codes are supported.\n", argv[0]); const struct xkb_message_entry *xkb_messages; size_t count = xkb_message_get_all(&xkb_messages); printf("\nCurrent supported messages:\n"); for (size_t idx = 0; idx < count; idx++) { printf("- XKB-%03u: %s\n", xkb_messages[idx].code, xkb_messages[idx].label); } } #define XKB_CHECK_MSG_ERROR_PREFIX "xkb-check-messages: ERROR: " #define MALFORMED_MESSAGE (1 << 2) #define UNSUPPORTED_MESSAGE (1 << 3) int main(int argc, char **argv) { setlocale(LC_ALL, ""); if (argc <= 1) { usage(argv); return EXIT_INVALID_USAGE; } int rc = 0; xkb_message_code_t code; const struct xkb_message_entry* entry; for (int k=1; k < argc; k++) { code = parse_message_code(argv[k]); if (!code) { fprintf(stderr, XKB_CHECK_MSG_ERROR_PREFIX "Malformed message code: %s\n", argv[k]); rc |= MALFORMED_MESSAGE; continue; } entry = xkb_message_get(code); if (entry == NULL) { fprintf(stderr, XKB_CHECK_MSG_ERROR_PREFIX "Unsupported message code: %s\n", argv[k]); rc |= UNSUPPORTED_MESSAGE; } } return rc; } xkbcommon-libxkbcommon-54ee7ac/tools/compile-compose.c000066400000000000000000000123211510033435100232610ustar00rootroot00000000000000/* * Copyright © 2021 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-keysyms.h" #include "xkbcommon/xkbcommon-compose.h" #include "src/compose/dump.h" #include "src/keysym.h" #include "tools/tools-common.h" static void usage(FILE *fp, char *progname) { fprintf(fp, "Usage: %s [--help] [--verbose] [--locale LOCALE] [--test] [FILE]\n", progname); fprintf(fp, "\n" "Compile a Compose file and print it\n" "\n" "Options:\n" " --help\n" " Print this help and exit\n" " --verbose\n" " Enable verbose debugging output\n" " --file FILE\n" " Specify a Compose file to load.\n" " DEPRECATED: use the positional argument instead.\n" " --locale LOCALE\n" " Specify the locale directly, instead of relying on the environment variables\n" " LC_ALL, LC_TYPE and LANG.\n" " --test\n" " Test compilation but do not print the Compose file.\n"); } int main(int argc, char *argv[]) { const char *locale = NULL; const char *path = NULL; enum xkb_compose_format format = XKB_COMPOSE_FORMAT_TEXT_V1; bool verbose = false; bool test = false; enum options { OPT_VERBOSE, OPT_FILE, OPT_LOCALE, OPT_TEST, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, OPT_VERBOSE}, {"file", required_argument, 0, OPT_FILE}, {"locale", required_argument, 0, OPT_LOCALE}, {"test", no_argument, 0, OPT_TEST}, {0, 0, 0, 0}, }; setlocale(LC_ALL, ""); /* Initialize the locale to use */ locale = setlocale(LC_CTYPE, NULL); if (!locale) locale = "C"; while (1) { int opt; int option_index = 0; opt = getopt_long(argc, argv, "h", opts, &option_index); if (opt == -1) break; switch (opt) { case OPT_VERBOSE: verbose = true; break; case OPT_FILE: path = optarg; fprintf(stderr, "WARNING: the flag --file is deprecated\n"); break; case OPT_LOCALE: locale = optarg; break; case OPT_TEST: test = true; break; case 'h': usage(stdout, argv[0]); return EXIT_SUCCESS; default: usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } } if (locale == NULL) { fprintf(stderr, "ERROR: Cannot determine the locale.\n"); usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } if (optind < argc && !isempty(argv[optind])) { /* Some positional arguments left: use a file */ if (path) { fprintf(stderr, "ERROR: Path already provided via the flag: --file\n"); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } path = argv[optind++]; if (optind < argc) { fprintf(stderr, "ERROR: Too many positional arguments\n"); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } } else if (is_pipe_or_regular_file(STDIN_FILENO)) { /* No positional argument: detect piping */ path = "-"; } struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!ctx) { fprintf(stderr, "ERROR: Couldn't create xkb context\n"); return EXIT_FAILURE; } if (verbose) tools_enable_verbose_logging(ctx); int ret = EXIT_FAILURE; struct xkb_compose_table *compose_table = NULL; if (path != NULL) { FILE *file; if (isempty(path) || strcmp(path, "-") == 0) { /* Read from stdin */ file = tools_read_stdin(); } else { /* Read from regular file */ file = fopen(path, "rb"); } if (file == NULL) { perror(path); goto file_error; } compose_table = xkb_compose_table_new_from_file(ctx, file, locale, format, XKB_COMPOSE_COMPILE_NO_FLAGS); fclose(file); if (!compose_table) { fprintf(stderr, "ERROR: Couldn't create compose from file: %s\n", path); goto out; } } else { compose_table = xkb_compose_table_new_from_locale(ctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (!compose_table) { fprintf(stderr, "ERROR: Couldn't create compose from locale \"%s\"\n", locale); goto out; } } if (test) { ret = EXIT_SUCCESS; goto out; } ret = xkb_compose_table_dump(stdout, compose_table) ? EXIT_SUCCESS : EXIT_FAILURE; out: xkb_compose_table_unref(compose_table); file_error: xkb_context_unref(ctx); return ret; } xkbcommon-libxkbcommon-54ee7ac/tools/compile-keymap.c000066400000000000000000000547711510033435100231210ustar00rootroot00000000000000/* * Copyright © 2018 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include #include #include "xkbcommon/xkbcommon.h" #include "tools-common.h" #include "src/utils.h" #include "src/keymap-formats.h" #define DEFAULT_INCLUDE_PATH_PLACEHOLDER "__defaults__" enum input_format { INPUT_FORMAT_AUTO = 0, INPUT_FORMAT_RMLVO, INPUT_FORMAT_KEYMAP }; enum output_format { OUTPUT_FORMAT_KEYMAP = 0, OUTPUT_FORMAT_RMLVO, OUTPUT_FORMAT_KCCGST, OUTPUT_FORMAT_KCCGST_YAML, OUTPUT_FORMAT_MODMAPS, }; static bool verbose = false; static const char *includes[64] = { 0 }; static size_t num_includes = 0; static bool test = false; static void usage(FILE *file, const char *progname) { fprintf(file, "Usage: %s [OPTIONS]\n" "\n" "Compile the given input to a keymap and print it\n" "\n" "General options:\n" " --help\n" " Print this help and exit\n" " --verbose\n" " Enable verbose debugging output\n" " --test\n" " Test compilation but do not print the keymap.\n" "\n" "Input options:\n" " --include\n" " Add the given path to the include path list. This option is\n" " order-dependent, include paths given first are searched first.\n" " If an include path is given, the default include path list is\n" " not used. Use --include-defaults to add the default include\n" " paths\n" " --include-defaults\n" " Add the default set of include directories.\n" " This option is order-dependent, include paths given first\n" " are searched first.\n" " --input-format \n" " The keymap format to use for parsing (default: '%d')\n" " --output-format \n" " The keymap format to use for serializing (default: '%d')\n" " --format \n" " The keymap format to use for both parsing and serializing\n" " --no-pretty\n" " Do not pretty-print when serializing a keymap\n" " --drop-unused\n" " Disable unused bits serialization\n" " --keymap \n" " --from-xkb \n" " Load the corresponding XKB file, ignore RMLVO options. If \n" " is \"-\" or missing, then load from stdin." " This option must not be used with --kccgst.\n" " --rules \n" " The XKB ruleset (default: '%s')\n" " --model \n" " The XKB model (default: '%s')\n" " --layout \n" " The XKB layout (default: '%s')\n" " --variant \n" " The XKB layout variant (default: '%s')\n" " --options \n" " The XKB options (default: '%s')\n" " --enable-environment-names\n" " Allow to set the default RMLVO values via the following environment variables:\n" " - XKB_DEFAULT_RULES\n" " - XKB_DEFAULT_MODEL\n" " - XKB_DEFAULT_LAYOUT\n" " - XKB_DEFAULT_VARIANT\n" " - XKB_DEFAULT_OPTIONS\n" " Note that this option may affect the default values of the previous options.\n" " This option must not be used with --keymap.\n" "\n" "Output options:\n" " --kccgst\n" " Print a keymap which only includes the KcCGST component names instead of the full keymap\n" " --kccgst-yaml\n" " Print the KcCGST component names in YAML format\n" " --rmlvo\n" " Print the full RMLVO with the defaults filled in for missing elements, in YAML format\n" " --modmaps\n" " Print real and virtual key modmaps and modifiers encodings in YAML format\n" "\n", progname, DEFAULT_INPUT_KEYMAP_FORMAT, DEFAULT_OUTPUT_KEYMAP_FORMAT, DEFAULT_XKB_RULES, DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT, DEFAULT_XKB_VARIANT ? DEFAULT_XKB_VARIANT : "", DEFAULT_XKB_OPTIONS ? DEFAULT_XKB_OPTIONS : ""); } static inline bool is_incompatible_with_keymap_input(enum output_format format) { switch (format) { case OUTPUT_FORMAT_KCCGST: case OUTPUT_FORMAT_KCCGST_YAML: case OUTPUT_FORMAT_RMLVO: return true; default: return false; } } static bool parse_options(int argc, char **argv, enum input_format *input_format_out, enum output_format *output_format_out, enum xkb_keymap_format *keymap_input_format, enum xkb_keymap_format *keymap_output_format, enum xkb_keymap_serialize_flags *serialize_flags, bool *use_env_names, char **path, struct xkb_rule_names *names) { enum input_format input_format = INPUT_FORMAT_AUTO; enum output_format output_format = OUTPUT_FORMAT_KEYMAP; enum options { /* General */ OPT_VERBOSE, OPT_TEST, /* Input */ OPT_INCLUDE, OPT_INCLUDE_DEFAULTS, OPT_KEYMAP, OPT_ENABLE_ENV_NAMES, OPT_KEYMAP_INPUT_FORMAT, OPT_KEYMAP_OUTPUT_FORMAT, OPT_KEYMAP_FORMAT, OPT_KEYMAP_NO_PRETTY, OPT_KEYMAP_DROP_UNUSED, OPT_RULES, OPT_MODEL, OPT_LAYOUT, OPT_VARIANT, OPT_OPTION, /* Output */ OPT_KCCGST, OPT_KCCGST_YAML, OPT_RMLVO, OPT_MODMAPS, }; static struct option opts[] = { /* * General */ {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, OPT_VERBOSE}, {"test", no_argument, 0, OPT_TEST}, /* * Input */ {"include", required_argument, 0, OPT_INCLUDE}, {"include-defaults", no_argument, 0, OPT_INCLUDE_DEFAULTS}, {"keymap", optional_argument, 0, OPT_KEYMAP}, /* Alias maintained for backward compatibility */ {"from-xkb", optional_argument, 0, OPT_KEYMAP}, {"enable-environment-names", no_argument, 0, OPT_ENABLE_ENV_NAMES}, {"input-format", required_argument, 0, OPT_KEYMAP_INPUT_FORMAT}, {"output-format", required_argument, 0, OPT_KEYMAP_OUTPUT_FORMAT}, {"format", required_argument, 0, OPT_KEYMAP_FORMAT}, {"no-pretty", no_argument, 0, OPT_KEYMAP_NO_PRETTY}, {"drop-unused", no_argument, 0, OPT_KEYMAP_DROP_UNUSED}, {"rules", required_argument, 0, OPT_RULES}, {"model", required_argument, 0, OPT_MODEL}, {"layout", required_argument, 0, OPT_LAYOUT}, {"variant", required_argument, 0, OPT_VARIANT}, {"options", required_argument, 0, OPT_OPTION}, /* * Output */ {"kccgst", no_argument, 0, OPT_KCCGST}, {"kccgst-yaml", no_argument, 0, OPT_KCCGST_YAML}, {"rmlvo", no_argument, 0, OPT_RMLVO}, {"modmaps", no_argument, 0, OPT_MODMAPS}, {0, 0, 0, 0}, }; *use_env_names = false; int option_index = 0; while (1) { option_index = 0; int c = getopt_long(argc, argv, "h", opts, &option_index); if (c == -1) break; switch (c) { /* General */ case 'h': usage(stdout, argv[0]); exit(0); case OPT_VERBOSE: verbose = true; break; case OPT_TEST: test = true; break; /* Input */ case OPT_INCLUDE: if (num_includes >= ARRAY_SIZE(includes)) goto too_many_includes; includes[num_includes++] = optarg; break; case OPT_INCLUDE_DEFAULTS: if (num_includes >= ARRAY_SIZE(includes)) goto too_many_includes; includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER; break; case OPT_KEYMAP: if (*use_env_names) goto keymap_env_error; if (input_format == INPUT_FORMAT_RMLVO) goto input_format_error; if (is_incompatible_with_keymap_input(output_format)) goto output_incompatible_with_keymap_input_error; input_format = INPUT_FORMAT_KEYMAP; /* Optional arguments require `=`, but we want to make this * requirement optional too, so that both `--keymap=xxx` and * `--keymap xxx` work. */ if (!optarg && argv[optind] && (argv[optind][0] != '-' || strcmp(argv[optind], "-") == 0 )) { *path = argv[optind++]; } else { *path = optarg; } break; case OPT_ENABLE_ENV_NAMES: if (input_format == INPUT_FORMAT_KEYMAP) goto keymap_env_error; *use_env_names = true; input_format = INPUT_FORMAT_RMLVO; break; case OPT_KEYMAP_INPUT_FORMAT: *keymap_input_format = xkb_keymap_parse_format(optarg); if (!(*keymap_input_format)) { fprintf(stderr, "ERROR: invalid --input-format: \"%s\"\n", optarg); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } break; case OPT_KEYMAP_OUTPUT_FORMAT: *keymap_output_format = xkb_keymap_parse_format(optarg); if (!(*keymap_output_format)) { fprintf(stderr, "ERROR: invalid --output-format: \"%s\"\n", optarg); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } break; case OPT_KEYMAP_FORMAT: *keymap_input_format = xkb_keymap_parse_format(optarg); if (!(*keymap_input_format)) { fprintf(stderr, "ERROR: invalid --format: \"%s\"\n", optarg); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } *keymap_output_format = *keymap_input_format; break; case OPT_KEYMAP_NO_PRETTY: *serialize_flags &= ~XKB_KEYMAP_SERIALIZE_PRETTY; break; case OPT_KEYMAP_DROP_UNUSED: *serialize_flags &= ~XKB_KEYMAP_SERIALIZE_KEEP_UNUSED; break; case OPT_RULES: if (input_format == INPUT_FORMAT_KEYMAP) goto input_format_error; names->rules = optarg; input_format = INPUT_FORMAT_RMLVO; break; case OPT_MODEL: if (input_format == INPUT_FORMAT_KEYMAP) goto input_format_error; names->model = optarg; input_format = INPUT_FORMAT_RMLVO; break; case OPT_LAYOUT: if (input_format == INPUT_FORMAT_KEYMAP) goto input_format_error; names->layout = optarg; input_format = INPUT_FORMAT_RMLVO; break; case OPT_VARIANT: if (input_format == INPUT_FORMAT_KEYMAP) goto input_format_error; names->variant = optarg; input_format = INPUT_FORMAT_RMLVO; break; case OPT_OPTION: if (input_format == INPUT_FORMAT_KEYMAP) goto input_format_error; names->options = optarg; input_format = INPUT_FORMAT_RMLVO; break; /* Output */ case OPT_KCCGST: assert(is_incompatible_with_keymap_input(OUTPUT_FORMAT_KCCGST)); if (input_format == INPUT_FORMAT_KEYMAP) goto output_incompatible_with_keymap_input_error; if (output_format != OUTPUT_FORMAT_KEYMAP && output_format != OUTPUT_FORMAT_KCCGST) goto output_format_error; output_format = OUTPUT_FORMAT_KCCGST; break; case OPT_KCCGST_YAML: assert(is_incompatible_with_keymap_input(OUTPUT_FORMAT_KCCGST_YAML)); if (input_format == INPUT_FORMAT_KEYMAP) goto output_incompatible_with_keymap_input_error; if (output_format != OUTPUT_FORMAT_KEYMAP && output_format != OUTPUT_FORMAT_KCCGST_YAML) goto output_format_error; output_format = OUTPUT_FORMAT_KCCGST_YAML; break; case OPT_RMLVO: assert(is_incompatible_with_keymap_input(OUTPUT_FORMAT_RMLVO)); if (input_format == INPUT_FORMAT_KEYMAP) goto output_incompatible_with_keymap_input_error; if (output_format != OUTPUT_FORMAT_KEYMAP && output_format != OUTPUT_FORMAT_RMLVO) goto output_format_error; output_format = OUTPUT_FORMAT_RMLVO; break; case OPT_MODMAPS: assert(!is_incompatible_with_keymap_input(OUTPUT_FORMAT_MODMAPS)); if (output_format != OUTPUT_FORMAT_KEYMAP && output_format != OUTPUT_FORMAT_MODMAPS) goto output_format_error; output_format = OUTPUT_FORMAT_MODMAPS; break; default: goto invalid_usage; } } if (optind < argc && !isempty(argv[optind])) { /* Some positional arguments left: use as a keymap input */ if (input_format != INPUT_FORMAT_AUTO || is_incompatible_with_keymap_input(output_format)) { goto too_much_arguments; } input_format = INPUT_FORMAT_KEYMAP; *path = argv[optind++]; if (optind < argc) { /* Further positional arguments is an error */ too_much_arguments: fprintf(stderr, "ERROR: Too many positional arguments\n"); goto invalid_usage; } } else if (is_pipe_or_regular_file(STDIN_FILENO) && input_format != INPUT_FORMAT_RMLVO && !is_incompatible_with_keymap_input(output_format)) { /* No positional argument: detect piping */ input_format = INPUT_FORMAT_KEYMAP; } if (isempty(*path) || strcmp(*path, "-") == 0) *path = NULL; *input_format_out = input_format; *output_format_out = output_format; return true; input_format_error: fprintf(stderr, "ERROR: Cannot use RMLVO options with keymap input\n"); goto invalid_usage; keymap_env_error: fprintf(stderr, "ERROR: --keymap is not compatible with " "--enable-environment-names\n"); goto invalid_usage; output_format_error: fprintf(stderr, "ERROR: Cannot mix output formats\n"); goto invalid_usage; output_incompatible_with_keymap_input_error: fprintf(stderr, "ERROR: Output format incompatible with keymap input\n"); goto invalid_usage; too_many_includes: fprintf(stderr, "ERROR: too many includes (max: %zu)\n", ARRAY_SIZE(includes)); invalid_usage: usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } static int print_rmlvo(struct xkb_context *ctx, struct xkb_rule_names *rmlvo) { /* Resolve default RMLVO values */ struct xkb_rule_names resolved = { NULL }; xkb_components_names_from_rules(ctx, rmlvo, &resolved, NULL); if (test) return EXIT_SUCCESS; printf("rules: \"%s\"\nmodel: \"%s\"\nlayout: \"%s\"\nvariant: \"%s\"\n" "options: \"%s\"\n", resolved.rules, resolved.model, resolved.layout, resolved.variant ? resolved.variant : "", resolved.options ? resolved.options : ""); return EXIT_SUCCESS; } static int print_kccgst(struct xkb_context *ctx, struct xkb_rule_names *rmlvo, bool yaml) { struct xkb_component_names kccgst = { 0 }; /* Resolve missing RMLVO values, then resolve the RMLVO names to * KcCGST components */ if (!xkb_components_names_from_rules(ctx, rmlvo, NULL, &kccgst)) return EXIT_FAILURE; if (test) goto out; if (yaml) { printf("keycodes: \"%s\"\n" "types: \"%s\"\n" "compat: \"%s\"\n" "symbols: \"%s\"\n", kccgst.keycodes, kccgst.types, kccgst.compatibility, kccgst.symbols); /* Contrary to the previous components, geometry can be empty */ if (!isempty(kccgst.geometry)) { printf("geometry: \"%s\"\n", kccgst.geometry); } } else { printf("xkb_keymap {\n" " xkb_keycodes { include \"%s\" };\n" " xkb_types { include \"%s\" };\n" " xkb_compat { include \"%s\" };\n" " xkb_symbols { include \"%s\" };\n", kccgst.keycodes, kccgst.types, kccgst.compatibility, kccgst.symbols); /* Contrary to the previous components, geometry can be empty */ if (!isempty(kccgst.geometry)) { printf(" xkb_geometry { include \"%s\" };\n", kccgst.geometry); } printf("};\n"); } out: free(kccgst.keycodes); free(kccgst.types); free(kccgst.compatibility); free(kccgst.symbols); free(kccgst.geometry); return EXIT_SUCCESS; } static struct xkb_keymap* load_keymap(struct xkb_context *ctx, enum xkb_keymap_format keymap_input_format, enum input_format format, const struct xkb_rule_names *rmlvo, const char *path) { if (format == INPUT_FORMAT_KEYMAP) { FILE *file = NULL; if (path) { /* Read from regular file */ file = fopen(path, "rb"); } else { /* Read from stdin */ file = tools_read_stdin(); } if (!file) { fprintf(stderr, "ERROR: Failed to open keymap file \"%s\": %s\n", path ? path : "stdin", strerror(errno)); return NULL; } return xkb_keymap_new_from_file(ctx, file, keymap_input_format, XKB_KEYMAP_COMPILE_NO_FLAGS); } else { return xkb_keymap_new_from_names2(ctx, rmlvo, keymap_input_format, XKB_KEYMAP_COMPILE_NO_FLAGS); } } static int print_keymap(struct xkb_context *ctx, enum xkb_keymap_format keymap_input_format, enum xkb_keymap_format keymap_output_format, enum input_format format, enum xkb_keymap_serialize_flags flags, const struct xkb_rule_names *rmlvo, const char *path) { int ret = EXIT_SUCCESS; struct xkb_keymap *keymap = load_keymap(ctx, keymap_input_format, format, rmlvo, path); if (!keymap) { fprintf(stderr, "ERROR: Couldn't create xkb keymap\n"); ret = EXIT_FAILURE; } else if (!test) { char* keymap_string = xkb_keymap_get_as_string2(keymap, keymap_output_format, flags); if (!keymap_string) { fprintf(stderr, "ERROR: Couldn't get the keymap string\n"); } else { fputs(keymap_string, stdout); free(keymap_string); } } xkb_keymap_unref(keymap); return ret; } static int print_modmaps(struct xkb_context *ctx, enum xkb_keymap_format keymap_input_format, enum input_format format, const struct xkb_rule_names *rmlvo, const char *path) { int ret = EXIT_SUCCESS; struct xkb_keymap *keymap = load_keymap(ctx, keymap_input_format, format, rmlvo, path); if (!keymap) { fprintf(stderr, "ERROR: Couldn't create xkb keymap\n"); ret = EXIT_FAILURE; } else if (!test) { print_modifiers_encodings(keymap); printf("\n"); print_keys_modmaps(keymap); } xkb_keymap_unref(keymap); return ret; } int main(int argc, char **argv) { struct xkb_context *ctx; char *keymap_path = NULL; struct xkb_rule_names names = { 0 }; bool use_env_names = false; enum xkb_keymap_format keymap_input_format = DEFAULT_INPUT_KEYMAP_FORMAT; enum xkb_keymap_format keymap_output_format = DEFAULT_OUTPUT_KEYMAP_FORMAT; enum xkb_keymap_serialize_flags serialize_flags = (enum xkb_keymap_serialize_flags) DEFAULT_KEYMAP_SERIALIZE_FLAGS; int rc = 1; setlocale(LC_ALL, ""); if (argc < 1) { usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } enum input_format input_format = INPUT_FORMAT_AUTO; enum output_format output_format = OUTPUT_FORMAT_KEYMAP; if (!parse_options(argc, argv, &input_format, &output_format, &keymap_input_format, &keymap_output_format, &serialize_flags, &use_env_names, &keymap_path, &names)) return EXIT_INVALID_USAGE; enum xkb_context_flags ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES; if (!use_env_names) ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES; ctx = xkb_context_new(ctx_flags); assert(ctx); if (verbose) tools_enable_verbose_logging(ctx); if (num_includes == 0) includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER; for (size_t i = 0; i < num_includes; i++) { const char *include = includes[i]; if (strcmp(include, DEFAULT_INCLUDE_PATH_PLACEHOLDER) == 0) xkb_context_include_path_append_default(ctx); else xkb_context_include_path_append(ctx, include); } switch (output_format) { case OUTPUT_FORMAT_RMLVO: assert(input_format != INPUT_FORMAT_KEYMAP); rc = print_rmlvo(ctx, &names); break; case OUTPUT_FORMAT_KCCGST: assert(input_format != INPUT_FORMAT_KEYMAP); rc = print_kccgst(ctx, &names, false); break; case OUTPUT_FORMAT_KCCGST_YAML: assert(input_format != INPUT_FORMAT_KEYMAP); rc = print_kccgst(ctx, &names, true); break; case OUTPUT_FORMAT_MODMAPS: rc = print_modmaps(ctx, keymap_input_format, input_format, &names, keymap_path); break; default: rc = print_keymap(ctx, keymap_input_format, keymap_output_format, input_format, serialize_flags, &names, keymap_path); } xkb_context_unref(ctx); return rc; } xkbcommon-libxkbcommon-54ee7ac/tools/export-keysyms.c000066400000000000000000000050071510033435100232140ustar00rootroot00000000000000/* * Copyright © 2024 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #if HAVE_ICU #include #endif #include "xkbcommon/xkbcommon.h" #include "src/keysym.h" static void print_char_name(uint32_t cp) { #if HAVE_ICU char char_name[256]; UErrorCode pErrorCode = 0; int32_t count = u_charName((UChar32)cp, U_CHAR_NAME_ALIAS, char_name, sizeof(char_name), &pErrorCode); if (count <= 0) { count = u_charName((UChar32)cp, U_EXTENDED_CHAR_NAME, char_name, sizeof(char_name), &pErrorCode); } if (count > 0) { printf(" %s", char_name); } #endif } int main(int argc, char **argv) { bool explicit = !(argc > 1 && strcmp("all", argv[1]) == 0); int idx = 1 + !explicit; bool char_names = argc > idx && strcmp("names", argv[idx]) == 0; #if !HAVE_ICU if (char_names) fprintf(stderr, "ERROR: names argument requires ICU.\n"); #endif setlocale(LC_ALL, ""); struct xkb_keysym_iterator *iter = xkb_keysym_iterator_new(explicit); while (xkb_keysym_iterator_next(iter)) { xkb_keysym_t ks = xkb_keysym_iterator_get_keysym(iter); printf("0x%04x:\n", ks); char name[XKB_KEYSYM_NAME_MAX_SIZE]; xkb_keysym_iterator_get_name(iter, name, sizeof(name)); printf(" name: %s\n", name); // char utf8[7]; // int count = xkb_keysym_to_utf8(ks, utf8, sizeof(utf8)); uint32_t cp = xkb_keysym_to_utf32(ks); if (cp) { printf(" code point: 0x%04X", cp); if (char_names) { printf(" #"); print_char_name(cp); } printf("\n"); } xkb_keysym_t ks2; if ((ks2 = xkb_keysym_to_lower(ks)) != ks) { xkb_keysym_get_name(ks2, name, sizeof(name)); printf(" lower: 0x%04x # %s", ks2, name); if (char_names) { cp = xkb_keysym_to_utf32(ks2); print_char_name(cp); } printf("\n"); } if ((ks2 = xkb_keysym_to_upper(ks)) != ks) { xkb_keysym_get_name(ks2, name, sizeof(name)); printf(" upper: 0x%04x # %s", ks2, name); if (char_names) { cp = xkb_keysym_to_utf32(ks2); print_char_name(cp); } printf("\n"); } }; xkb_keysym_iterator_unref(iter); } xkbcommon-libxkbcommon-54ee7ac/tools/how-to-type.c000066400000000000000000000723501510033435100223720ustar00rootroot00000000000000/* * Copyright © 2020 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-compose.h" #include "xkbcommon/xkbcommon-keysyms.h" #include "src/compose/constants.h" #include "src/darray.h" #include "src/keysym.h" #include "src/keymap-formats.h" #include "src/utils.h" #include "src/utf8-decoding.h" #include "tools-common.h" #define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr)))) #define MAX_TYPE_MAP_ENTRIES 100 static uint32_t parse_char_or_codepoint(const char *raw) { size_t raw_length = strlen_safe(raw); size_t length = 0; if (!raw_length) return INVALID_UTF8_CODE_POINT; /* Try to parse the parameter as a UTF-8 encoded single character */ uint32_t codepoint = utf8_next_code_point(raw, raw_length, &length); /* If parsing failed or did not consume all the string, then try other formats */ if (codepoint == INVALID_UTF8_CODE_POINT || length == 0 || length != raw_length) { char *endp; long val; int base = 10; /* Detect U+NNNN format standard Unicode code point format */ if (raw_length >= 2 && raw[0] == 'U' && raw[1] == '+') { base = 16; raw += 2; } /* Use strtol with explicit bases instead of `0` in order to avoid * unexpected parsing as octal. */ for (; base <= 16; base += 6) { errno = 0; val = strtol(raw, &endp, base); if (errno != 0 || !isempty(endp) || val < 0 || val > 0x10FFFF) { val = -1; } else { break; } } if (val < 0) { fprintf(stderr, "ERROR: Failed to convert argument to Unicode code point\n"); return INVALID_UTF8_CODE_POINT; } codepoint = (uint32_t) val; } return codepoint; } static void usage(FILE *fp, const char *argv0) { fprintf(fp, "Usage: %s [--help] [--verbose] [--keysym] [--disable-compose] " "[--rules ] [--model ] " "[--layout ] [--variant ] " "[--options ] [--enable-environment-names] " "\n", argv0); fprintf( fp, "\n" "Prints the key combinations (keycode + modifiers) in the keymap's layouts which\n" "would produce the given Unicode code point or keysym.\n" "\n" " is either:\n" "- a single character (requires a terminal which uses UTF-8 character encoding);\n" "- a Unicode code point, interpreted as hexadecimal if prefixed with '0x' or 'U+'\n" " else as decimal;\n" "- a keysym if either the previous interpretations failed or if --keysym is used. \n" " The parameter is then either a keysym name or a numeric value (hexadecimal \n" " if prefixed with '0x' else decimal). Note that values '0' .. '9' are special: \n" " they are both names and numeric values. The default interpretation is names; \n" " use the hexadecimal form '0x0' .. '0x9' in order to interpret as numeric values.\n" "\n" "Options:\n" " --help\n" " Print this help and exit\n" " --verbose\n" " Enable verbose debugging output\n" " --keysym\n" " Treat the argument only as a keysym\n" " --disable-compose\n" " Disable Compose support to query combinations involving e.g. dead keys\n" "\n" "XKB-specific options:\n" " --format \n" " The keymap format to use (default: %d)\n" " --keymap=\n" " Load the corresponding XKB file, ignore RMLVO options. If \n" " is \"-\" or missing, then load from stdin.\n" " --rules \n" " The XKB ruleset (default: '%s')\n" " --model \n" " The XKB model (default: '%s')\n" " --layout \n" " The XKB layout (default: '%s')\n" " --variant \n" " The XKB layout variant (default: '%s')\n" " --options \n" " The XKB options (default: '%s')\n" " --enable-environment-names\n" " Allow to set the default RMLVO values via the following environment variables:\n" " - XKB_DEFAULT_RULES\n" " - XKB_DEFAULT_MODEL\n" " - XKB_DEFAULT_LAYOUT\n" " - XKB_DEFAULT_VARIANT\n" " - XKB_DEFAULT_OPTIONS\n" " Note that this option may affect the default values of the previous options.\n" "\n", DEFAULT_INPUT_KEYMAP_FORMAT, DEFAULT_XKB_RULES, DEFAULT_XKB_MODEL, DEFAULT_XKB_LAYOUT, DEFAULT_XKB_VARIANT ? DEFAULT_XKB_VARIANT : "", DEFAULT_XKB_OPTIONS ? DEFAULT_XKB_OPTIONS : ""); } enum input_keymap_source { KEYMAP_SOURCE_AUTO, KEYMAP_SOURCE_RMLVO, KEYMAP_SOURCE_FILE }; static int parse_options(int argc, char **argv, bool *verbose, bool *keysym_mode, xkb_keysym_t *keysym, enum input_keymap_source *keymap_source, enum xkb_keymap_format *keymap_input_format, const char **keymap_path, bool *use_env_names, struct xkb_rule_names *names, bool *use_compose) { enum options { OPT_VERBOSE, OPT_KEYSYM, OPT_DISABLE_COMPOSE, OPT_ENABLE_ENV_NAMES, OPT_KEYMAP_FORMAT, OPT_KEYMAP, OPT_RULES, OPT_MODEL, OPT_LAYOUT, OPT_VARIANT, OPT_OPTIONS, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, OPT_VERBOSE}, {"keysym", no_argument, 0, OPT_KEYSYM}, {"disable-compose", no_argument, 0, OPT_DISABLE_COMPOSE}, {"enable-environment-names", no_argument, 0, OPT_ENABLE_ENV_NAMES}, {"format", required_argument, 0, OPT_KEYMAP_FORMAT}, {"keymap", optional_argument, 0, OPT_KEYMAP}, {"rules", required_argument, 0, OPT_RULES}, {"model", required_argument, 0, OPT_MODEL}, {"layout", required_argument, 0, OPT_LAYOUT}, {"variant", required_argument, 0, OPT_VARIANT}, {"options", required_argument, 0, OPT_OPTIONS}, {0, 0, 0, 0}, }; while (1) { int opt; int option_index = 0; opt = getopt_long(argc, argv, "h", opts, &option_index); if (opt == -1) break; switch (opt) { case OPT_VERBOSE: *verbose = true; break; case OPT_KEYSYM: *keysym_mode = true; break; case OPT_DISABLE_COMPOSE: *use_compose = false; break; case OPT_ENABLE_ENV_NAMES: if (*keymap_source == KEYMAP_SOURCE_FILE) goto keymap_env_error; *use_env_names = true; *keymap_source = KEYMAP_SOURCE_RMLVO; break; case OPT_KEYMAP_FORMAT: *keymap_input_format = xkb_keymap_parse_format(optarg); if (!*keymap_input_format) { fprintf(stderr, "ERROR: invalid --format \"%s\"\n", optarg); goto invalid_usage; } break; case OPT_KEYMAP: if (*keymap_source == KEYMAP_SOURCE_RMLVO) goto keymap_source_error; *keymap_source = KEYMAP_SOURCE_FILE; *keymap_path = optarg; break; case OPT_RULES: if (*keymap_source == KEYMAP_SOURCE_FILE) goto keymap_source_error; names->rules = optarg; *keymap_source = KEYMAP_SOURCE_RMLVO; break; case OPT_MODEL: if (*keymap_source == KEYMAP_SOURCE_FILE) goto keymap_source_error; names->model = optarg; *keymap_source = KEYMAP_SOURCE_RMLVO; break; case OPT_LAYOUT: if (*keymap_source == KEYMAP_SOURCE_FILE) goto keymap_source_error; names->layout = optarg; *keymap_source = KEYMAP_SOURCE_RMLVO; break; case OPT_VARIANT: if (*keymap_source == KEYMAP_SOURCE_FILE) goto keymap_source_error; names->variant = optarg; *keymap_source = KEYMAP_SOURCE_RMLVO; break; case OPT_OPTIONS: if (*keymap_source == KEYMAP_SOURCE_FILE) goto keymap_source_error; names->options = optarg; *keymap_source = KEYMAP_SOURCE_RMLVO; break; case 'h': usage(stdout, argv[0]); exit(EXIT_SUCCESS); default: goto invalid_usage; } } if (argc - optind != 1) { fprintf(stderr, "ERROR: missing positional parameter\n"); goto invalid_usage; } /* Check for keymap input */ if (*keymap_source == KEYMAP_SOURCE_AUTO && is_pipe_or_regular_file(STDIN_FILENO)) { /* Piping detected */ *keymap_source = KEYMAP_SOURCE_FILE; } if (isempty(*keymap_path) || strcmp(*keymap_path, "-") == 0) *keymap_path = NULL; *keysym = XKB_KEY_NoSymbol; if (!*keysym_mode) { /* Try to parse code point */ const uint32_t codepoint = parse_char_or_codepoint(argv[optind]); if (codepoint != INVALID_UTF8_CODE_POINT) { *keysym = xkb_utf32_to_keysym(codepoint); if (*keysym == XKB_KEY_NoSymbol) { fprintf(stderr, "ERROR: Failed to convert code point to keysym\n"); goto invalid_usage; } } else { /* Try to parse as keysym */ } } if (*keysym == XKB_KEY_NoSymbol) { /* Try to parse keysym name or hexadecimal value (0xNNNN) */ *keysym = xkb_keysym_from_name(argv[optind], XKB_KEYSYM_NO_FLAGS); if (*keysym == XKB_KEY_NoSymbol) { /* Try to parse numeric keysym in base 10, without prefix */ char *endp = NULL; errno = 0; const long int val = strtol(argv[optind], &endp, 10); if (errno != 0 || !isempty(endp) || val <= 0 || val > XKB_KEYSYM_MAX) { fprintf(stderr, "ERROR: Failed to convert argument to keysym\n"); goto invalid_usage; } *keysym = (uint32_t) val; } } return EXIT_SUCCESS; keymap_env_error: fprintf(stderr, "ERROR: --keymap is not compatible with " "--enable-environment-names\n"); goto invalid_usage; keymap_source_error: fprintf(stderr, "ERROR: Cannot use RMLVO options with keymap input\n"); goto invalid_usage; invalid_usage: usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } static struct xkb_keymap * load_keymap(struct xkb_context *ctx, enum input_keymap_source keymap_source, enum xkb_keymap_format keymap_format, const char *keymap_path, struct xkb_rule_names *names) { if (keymap_source == KEYMAP_SOURCE_FILE) { FILE *file = NULL; if (keymap_path) { /* Read from regular file */ file = fopen(keymap_path, "rb"); } else { /* Read from stdin */ file = tools_read_stdin(); } if (!file) { fprintf(stderr, "ERROR: Failed to open keymap file \"%s\": %s\n", keymap_path ? keymap_path : "stdin", strerror(errno)); return NULL; } return xkb_keymap_new_from_file(ctx, file, keymap_format, XKB_KEYMAP_COMPILE_NO_FLAGS); } else { return xkb_keymap_new_from_names2(ctx, names, keymap_format, XKB_KEYMAP_COMPILE_NO_FLAGS); } } /** The left-hand side of a Compose sequence */ struct compose_lhs { size_t count; xkb_keysym_t keysyms[COMPOSE_MAX_LHS_LEN]; }; typedef darray(struct compose_lhs) darray_compose; /** Given a keysym, gather the Compose sequences that produce it */ static bool lookup_compose_sequences(struct xkb_compose_table *table, darray_compose *entries, xkb_keysym_t keysym) { struct xkb_compose_table_iterator *iter = xkb_compose_table_iterator_new(table); if (!iter) { fprintf(stderr, "ERROR: cannot iterate Compose table\n"); return false; } struct xkb_compose_table_entry *entry; while ((entry = xkb_compose_table_iterator_next(iter))) { if (keysym != xkb_compose_table_entry_keysym(entry)) continue; size_t count = 0; const xkb_keysym_t * const seq = xkb_compose_table_entry_sequence(entry, &count); const darray_size_t idx = darray_size(*entries); darray_resize0(*entries, idx + 1); for (size_t k = 0; k < count; k++) { darray_item(*entries, idx).keysyms[k] = seq[k]; } darray_item(*entries, idx).count = count; } xkb_compose_table_iterator_free(iter); return true; } /** The location in a keymap of a keysym used in a Compose sequence */ struct keysym_entry { xkb_keycode_t keycode; xkb_layout_index_t layout; xkb_level_index_t level; xkb_mod_mask_t mask; }; /** A keysym used in a Compose sequence and all its location in the keymap */ struct keysym_entries { xkb_keysym_t keysym; darray(struct keysym_entry) entries; }; typedef darray(struct keysym_entries) darray_keysym_entries; /** Comparison function to sort entries and display user-friendly key combos */ static int keysym_entry_compare(const void *a, const void *b) { const struct keysym_entry * const e1 = a; const struct keysym_entry * const e2 = b; if (e1->layout < e2->layout) return -1; if (e1->layout > e2->layout) return 1; if (e1->level < e2->level) return -1; if (e1->level > e2->level) return 1; if (e1->keycode < e2->keycode) return -1; if (e1->keycode > e2->keycode) return 1; return 0; } static void darray_keysym_entries_free(darray_keysym_entries *entries) { struct keysym_entries *e; darray_foreach(e, *entries) darray_free(e->entries); darray_free(*entries); } /** Lookup for an existing keysym entry and possibly insert it if it is missing */ static struct keysym_entries * lookup_keysym_entries(darray_keysym_entries *entries, xkb_keysym_t keysym, bool insert) { /* We do not expect a large set of keysym, so a simple linear search is fine */ struct keysym_entries *e; darray_foreach(e, *entries) { if (e->keysym == keysym) return e; } if (insert) { const darray_size_t idx = darray_size(*entries); const struct keysym_entries new = { .keysym = keysym, .entries = darray_new() }; darray_append(*entries, new); return &darray_item(*entries, idx); } else { return NULL; } } /* These are fixed */ #define SHIFT_MASK UINT32_C(0x1) #define LOCK_MASK UINT32_C(0x2) #define SHIFT_LOCK_MASK (SHIFT_MASK | LOCK_MASK) /** * Given a keysym, add its position in the keymap if it is used in a * Compose sequence */ static bool add_compose_keysym_entry(struct xkb_keymap *keymap, darray_keysym_entries *entries, xkb_keysym_t keysym, xkb_keycode_t keycode, xkb_layout_index_t layout, xkb_level_index_t level) { struct keysym_entries * const entry = lookup_keysym_entries(entries, keysym, false); if (!entry) return false; /* * The keysym position may be reached by multiple modifiers combinations: * append an entry for all but combo including another one, so that we * avoid combinatorial explosion. */ xkb_mod_mask_t masks[MAX_TYPE_MAP_ENTRIES]; bool skip[MAX_TYPE_MAP_ENTRIES] = {0}; const size_t num_masks = xkb_keymap_key_get_mods_for_level( keymap, keycode, layout, level, masks, ARRAY_SIZE(masks) ); for (size_t j = 0; j < num_masks; j++) { for (size_t k = j + 1; k < num_masks; k++) { /* skip “shift cancel lock” */ if (!masks[j]) { if (masks[k] == SHIFT_LOCK_MASK) skip[k] = true; else continue; } else if (!masks[k]) { if (masks[j] == SHIFT_LOCK_MASK) skip[j] = true; else continue; } /* skip any mask that contains another mask of the list */ if ((masks[j] & masks[k]) == masks[j]) skip[k] = true; else if ((masks[j] & masks[k]) == masks[k]) skip[j] = true; } if (skip[j]) continue; const struct keysym_entry new = { .keycode = keycode, .layout = layout, .level = level, .mask = masks[j] }; darray_append(entry->entries, new); } return true; } static void print_combo(struct xkb_keymap *keymap, xkb_mod_index_t num_mods, xkb_keycode_t keycode, const char *key_name, xkb_layout_index_t layout, const char *layout_name, xkb_level_index_t level, xkb_mod_mask_t mask) { printf("%-8u %-9s %-8u %-20s %-7u [ ", keycode, key_name, layout + 1, layout_name, level + 1); for (xkb_mod_index_t mod = 0; mod < num_mods; mod++) { const xkb_mod_mask_t mod_mask = xkb_keymap_mod_get_mask2(keymap, mod); if ((mask & mod_mask) != mod_mask) continue; printf("%s ", xkb_keymap_mod_get_name(keymap, mod)); } printf("]\n"); } int main(int argc, char *argv[]) { setlocale(LC_ALL, ""); struct xkb_context *ctx = NULL; struct xkb_keymap *keymap = NULL; bool verbose = false; bool use_compose = true; bool use_env_names = false; enum input_keymap_source keymap_source = KEYMAP_SOURCE_AUTO; enum xkb_keymap_format keymap_format = DEFAULT_INPUT_KEYMAP_FORMAT; const char *keymap_path = NULL; bool keysym_mode = false; xkb_keysym_t keysym = XKB_KEY_NoSymbol; struct xkb_rule_names names = { .rules = NULL, .model = NULL, .layout = NULL, .variant = NULL, .options = NULL, }; int ret = parse_options(argc, argv, &verbose, &keysym_mode, &keysym, &keymap_source, &keymap_format, &keymap_path, &use_env_names, &names, &use_compose); if (ret != EXIT_SUCCESS) goto err; char name[XKB_KEYSYM_NAME_MAX_SIZE]; ret = xkb_keysym_get_name(keysym, name, sizeof(name)); if (ret < 0 || (size_t) ret >= sizeof(name)) { fprintf(stderr, "ERROR: Failed to get name of keysym\n"); ret = EXIT_FAILURE; goto err; } ret = EXIT_FAILURE; const enum xkb_context_flags ctx_flags = (use_env_names) ? XKB_CONTEXT_NO_FLAGS : XKB_CONTEXT_NO_ENVIRONMENT_NAMES; ctx = xkb_context_new(ctx_flags); if (!ctx) { fprintf(stderr, "ERROR: Failed to create XKB context\n"); goto err; } if (verbose) tools_enable_verbose_logging(ctx); keymap = load_keymap(ctx, keymap_source, keymap_format, keymap_path, &names); if (!keymap) { fprintf(stderr, "ERROR: Failed to create XKB keymap\n"); goto err; } /* Gather Compose sequences producing the given keysym */ darray_compose compose_entries = darray_new(); darray_keysym_entries keysym_entries = darray_new(); if (use_compose) { /* Load the Compose table */ const char *locale = setlocale(LC_CTYPE, NULL); struct xkb_compose_table * const compose_table = xkb_compose_table_new_from_locale(ctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (!compose_table) { fprintf(stderr, "Couldn't create compose from locale\n"); goto err; } /* Get sequences producing the keysym */ lookup_compose_sequences(compose_table, &compose_entries, keysym); xkb_compose_table_unref(compose_table); /* Get all the keysyms required in sequences */ struct compose_lhs *compose_entry; darray_foreach(compose_entry, compose_entries) { for (size_t k = 0; k < compose_entry->count; k++) { lookup_keysym_entries(&keysym_entries, compose_entry->keysyms[k], true); } } } printf("keysym: %s (%#06"PRIx32")\n\n", name, keysym); printf("=== Direct access ===\n\n"); printf("%-8s %-9s %-8s %-20s %-7s %-s\n", "KEYCODE", "KEY NAME", "LAYOUT", "LAYOUT NAME", "LEVEL#", "MODIFIERS"); /* Iterate over all the positions in the keymap */ const xkb_keycode_t min_keycode = xkb_keymap_min_keycode(keymap); const xkb_keycode_t max_keycode = xkb_keymap_max_keycode(keymap); const xkb_mod_index_t num_mods = xkb_keymap_num_mods(keymap); darray(xkb_keysym_t) key_compose_keysyms = darray_new(); for (xkb_keycode_t keycode = min_keycode; keycode <= max_keycode; keycode++) { const char* const key_name = xkb_keymap_key_get_name(keymap, keycode); if (!key_name) { continue; } const xkb_layout_index_t num_layouts = xkb_keymap_num_layouts_for_key(keymap, keycode); for (xkb_layout_index_t layout = 0; layout < num_layouts; layout++) { const char *layout_name = xkb_keymap_layout_get_name(keymap, layout); if (!layout_name) { layout_name = "?"; } const xkb_level_index_t num_levels = xkb_keymap_num_levels_for_key(keymap, keycode, layout); darray_resize(key_compose_keysyms, 0); for (xkb_level_index_t level = 0; level < num_levels; level++) { const xkb_keysym_t *syms; const int num_syms = xkb_keymap_key_get_syms_by_level( keymap, keycode, layout, level, &syms ); if (num_syms != 1) { /* We only deal with levels with exactly one keysym */ continue; } if (syms[0] != keysym) { /* * If it is not the keysym we look for, then check if it is * a keysym that contribute to a Compose sequence that * produce it. For our use case there is no point to list * Compose sequences producing a keysym that is also in the * the sequence producing it. * * Keep only the lowest level, so that we avoid combinatorial * explosion. */ bool found = false; /* Look for the current keysym in previous levels */ for (darray_size_t k = 0; k < darray_size(key_compose_keysyms); k++) { if (darray_item(key_compose_keysyms, k) == syms[0]) { /* Found it: skip this level */ found = true; break; } } if (!found) { /* First occurrence of the keysym on the layout/key */ darray_append(key_compose_keysyms, syms[0]); /* Add the keysym position if in a Compose sequence */ found = add_compose_keysym_entry( keymap, &keysym_entries, syms[0], keycode, layout, level ); } continue; } /* Found our keysym: print the combo that generates it */ xkb_mod_mask_t masks[MAX_TYPE_MAP_ENTRIES]; const size_t num_masks = xkb_keymap_key_get_mods_for_level( keymap, keycode, layout, level, masks, ARRAY_SIZE(masks) ); for (size_t i = 0; i < num_masks; i++) { print_combo(keymap, num_mods, keycode, key_name, layout, layout_name, level, masks[i]); } } } } darray_free(key_compose_keysyms); /* Compose sequences */ if (use_compose) { printf("\n=== Access via Compose sequences ===\n\n"); printf("# %-*s %-8s %-9s %-8s %-20s %-7s %-s\n", XKB_KEYSYM_NAME_MAX_SIZE - 1, "KEYSYM", "KEYCODE", "KEY NAME", "LAYOUT", "LAYOUT NAME", "LEVEL#", "MODIFIERS"); /* Sort keysyms positions */ struct keysym_entries *entry; darray_foreach(entry, keysym_entries) { if (!darray_size(entry->entries)) continue; qsort(darray_items(entry->entries), darray_size(entry->entries), sizeof(*darray_items(entry->entries)), keysym_entry_compare); } } struct compose_lhs *compose_entry; size_t count = 0; darray_foreach(compose_entry, compose_entries) { /* Check we got all the keysyms required by the Compose sequence */ struct { size_t index; struct keysym_entries *entry; } indexes[COMPOSE_MAX_LHS_LEN] = {0}; bool enabled = true; for (size_t k = 0; k < compose_entry->count; k++) { struct keysym_entries *entry = lookup_keysym_entries( &keysym_entries, compose_entry->keysyms[k], false ); if (!entry || !darray_size(entry->entries)) { enabled = false; break; } indexes[k].index = 0; indexes[k].entry = entry; } if (!enabled) { continue; } /* * Compose sequence is reachable with the keymap: iterate over the * cartesian product of the keysyms’ positions. */ bool more_sequences = true; while (more_sequences) { /* * Discard combinations that mix layouts. Only apply to keys with * more that one layout. */ xkb_layout_index_t layout = XKB_LAYOUT_INVALID; for (size_t k = 0; k < compose_entry->count; k++) { struct keysym_entries *entry = indexes[k].entry; struct keysym_entry *e = &darray_item(entry->entries, indexes[k].index); if (layout == XKB_LAYOUT_INVALID && xkb_keymap_num_layouts_for_key(keymap, e->keycode) > 1) { layout = e->layout; } if (layout != XKB_LAYOUT_INVALID && xkb_keymap_num_layouts_for_key(keymap, e->keycode) > 1 && e->layout != layout) { /* Skip combinations that mix layouts */ goto skip; } } if (count++ > 0) printf("---\n"); /* Display the Compose sequence */ for (size_t k = 0; k < compose_entry->count; k++) { struct keysym_entries *entry = indexes[k].entry; struct keysym_entry *e = &darray_item(entry->entries, indexes[k].index); const char* const key_name = xkb_keymap_key_get_name(keymap, e->keycode); assert(key_name); /* Already skipped unamed keys above */ const char * layout_name = xkb_keymap_layout_get_name(keymap, e->layout); if (!layout_name) { layout_name = "?"; } char buf[XKB_KEYSYM_NAME_MAX_SIZE] = {0}; xkb_keysym_get_name(entry->keysym, buf, ARRAY_SIZE(buf)); if (k > 0) printf(" "); else printf("%02zu ", count); printf("%-*s ", XKB_KEYSYM_NAME_MAX_SIZE - 1, buf); print_combo(keymap, num_mods, e->keycode, key_name, e->layout, layout_name, e->level, e->mask); } skip: /* Cartesian product: find the rightmost list that can be advanced */ { size_t k = compose_entry->count; while (k > 0) { k--; indexes[k].index++; if (indexes[k].index < darray_size(indexes[k].entry->entries)) { k++; break; } indexes[k].index = 0; } if (k == 0) more_sequences = false; } } } ret = EXIT_SUCCESS; darray_free(compose_entries); darray_keysym_entries_free(&keysym_entries); err: xkb_keymap_unref(keymap); xkb_context_unref(ctx); return ret; } xkbcommon-libxkbcommon-54ee7ac/tools/interactive-evdev.c000066400000000000000000000473141510033435100236240ustar00rootroot00000000000000/* * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xkbcommon/xkbcommon.h" #include "src/utils.h" #include "src/keymap-formats.h" #include "tools-common.h" struct keyboard { char *path; int fd; struct xkb_state *state; struct xkb_compose_state *compose_state; struct keyboard *next; }; static bool verbose = false; static bool terminate; static int evdev_offset = 8; static bool report_state_changes; static bool with_compose; static enum xkb_consumed_mode consumed_mode = XKB_CONSUMED_MODE_XKB; enum print_state_options print_options = DEFAULT_PRINT_OPTIONS; #define DEFAULT_INCLUDE_PATH_PLACEHOLDER "__defaults__" #define NLONGS(n) (((n) + LONG_BIT - 1) / LONG_BIT) static bool evdev_bit_is_set(const unsigned long *array, int bit) { return array[bit / LONG_BIT] & (1ULL << (bit % LONG_BIT)); } /* Some heuristics to see if the device is a keyboard. */ static bool is_keyboard(int fd) { int i; unsigned long evbits[NLONGS(EV_CNT)] = { 0 }; unsigned long keybits[NLONGS(KEY_CNT)] = { 0 }; errno = 0; ioctl(fd, EVIOCGBIT(0, sizeof(evbits)), evbits); if (errno) return false; if (!evdev_bit_is_set(evbits, EV_KEY)) return false; errno = 0; ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits); if (errno) return false; for (i = KEY_RESERVED; i <= KEY_MIN_INTERESTING; i++) if (evdev_bit_is_set(keybits, i)) return true; return false; } static int keyboard_new(struct dirent *ent, struct xkb_keymap *keymap, struct xkb_compose_table *compose_table, struct keyboard **out) { int ret; char *path; int fd; struct xkb_state *state; struct xkb_compose_state *compose_state = NULL; struct keyboard *kbd; ret = asprintf(&path, "/dev/input/%s", ent->d_name); if (ret < 0) return -ENOMEM; fd = open(path, O_NONBLOCK | O_CLOEXEC | O_RDONLY); if (fd < 0) { ret = -errno; goto err_path; } if (!is_keyboard(fd)) { /* Dummy "skip this device" value. */ ret = -ENOTSUP; goto err_fd; } state = xkb_state_new(keymap); if (!state) { fprintf(stderr, "Couldn't create xkb state for %s\n", path); ret = -EFAULT; goto err_fd; } if (with_compose) { compose_state = xkb_compose_state_new(compose_table, XKB_COMPOSE_STATE_NO_FLAGS); if (!compose_state) { fprintf(stderr, "Couldn't create compose state for %s\n", path); ret = -EFAULT; goto err_state; } } kbd = calloc(1, sizeof(*kbd)); if (!kbd) { ret = -ENOMEM; goto err_compose_state; } kbd->path = path; kbd->fd = fd; kbd->state = state; kbd->compose_state = compose_state; *out = kbd; return 0; err_compose_state: xkb_compose_state_unref(compose_state); err_state: xkb_state_unref(state); err_fd: close(fd); err_path: free(path); return ret; } static void keyboard_free(struct keyboard *kbd) { if (!kbd) return; if (kbd->fd >= 0) close(kbd->fd); free(kbd->path); xkb_state_unref(kbd->state); xkb_compose_state_unref(kbd->compose_state); free(kbd); } static int filter_device_name(const struct dirent *ent) { return !fnmatch("event*", ent->d_name, 0); } static struct keyboard * get_keyboards(struct xkb_keymap *keymap, struct xkb_compose_table *compose_table) { int ret, i, nents; struct dirent **ents; struct keyboard *kbds = NULL, *kbd = NULL; nents = scandir("/dev/input", &ents, filter_device_name, alphasort); if (nents < 0) { fprintf(stderr, "Couldn't scan /dev/input: %s\n", strerror(errno)); return NULL; } for (i = 0; i < nents; i++) { ret = keyboard_new(ents[i], keymap, compose_table, &kbd); if (ret) { if (ret == -EACCES) { fprintf(stderr, "Couldn't open /dev/input/%s: %s. " "You probably need root to run this.\n", ents[i]->d_name, strerror(-ret)); break; } if (ret != -ENOTSUP) { fprintf(stderr, "Couldn't open /dev/input/%s: %s. Skipping.\n", ents[i]->d_name, strerror(-ret)); } continue; } assert(kbd != NULL); kbd->next = kbds; kbds = kbd; } if (!kbds) { fprintf(stderr, "Couldn't find any keyboards I can use! Quitting.\n"); goto err; } err: for (i = 0; i < nents; i++) free(ents[i]); free(ents); return kbds; } static void free_keyboards(struct keyboard *kbds) { struct keyboard *next; while (kbds) { next = kbds->next; keyboard_free(kbds); kbds = next; } } /* The meaning of the input_event 'value' field. */ enum { KEY_STATE_RELEASE = 0, KEY_STATE_PRESS = 1, KEY_STATE_REPEAT = 2, }; static void process_event(struct keyboard *kbd, uint16_t type, uint16_t code, int32_t value) { xkb_keycode_t keycode; struct xkb_keymap *keymap; enum xkb_state_component changed; enum xkb_compose_status status; if (type != EV_KEY) return; keycode = evdev_offset + code; keymap = xkb_state_get_keymap(kbd->state); if (value == KEY_STATE_REPEAT && !xkb_keymap_key_repeats(keymap, keycode)) return; if (with_compose && value != KEY_STATE_RELEASE) { xkb_keysym_t keysym = xkb_state_key_get_one_sym(kbd->state, keycode); xkb_compose_state_feed(kbd->compose_state, keysym); } tools_print_keycode_state( NULL, kbd->state, kbd->compose_state, keycode, (value == KEY_STATE_RELEASE) ? XKB_KEY_UP : XKB_KEY_DOWN, consumed_mode, print_options ); if (with_compose) { status = xkb_compose_state_get_status(kbd->compose_state); if (status == XKB_COMPOSE_CANCELLED || status == XKB_COMPOSE_COMPOSED) xkb_compose_state_reset(kbd->compose_state); } changed = xkb_state_update_key(kbd->state, keycode, (value == KEY_STATE_RELEASE ? XKB_KEY_UP : XKB_KEY_DOWN)); if (report_state_changes) tools_print_state_changes(NULL, kbd->state, changed, print_options); } static int read_keyboard(struct keyboard *kbd) { ssize_t len; struct input_event evs[16]; /* No fancy error checking here. */ while ((len = read(kbd->fd, &evs, sizeof(evs))) > 0) { const size_t nevs = len / sizeof(struct input_event); for (size_t i = 0; i < nevs; i++) process_event(kbd, evs[i].type, evs[i].code, evs[i].value); } if (len < 0 && errno != EWOULDBLOCK) { fprintf(stderr, "Couldn't read %s: %s\n", kbd->path, strerror(errno)); return 1; } return 0; } static int loop(struct keyboard *kbds) { int ret = -1; struct keyboard *kbd; nfds_t nfds, i; struct pollfd *fds = NULL; for (kbd = kbds, nfds = 0; kbd; kbd = kbd->next, nfds++) {} fds = calloc(nfds, sizeof(*fds)); if (fds == NULL) { fprintf(stderr, "Out of memory"); goto out; } for (i = 0, kbd = kbds; kbd; kbd = kbd->next, i++) { fds[i].fd = kbd->fd; fds[i].events = POLLIN; } while (!terminate) { ret = poll(fds, nfds, -1); if (ret < 0) { if (errno == EINTR) continue; fprintf(stderr, "Couldn't poll for events: %s\n", strerror(errno)); goto out; } for (i = 0, kbd = kbds; kbd; kbd = kbd->next, i++) { if (fds[i].revents != 0) { ret = read_keyboard(kbd); if (ret) { goto out; } } } } ret = 0; out: free(fds); return ret; } static void sigintr_handler(int signum) { terminate = true; } static void usage(FILE *fp, char *progname) { fprintf(fp, "Usage: %s [--include=] [--include-defaults] [--format=]" "[--rules=] [--model=] [--layout=] " "[--variant=] [--options=] " "[--enable-environment-names]\n", progname); fprintf(fp, " or: %s --keymap \n", progname); fprintf(fp, "For both:\n" " --format (use keymap format FORMAT)\n" " --verbose (enable verbose debugging output)\n" " -1, --uniline (enable uniline event output)\n" " --multiline (enable uniline event output)\n" " --short (shorter event output)\n" " --report-state-changes (report changes to the state)\n" " --enable-compose (enable Compose)\n" " --consumed-mode={xkb|gtk} (select the consumed modifiers mode, default: xkb)\n" " --without-x11-offset (don't add X11 keycode offset)\n" "Other:\n" " --help (display this help and exit)\n" ); } int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; struct keyboard *kbds; struct xkb_context *ctx = NULL; struct xkb_keymap *keymap = NULL; struct xkb_compose_table *compose_table = NULL; const char *includes[64]; size_t num_includes = 0; bool use_env_names = false; enum xkb_keymap_format keymap_format = DEFAULT_INPUT_KEYMAP_FORMAT; const char *rules = NULL; const char *model = NULL; const char *layout = NULL; const char *variant = NULL; const char *options = NULL; const char *keymap_path = NULL; const char *locale; struct sigaction act; enum options { OPT_VERBOSE, OPT_UNILINE, OPT_MULTILINE, OPT_INCLUDE, OPT_INCLUDE_DEFAULTS, OPT_ENABLE_ENV_NAMES, OPT_KEYMAP_FORMAT, OPT_RULES, OPT_MODEL, OPT_LAYOUT, OPT_VARIANT, OPT_OPTION, OPT_KEYMAP, OPT_WITHOUT_X11_OFFSET, OPT_CONSUMED_MODE, OPT_COMPOSE, OPT_SHORT, OPT_REPORT_STATE, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, OPT_VERBOSE}, {"uniline", no_argument, 0, OPT_UNILINE}, {"multiline", no_argument, 0, OPT_MULTILINE}, {"include", required_argument, 0, OPT_INCLUDE}, {"include-defaults", no_argument, 0, OPT_INCLUDE_DEFAULTS}, {"enable-environment-names", no_argument, 0, OPT_ENABLE_ENV_NAMES}, {"format", required_argument, 0, OPT_KEYMAP_FORMAT}, {"rules", required_argument, 0, OPT_RULES}, {"model", required_argument, 0, OPT_MODEL}, {"layout", required_argument, 0, OPT_LAYOUT}, {"variant", required_argument, 0, OPT_VARIANT}, {"options", required_argument, 0, OPT_OPTION}, {"keymap", required_argument, 0, OPT_KEYMAP}, {"consumed-mode", required_argument, 0, OPT_CONSUMED_MODE}, {"enable-compose", no_argument, 0, OPT_COMPOSE}, {"short", no_argument, 0, OPT_SHORT}, {"report-state-changes", no_argument, 0, OPT_REPORT_STATE}, {"without-x11-offset", no_argument, 0, OPT_WITHOUT_X11_OFFSET}, {0, 0, 0, 0}, }; setlocale(LC_ALL, ""); bool has_rmlvo_options = false; while (1) { int option_index = 0; int opt = getopt_long(argc, argv, "*1h", opts, &option_index); if (opt == -1) break; switch (opt) { case OPT_VERBOSE: verbose = true; break; case '1': case OPT_UNILINE: print_options |= PRINT_UNILINE; break; case '*': case OPT_MULTILINE: print_options &= ~PRINT_UNILINE; break; case OPT_INCLUDE: if (num_includes >= ARRAY_SIZE(includes)) goto too_many_includes; includes[num_includes++] = optarg; break; case OPT_INCLUDE_DEFAULTS: if (num_includes >= ARRAY_SIZE(includes)) goto too_many_includes; includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER; break; case OPT_ENABLE_ENV_NAMES: use_env_names = true; break; case OPT_KEYMAP_FORMAT: keymap_format = xkb_keymap_parse_format(optarg); if (!keymap_format) { fprintf(stderr, "ERROR: invalid --format \"%s\"\n", optarg); usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } break; case OPT_RULES: if (keymap_path) goto input_format_error; rules = optarg; has_rmlvo_options = true; break; case OPT_MODEL: if (keymap_path) goto input_format_error; model = optarg; has_rmlvo_options = true; break; case OPT_LAYOUT: if (keymap_path) goto input_format_error; layout = optarg; has_rmlvo_options = true; break; case OPT_VARIANT: if (keymap_path) goto input_format_error; variant = optarg; has_rmlvo_options = true; break; case OPT_OPTION: if (keymap_path) goto input_format_error; options = optarg; has_rmlvo_options = true; break; case OPT_KEYMAP: if (has_rmlvo_options) goto input_format_error; keymap_path = optarg; break; case OPT_WITHOUT_X11_OFFSET: evdev_offset = 0; break; case OPT_REPORT_STATE: report_state_changes = true; break; case OPT_COMPOSE: with_compose = true; break; case OPT_SHORT: print_options &= ~PRINT_VERBOSE; break; case OPT_CONSUMED_MODE: if (strcmp(optarg, "gtk") == 0) { consumed_mode = XKB_CONSUMED_MODE_GTK; } else if (strcmp(optarg, "xkb") == 0) { consumed_mode = XKB_CONSUMED_MODE_XKB; } else { fprintf(stderr, "ERROR: invalid --consumed-mode \"%s\"\n", optarg); usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } break; #ifdef ENABLE_PRIVATE_APIS case OPT_PRINT_MODMAPS: print_modmaps = true; break; #endif case 'h': usage(stdout, argv[0]); return EXIT_SUCCESS; default: usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } } if (optind < argc && !isempty(argv[optind])) { /* Some positional arguments left: use as a keymap input */ if (keymap_path || has_rmlvo_options) goto too_much_arguments; keymap_path = argv[optind++]; if (optind < argc) { too_much_arguments: fprintf(stderr, "ERROR: Too much positional arguments\n"); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } } if (!(print_options & PRINT_VERBOSE) && (print_options & PRINT_UNILINE)) { print_options &= ~PRINT_VERBOSE_ONE_LINE_FIELDS; } enum xkb_context_flags ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES; if (!use_env_names) ctx_flags |= XKB_CONTEXT_NO_ENVIRONMENT_NAMES; ctx = xkb_context_new(ctx_flags); if (!ctx) { fprintf(stderr, "ERROR: Couldn't create xkb context\n"); goto out; } if (verbose) tools_enable_verbose_logging(ctx); if (num_includes == 0) includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER; for (size_t i = 0; i < num_includes; i++) { const char *include = includes[i]; if (strcmp(include, DEFAULT_INCLUDE_PATH_PLACEHOLDER) == 0) xkb_context_include_path_append_default(ctx); else xkb_context_include_path_append(ctx, include); } if (keymap_path) { FILE *file = fopen(keymap_path, "rb"); if (!file) { fprintf(stderr, "ERROR: Couldn't open '%s': %s\n", keymap_path, strerror(errno)); goto out; } keymap = xkb_keymap_new_from_file(ctx, file, keymap_format, XKB_KEYMAP_COMPILE_NO_FLAGS); fclose(file); } else { struct xkb_rule_names rmlvo = { .rules = (isempty(rules)) ? NULL : rules, .model = (isempty(model)) ? NULL : model, .layout = (isempty(layout)) ? NULL : layout, .variant = (isempty(variant)) ? NULL : variant, .options = (isempty(options)) ? NULL : options }; if (!rules && !model && !layout && !variant && !options) keymap = xkb_keymap_new_from_names2(ctx, NULL, keymap_format, XKB_KEYMAP_COMPILE_NO_FLAGS); else keymap = xkb_keymap_new_from_names2(ctx, &rmlvo, keymap_format, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) { fprintf(stderr, "ERROR: Failed to compile RMLVO: " "'%s', '%s', '%s', '%s', '%s'\n", rules, model, layout, variant, options); goto out; } } if (!keymap) { fprintf(stderr, "ERROR: Couldn't create xkb keymap\n"); goto out; } if (with_compose) { locale = setlocale(LC_CTYPE, NULL); compose_table = xkb_compose_table_new_from_locale(ctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (!compose_table) { fprintf(stderr, "ERROR: Couldn't create compose from locale\n"); goto out; } } kbds = get_keyboards(keymap, compose_table); if (!kbds) { goto out; } #ifdef ENABLE_PRIVATE_APIS if (print_modmaps) { print_keys_modmaps(keymap); putchar('\n'); print_modifiers_encodings(keymap); putchar('\n'); } #endif act.sa_handler = sigintr_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &act, NULL); sigaction(SIGTERM, &act, NULL); tools_disable_stdin_echo(); ret = loop(kbds); tools_enable_stdin_echo(); free_keyboards(kbds); out: xkb_compose_table_unref(compose_table); xkb_keymap_unref(keymap); xkb_context_unref(ctx); return ret; too_many_includes: fprintf(stderr, "ERROR: too many includes (max: %zu)\n", ARRAY_SIZE(includes)); exit(EXIT_INVALID_USAGE); input_format_error: fprintf(stderr, "ERROR: Cannot use RMLVO options with keymap input\n"); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } xkbcommon-libxkbcommon-54ee7ac/tools/interactive-wayland.c000066400000000000000000001013721510033435100241450ustar00rootroot00000000000000/* * Copyright © 2012 Collabora, Ltd. * Copyright © 2013 Ran Benita * Copyright © 2016 Daniel Stone * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-compose.h" #include "src/utils.h" #include "src/keymap-formats.h" #include "tools-common.h" #include #include "wayland-client-protocol.h" #include "xdg-shell-client-protocol.h" #include "xdg-decoration-unstable-v1-client-protocol.h" #include #define MIN(a, b) ((a) < (b) ? (a) : (b)) /* Offset between evdev keycodes (where KEY_ESCAPE is 1), and the evdev XKB * keycode set (where ESC is 9). */ #define EVDEV_OFFSET 8 struct interactive_dpy { struct wl_display *dpy; struct wl_compositor *compositor; struct xdg_wm_base *shell; struct wl_shm *shm; uint32_t shm_format; struct wl_buffer *buf; struct zxdg_decoration_manager_v1 *decoration_manager; struct zxdg_toplevel_decoration_v1 *decoration; struct xkb_context *ctx; struct xkb_compose_table *compose_table; struct wl_surface *wl_surf; struct xdg_surface *xdg_surf; struct xdg_toplevel *xdg_top; struct wl_list seats; }; struct interactive_seat { struct interactive_dpy *inter; struct wl_seat *wl_seat; struct wl_keyboard *wl_kbd; struct wl_pointer *wl_pointer; uint32_t version; /* ... of wl_seat */ uint32_t global_name; /* an ID of sorts */ char *name_str; /* a descriptor */ struct xkb_keymap *keymap; struct xkb_state *state; struct xkb_compose_state *compose_state; struct wl_list link; }; static bool terminate; static enum xkb_keymap_format keymap_input_format = DEFAULT_INPUT_KEYMAP_FORMAT; #ifdef KEYMAP_DUMP static enum xkb_keymap_format keymap_output_format = DEFAULT_OUTPUT_KEYMAP_FORMAT; static enum xkb_keymap_serialize_flags serialize_flags = (enum xkb_keymap_serialize_flags) DEFAULT_KEYMAP_SERIALIZE_FLAGS; static bool dump_raw_keymap; #else static enum print_state_options print_options = DEFAULT_PRINT_OPTIONS; static bool use_local_state = false; static struct xkb_keymap *custom_keymap = NULL; #endif #ifndef KEYMAP_DUMP static void surface_configure(void *data, struct xdg_surface *surface, uint32_t serial) { struct interactive_dpy *inter = data; xdg_surface_ack_configure(inter->xdg_surf, serial); wl_surface_commit(inter->wl_surf); } static const struct xdg_surface_listener surface_listener = { surface_configure, }; #ifdef HAVE_MKOSTEMP static int create_tmpfile_cloexec(char *tmpname) { int fd = mkostemp(tmpname, O_CLOEXEC); if (fd >= 0) unlink(tmpname); return fd; } #else /* The following utility functions are taken from Weston's * shared/os-compatibility.c. */ static int os_fd_set_cloexec(int fd) { long flags; if (fd == -1) return -1; flags = fcntl(fd, F_GETFD); if (flags == -1) return -1; if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) return -1; return 0; } static int set_cloexec_or_close(int fd) { if (os_fd_set_cloexec(fd) != 0) { close(fd); return -1; } return fd; } static int create_tmpfile_cloexec(char *tmpname) { int fd = mkstemp(tmpname); if (fd >= 0) { fd = set_cloexec_or_close(fd); unlink(tmpname); } return fd; } #endif static int os_resize_anonymous_file(int fd, off_t size) { int ret; #ifdef HAVE_POSIX_FALLOCATE ret = posix_fallocate(fd, 0, size); if (ret == 0) return 0; /* * Filesystems that do support fallocate will return EINVAL * or EOPNOTSUPP, fallback to ftruncate() then. */ if (ret != EINVAL && ret != EOPNOTSUPP) return ret; #endif ret = ftruncate(fd, size); if (ret != 0) return errno; return 0; } /* * Create a new, unique, anonymous file of the given size, and * return the file descriptor for it. The file descriptor is set * CLOEXEC. The file is immediately suitable for mmap()'ing * the given size at offset zero. * * The file should not have a permanent backing store like a disk, * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. * * The file name is deleted from the file system. * * The file is suitable for buffer sharing between processes by * transmitting the file descriptor over Unix sockets using the * SCM_RIGHTS methods. * * If the C library implements posix_fallocate(), it is used to * guarantee that disk space is available for the file at the * given size. If disk space is insufficent, errno is set to ENOSPC. * If posix_fallocate() is not supported, program will fallback * to ftruncate() instead. */ static int os_create_anonymous_file(off_t size) { static const char template[] = "/weston-shared-XXXXXX"; const char *path; char *name; int fd; int ret; path = getenv("XDG_RUNTIME_DIR"); if (!path) { errno = ENOENT; return -1; } const size_t len = strlen(path); name = malloc(len + sizeof(template)); if (!name) return -1; memcpy(name, path, len); memcpy(name + len, template, sizeof(template)); fd = create_tmpfile_cloexec(name); free(name); if (fd < 0) return -1; ret = os_resize_anonymous_file(fd, size); if (ret != 0) { close(fd); errno = ret; return -1; } return fd; } static void buffer_release(void *data, struct wl_buffer *buffer) { struct interactive_dpy *inter = data; wl_buffer_destroy(buffer); inter->buf = NULL; } static const struct wl_buffer_listener buffer_listener = { buffer_release }; static void buffer_create(struct interactive_dpy *inter, uint32_t width, uint32_t height) { struct wl_shm_pool *pool; struct wl_region *opaque; uint32_t stride; size_t size; void *map; int fd; switch (inter->shm_format) { case WL_SHM_FORMAT_ARGB8888: case WL_SHM_FORMAT_XRGB8888: case WL_SHM_FORMAT_ABGR8888: case WL_SHM_FORMAT_XBGR8888: stride = width * 4; break; case WL_SHM_FORMAT_RGB565: case WL_SHM_FORMAT_BGR565: stride = width * 2; break; default: fprintf(stderr, "Unsupported SHM format %"PRIu32"\n", inter->shm_format); exit(EXIT_FAILURE); } size = (size_t)(stride) * height; const off_t offset = (off_t) size; if ((size_t) offset != size) { fprintf(stderr, "Couldn't create surface buffer (buffer size error)\n"); exit(EXIT_FAILURE); } fd = os_create_anonymous_file(offset); if (fd < 0) { fprintf(stderr, "Couldn't create surface buffer (buffer file error)\n"); exit(EXIT_FAILURE); } map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "Couldn't mmap surface buffer\n"); exit(EXIT_FAILURE); } memset(map, 0xff, size); munmap(map, size); if (size > INT32_MAX) { fprintf(stderr, "Couldn't create surface pool\n"); exit(EXIT_FAILURE); } pool = wl_shm_create_pool(inter->shm, fd, (int32_t) size); if (width > INT32_MAX || height > INT32_MAX || stride > INT32_MAX) { fprintf(stderr, "Couldn't create surface pool buffer\n"); exit(EXIT_FAILURE); } const int32_t iwidth = (int32_t) width; const int32_t iheight = (int32_t) height; const int32_t istride = (int32_t) stride; if (inter->buf) wl_buffer_destroy(inter->buf); inter->buf = wl_shm_pool_create_buffer(pool, 0, iwidth, iheight, istride, inter->shm_format); wl_buffer_add_listener(inter->buf, &buffer_listener, inter); wl_surface_attach(inter->wl_surf, inter->buf, 0, 0); wl_surface_damage(inter->wl_surf, 0, 0, iwidth, iheight); opaque = wl_compositor_create_region(inter->compositor); wl_region_add(opaque, 0, 0, iwidth, iheight); wl_surface_set_opaque_region(inter->wl_surf, opaque); wl_region_destroy(opaque); wl_shm_pool_destroy(pool); close(fd); } static void toplevel_configure(void *data, struct xdg_toplevel *toplevel, int32_t width, int32_t height, struct wl_array *states) { struct interactive_dpy *inter = data; if (width == 0) width = 400; if (height == 0) height = 400; buffer_create(inter, width, height); } static void toplevel_close(void *data, struct xdg_toplevel *toplevel) { terminate = true; } static const struct xdg_toplevel_listener toplevel_listener = { toplevel_configure, toplevel_close }; static void surface_create(struct interactive_dpy *inter) { inter->wl_surf = wl_compositor_create_surface(inter->compositor); inter->xdg_surf = xdg_wm_base_get_xdg_surface(inter->shell, inter->wl_surf); xdg_surface_add_listener(inter->xdg_surf, &surface_listener, inter); /* Create a window only for the interactive tool */ inter->xdg_top = xdg_surface_get_toplevel(inter->xdg_surf); xdg_toplevel_add_listener(inter->xdg_top, &toplevel_listener, inter); xdg_toplevel_set_title(inter->xdg_top, "xkbcommon event tester"); xdg_toplevel_set_app_id(inter->xdg_top, "org.xkbcommon.test.interactive-wayland"); if (inter->decoration_manager) { inter->decoration = zxdg_decoration_manager_v1_get_toplevel_decoration( inter->decoration_manager, inter->xdg_top ); zxdg_toplevel_decoration_v1_set_mode( inter->decoration, ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE ); } wl_surface_commit(inter->wl_surf); } #endif static void shell_ping(void *data, struct xdg_wm_base *shell, uint32_t serial) { xdg_wm_base_pong(shell, serial); } static const struct xdg_wm_base_listener shell_listener = { shell_ping }; static void kbd_keymap(void *data, struct wl_keyboard *wl_kbd, uint32_t format, int fd, uint32_t size) { struct interactive_seat *seat = data; #ifndef KEYMAP_DUMP if (custom_keymap) { /* Custom keymap: ignore keymap from the server */ close(fd); if (!seat->keymap) seat->keymap = xkb_keymap_ref(custom_keymap); } else { #endif void *buf = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { fprintf(stderr, "ERROR: Failed to mmap keymap: %d\n", errno); close(fd); return; } #ifdef KEYMAP_DUMP /* We do not want to be interactive, so stop at next loop */ terminate = true; if (dump_raw_keymap) { /* Dump the raw keymap */ fprintf(stdout, "%s", (char *)buf); munmap(buf, size); close(fd); /* Do not go further */ return; } #endif xkb_keymap_unref(seat->keymap); seat->keymap = xkb_keymap_new_from_buffer(seat->inter->ctx, buf, size - 1, keymap_input_format, XKB_KEYMAP_COMPILE_NO_FLAGS); munmap(buf, size); close(fd); #ifndef KEYMAP_DUMP } #endif if (!seat->keymap) { fprintf(stderr, "ERROR: Failed to compile keymap!\n"); return; } #ifdef KEYMAP_DUMP /* Dump the reformatted keymap */ char *dump = xkb_keymap_get_as_string2(seat->keymap, keymap_output_format, serialize_flags); fprintf(stdout, "%s", dump); free(dump); #else /* Reset the state, except if unset or using a local state */ if (!seat->state || !use_local_state) { xkb_state_unref(seat->state); seat->state = xkb_state_new(seat->keymap); if (!seat->state) fprintf(stderr, "ERROR: Failed to create XKB state!\n"); } #endif } static void kbd_enter(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, struct wl_surface *surf, struct wl_array *keys) { } static void kbd_leave(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, struct wl_surface *surf) { } static void kbd_key(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { #ifndef KEYMAP_DUMP struct interactive_seat *seat = data; xkb_keycode_t keycode = key + EVDEV_OFFSET; if (seat->compose_state && state != WL_KEYBOARD_KEY_STATE_RELEASED) { xkb_keysym_t keysym = xkb_state_key_get_one_sym(seat->state, keycode); xkb_compose_state_feed(seat->compose_state, keysym); } char * const prefix = asprintf_safe("%s: ", seat->name_str); const enum xkb_key_direction direction = (state == WL_KEYBOARD_KEY_STATE_RELEASED) ? XKB_KEY_UP : XKB_KEY_DOWN; tools_print_keycode_state(prefix, seat->state, seat->compose_state, keycode, direction, XKB_CONSUMED_MODE_XKB, print_options); if (seat->compose_state) { enum xkb_compose_status status = xkb_compose_state_get_status(seat->compose_state); if (status == XKB_COMPOSE_CANCELLED || status == XKB_COMPOSE_COMPOSED) xkb_compose_state_reset(seat->compose_state); } if (use_local_state) { /* Run our local state machine */ const enum xkb_state_component changed = xkb_state_update_key(seat->state, keycode, (state == WL_KEYBOARD_KEY_STATE_RELEASED ? XKB_KEY_UP : XKB_KEY_DOWN)); if (changed) tools_print_state_changes(prefix, seat->state, changed, print_options); } free(prefix); /* Exit on ESC. */ if (xkb_state_key_get_one_sym(seat->state, keycode) == XKB_KEY_Escape && state != WL_KEYBOARD_KEY_STATE_PRESSED) terminate = true; #endif } static void kbd_modifiers(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) { #ifndef KEYMAP_DUMP if (use_local_state) { /* Ignore state update if using a local state machine */ return; } struct interactive_seat *seat = data; const enum xkb_state_component changed = xkb_state_update_mask( seat->state, mods_depressed, mods_latched, mods_locked, 0, 0, group ); char * const prefix = asprintf_safe("%s: ", seat->name_str); tools_print_state_changes(prefix, seat->state, changed, print_options); free(prefix); #endif } static void kbd_repeat_info(void *data, struct wl_keyboard *wl_kbd, int32_t rate, int32_t delay) { } static const struct wl_keyboard_listener kbd_listener = { kbd_keymap, kbd_enter, kbd_leave, kbd_key, kbd_modifiers, kbd_repeat_info }; static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surf, wl_fixed_t fsx, wl_fixed_t fsy) { } static void pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surf) { } static void pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t fsx, wl_fixed_t fsy) { } static void pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { struct interactive_seat *seat = data; xdg_toplevel_move(seat->inter->xdg_top, seat->wl_seat, serial); } static void pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { } static void pointer_frame(void *data, struct wl_pointer *wl_pointer) { } static void pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t source) { } static void pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) { } static void pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t time, int32_t discrete) { } static const struct wl_pointer_listener pointer_listener = { pointer_enter, pointer_leave, pointer_motion, pointer_button, pointer_axis, pointer_frame, pointer_axis_source, pointer_axis_stop, pointer_axis_discrete }; static void seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t caps) { struct interactive_seat *seat = data; if (!seat->wl_kbd && (caps & WL_SEAT_CAPABILITY_KEYBOARD)) { seat->wl_kbd = wl_seat_get_keyboard(seat->wl_seat); wl_keyboard_add_listener(seat->wl_kbd, &kbd_listener, seat); } else if (seat->wl_kbd && !(caps & WL_SEAT_CAPABILITY_KEYBOARD)) { if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) wl_keyboard_release(seat->wl_kbd); else wl_keyboard_destroy(seat->wl_kbd); xkb_state_unref(seat->state); xkb_keymap_unref(seat->keymap); xkb_compose_state_unref(seat->compose_state); seat->state = NULL; seat->compose_state = NULL; seat->keymap = NULL; seat->wl_kbd = NULL; } if (!seat->wl_pointer && (caps & WL_SEAT_CAPABILITY_POINTER)) { seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat); wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); } else if (seat->wl_pointer && !(caps & WL_SEAT_CAPABILITY_POINTER)) { if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) wl_pointer_release(seat->wl_pointer); else wl_pointer_destroy(seat->wl_pointer); seat->wl_pointer = NULL; } } static void seat_name(void *data, struct wl_seat *wl_seat, const char *name) { struct interactive_seat *seat = data; free(seat->name_str); seat->name_str = strdup(name); } static const struct wl_seat_listener seat_listener = { seat_capabilities, seat_name }; static void seat_create(struct interactive_dpy *inter, struct wl_registry *registry, uint32_t name, uint32_t version) { int ret; struct interactive_seat *seat = calloc(1, sizeof(*seat)); seat->global_name = name; seat->inter = inter; seat->wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, MIN(version, 5)); wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); if (seat->inter->compose_table) { seat->compose_state = xkb_compose_state_new(seat->inter->compose_table, XKB_COMPOSE_STATE_NO_FLAGS); } ret = asprintf(&seat->name_str, "seat:%"PRIu32, wl_proxy_get_id((struct wl_proxy *) seat->wl_seat)); assert(ret >= 0); wl_list_insert(&inter->seats, &seat->link); } static void seat_destroy(struct interactive_seat *seat) { if (seat->wl_kbd) { if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) wl_keyboard_release(seat->wl_kbd); else wl_keyboard_destroy(seat->wl_kbd); xkb_state_unref(seat->state); xkb_compose_state_unref(seat->compose_state); xkb_keymap_unref(seat->keymap); } if (seat->wl_pointer) { if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) wl_pointer_release(seat->wl_pointer); else wl_pointer_destroy(seat->wl_pointer); } if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) wl_seat_release(seat->wl_seat); else wl_seat_destroy(seat->wl_seat); free(seat->name_str); wl_list_remove(&seat->link); free(seat); } static void registry_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version) { struct interactive_dpy *inter = data; if (strcmp(interface, "wl_seat") == 0) { seat_create(inter, registry, name, version); } else if (strcmp(interface, "xdg_wm_base") == 0) { inter->shell = wl_registry_bind(registry, name, &xdg_wm_base_interface, MIN(version, 2)); xdg_wm_base_add_listener(inter->shell, &shell_listener, inter); } else if (strcmp(interface, "wl_compositor") == 0) { inter->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, MIN(version, 1)); } else if (strcmp(interface, "wl_shm") == 0) { inter->shm = wl_registry_bind(registry, name, &wl_shm_interface, MIN(version, 1)); } #ifndef KEYMAP_DUMP else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) { inter->decoration_manager = wl_registry_bind( registry, name, &zxdg_decoration_manager_v1_interface, MIN(version, 1) ); } #endif } static void registry_delete(void *data, struct wl_registry *registry, uint32_t name) { struct interactive_dpy *inter = data; struct interactive_seat *seat, *tmp; wl_list_for_each_safe(seat, tmp, &inter->seats, link) { if (seat->global_name != name) continue; seat_destroy(seat); } } static const struct wl_registry_listener registry_listener = { registry_global, registry_delete }; static void dpy_disconnect(struct interactive_dpy *inter) { struct interactive_seat *seat, *tmp; wl_list_for_each_safe(seat, tmp, &inter->seats, link) seat_destroy(seat); if (inter->decoration) zxdg_toplevel_decoration_v1_destroy(inter->decoration); if (inter->decoration_manager) zxdg_decoration_manager_v1_destroy(inter->decoration_manager); if (inter->xdg_top) xdg_toplevel_destroy(inter->xdg_top); if (inter->xdg_surf) xdg_surface_destroy(inter->xdg_surf); if (inter->wl_surf) wl_surface_destroy(inter->wl_surf); if (inter->shell) xdg_wm_base_destroy(inter->shell); if (inter->compositor) wl_compositor_destroy(inter->compositor); if (inter->shm) wl_shm_destroy(inter->shm); if (inter->buf) wl_buffer_destroy(inter->buf); /* Do one last roundtrip to try to destroy our wl_buffer. */ wl_display_roundtrip(inter->dpy); xkb_context_unref(inter->ctx); wl_display_disconnect(inter->dpy); } static void usage(FILE *fp, char *progname) { fprintf(fp, "Usage: %s [--help] [--verbose]" #ifdef KEYMAP_DUMP " [--no-pretty] [--drop-unused] [--raw] [--input-format]" " [--output-format] [--format]" #else " [--format] [--local-state] [--keymap FILE] [--enable-compose]" #endif "\n", progname); fprintf(fp, #ifdef KEYMAP_DUMP " --input-format use input keymap format FORMAT\n" " --output-format use output keymap format FORMAT\n" " --format keymap format to use for both input and output\n" " --no-pretty do not pretty-print when serializing a keymap\n" " --drop-unused disable unused bits serialization\n" " --raw dump the raw keymap, without parsing it\n" #else " --format use keymap format FORMAT\n" " --enable-compose enable Compose\n" " --local-state enable local state handling and ignore modifiers/layouts\n" " state updates from the compositor\n" " --keymap [] use the given keymap instead of the keymap from the\n" " compositor. It implies --local-state.\n" " If is \"-\" or missing, then load from stdin.\n" " -1, --uniline enable uniline event output\n" " --multiline enable multiline event output\n" #endif " --verbose enable verbose debugging output\n" " --help display this help and exit\n" ); } int main(int argc, char *argv[]) { int ret = 0; bool verbose = false; struct interactive_dpy inter; struct wl_registry *registry; #ifndef KEYMAP_DUMP bool with_keymap_file = false; const char *keymap_path = NULL; bool with_compose = false; struct xkb_compose_table *compose_table = NULL; #endif enum options { OPT_VERBOSE, OPT_UNILINE, OPT_MULTILINE, OPT_COMPOSE, OPT_LOCAL_STATE, OPT_INPUT_KEYMAP_FORMAT, OPT_OUTPUT_KEYMAP_FORMAT, OPT_KEYMAP_FORMAT, OPT_KEYMAP_NO_PRETTY, OPT_KEYMAP_DROP_UNUSED, OPT_KEYMAP, OPT_RAW, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, OPT_VERBOSE}, #ifdef KEYMAP_DUMP {"input-format", required_argument, 0, OPT_INPUT_KEYMAP_FORMAT}, {"output-format", required_argument, 0, OPT_OUTPUT_KEYMAP_FORMAT}, {"format", required_argument, 0, OPT_KEYMAP_FORMAT}, {"no-pretty", no_argument, 0, OPT_KEYMAP_NO_PRETTY}, {"drop-unused", no_argument, 0, OPT_KEYMAP_DROP_UNUSED}, {"raw", no_argument, 0, OPT_RAW}, #else {"uniline", no_argument, 0, OPT_UNILINE}, {"multiline", no_argument, 0, OPT_MULTILINE}, {"format", required_argument, 0, OPT_INPUT_KEYMAP_FORMAT}, {"enable-compose", no_argument, 0, OPT_COMPOSE}, {"local-state", no_argument, 0, OPT_LOCAL_STATE}, {"keymap", optional_argument, 0, OPT_KEYMAP}, #endif {0, 0, 0, 0}, }; setlocale(LC_ALL, ""); while (1) { int opt; int option_index = 0; opt = getopt_long(argc, argv, "*1h", opts, &option_index); if (opt == -1) break; switch (opt) { case OPT_VERBOSE: verbose = true; break; case OPT_INPUT_KEYMAP_FORMAT: keymap_input_format = xkb_keymap_parse_format(optarg); if (!keymap_input_format) { fprintf(stderr, "ERROR: invalid %s \"%s\"\n", #ifdef KEYMAP_DUMP "--input-format", #else "--format", #endif optarg); usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } break; #ifdef KEYMAP_DUMP case OPT_OUTPUT_KEYMAP_FORMAT: keymap_output_format = xkb_keymap_parse_format(optarg); if (!keymap_output_format) { fprintf(stderr, "ERROR: invalid --output-format \"%s\"\n", optarg); usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } break; case OPT_KEYMAP_FORMAT: keymap_input_format = xkb_keymap_parse_format(optarg); if (!keymap_input_format) { fprintf(stderr, "ERROR: invalid --format: \"%s\"\n", optarg); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } keymap_output_format = keymap_input_format; break; case OPT_KEYMAP_NO_PRETTY: serialize_flags &= ~XKB_KEYMAP_SERIALIZE_PRETTY; break; case OPT_KEYMAP_DROP_UNUSED: serialize_flags &= ~XKB_KEYMAP_SERIALIZE_KEEP_UNUSED; break; case OPT_RAW: dump_raw_keymap = true; break; #else case OPT_KEYMAP: with_keymap_file = true; /* Optional arguments require `=`, but we want to make this * requirement optional too, so that both `--keymap=xxx` and * `--keymap xxx` work. */ if (!optarg && argv[optind] && (argv[optind][0] != '-' || strcmp(argv[optind], "-") == 0 )) { keymap_path = argv[optind++]; } else { keymap_path = optarg; } /* --local-state is implied */ goto local_state; case OPT_COMPOSE: with_compose = true; break; case OPT_LOCAL_STATE: local_state: use_local_state = true; break; case '1': case OPT_UNILINE: print_options |= PRINT_UNILINE; break; case '*': case OPT_MULTILINE: print_options &= ~PRINT_UNILINE; break; #endif case 'h': usage(stdout, argv[0]); return EXIT_SUCCESS; default: #ifndef KEYMAP_DUMP invalid_usage: #endif usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } } #ifndef KEYMAP_DUMP if (optind < argc && !isempty(argv[optind])) { /* Some positional arguments left: use as a keymap input */ if (keymap_path) goto too_much_arguments; keymap_path = argv[optind++]; if (optind < argc) { /* Further positional arguments is an error */ too_much_arguments: fprintf(stderr, "ERROR: Too many positional arguments\n"); goto invalid_usage; } with_keymap_file = true; } else if (is_pipe_or_regular_file(STDIN_FILENO) && !with_keymap_file) { /* No positional argument: piping detected */ with_keymap_file = true; } if (with_keymap_file) { /* --local-state is implied with custom keymap */ use_local_state = true; } if (isempty(keymap_path) || strcmp(keymap_path, "-") == 0) keymap_path = NULL; #endif memset(&inter, 0, sizeof(inter)); wl_list_init(&inter.seats); inter.dpy = wl_display_connect(NULL); if (!inter.dpy) { fprintf(stderr, "Couldn't connect to Wayland server\n"); ret = -1; goto err_out; } inter.ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!inter.ctx) { ret = -1; fprintf(stderr, "Couldn't create xkb context\n"); goto err_out; } if (verbose) tools_enable_verbose_logging(inter.ctx); #ifndef KEYMAP_DUMP if (with_keymap_file) { FILE *file = NULL; if (keymap_path) { /* Read from regular file */ file = fopen(keymap_path, "rb"); } else { /* Read from stdin */ file = tools_read_stdin(); } if (!file) { fprintf(stderr, "ERROR: Failed to open keymap file \"%s\": %s\n", keymap_path ? keymap_path : "stdin", strerror(errno)); xkb_context_unref(inter.ctx); goto err_out; } custom_keymap = xkb_keymap_new_from_file(inter.ctx, file, keymap_input_format, XKB_KEYMAP_COMPILE_NO_FLAGS); } if (with_compose) { const char *locale = setlocale(LC_CTYPE, NULL); compose_table = xkb_compose_table_new_from_locale(inter.ctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (!compose_table) { fprintf(stderr, "Couldn't create compose from locale\n"); goto err_compose; } inter.compose_table = compose_table; } else { inter.compose_table = NULL; } #endif registry = wl_display_get_registry(inter.dpy); wl_registry_add_listener(registry, ®istry_listener, &inter); /* The first roundtrip gets the list of advertised globals. */ wl_display_roundtrip(inter.dpy); /* The second roundtrip dispatches the events sent after binding, e.g. * after binding to wl_seat globals in the first roundtrip, we will get * the wl_seat::capabilities event in this roundtrip. */ wl_display_roundtrip(inter.dpy); if (!inter.shell || !inter.shm || !inter.compositor) { fprintf(stderr, "Required Wayland interfaces %s%s%s unsupported\n", (inter.shell) ? "" : "xdg_shell ", (inter.shm) ? "" : "wl_shm", (inter.compositor) ? "" : "wl_compositor"); ret = -1; goto err_conn; } #ifndef KEYMAP_DUMP surface_create(&inter); #endif tools_disable_stdin_echo(); do { ret = wl_display_dispatch(inter.dpy); } while (ret >= 0 && !terminate); tools_enable_stdin_echo(); wl_registry_destroy(registry); err_conn: dpy_disconnect(&inter); #ifndef KEYMAP_DUMP err_compose: xkb_compose_table_unref(compose_table); #endif err_out: #ifndef KEYMAP_DUMP xkb_keymap_unref(custom_keymap); #endif exit(ret >= 0 ? EXIT_SUCCESS : EXIT_FAILURE); } xkbcommon-libxkbcommon-54ee7ac/tools/interactive-x11.c000066400000000000000000000535171510033435100231260ustar00rootroot00000000000000/* * Copyright © 2013 Ran Benita * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-x11.h" #include "xkbcommon/xkbcommon-compose.h" #include "src/keymap-formats.h" #include "src/utils.h" #include "tools-common.h" /* * Note: This program only handles the core keyboard device for now. * It should be straigtforward to change struct keyboard to a list of * keyboards with device IDs, as in tools/interactive-evdev.c. This would * require: * * - Initially listing the keyboard devices. * - Listening to device changes. * - Matching events to their devices. * * XKB itself knows about xinput1 devices, and most requests and events are * device-specific. * * In order to list the devices and react to changes, you need xinput1/2. * You also need xinput for the key press/release event, since the core * protocol key press event does not carry a device ID to match on. */ struct keyboard { xcb_connection_t *conn; uint8_t first_xkb_event; struct xkb_context *ctx; struct xkb_keymap *keymap; struct xkb_state *state; struct xkb_compose_state *compose_state; int32_t device_id; }; static bool terminate; #ifdef KEYMAP_DUMP static enum xkb_keymap_format keymap_format = DEFAULT_OUTPUT_KEYMAP_FORMAT; static enum xkb_keymap_serialize_flags serialize_flags = (enum xkb_keymap_serialize_flags) DEFAULT_KEYMAP_SERIALIZE_FLAGS; static bool const use_local_state = false; static struct xkb_keymap * const custom_keymap = NULL; #else static enum print_state_options print_options = DEFAULT_PRINT_OPTIONS; static bool use_local_state = false; static struct xkb_keymap *custom_keymap = NULL; #endif static int select_xkb_events_for_device(xcb_connection_t *conn, int32_t device_id) { enum { required_events = (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY), required_nkn_details = (XCB_XKB_NKN_DETAIL_KEYCODES), required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES | XCB_XKB_MAP_PART_KEY_SYMS | XCB_XKB_MAP_PART_MODIFIER_MAP | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | XCB_XKB_MAP_PART_KEY_ACTIONS | XCB_XKB_MAP_PART_VIRTUAL_MODS | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP), required_state_details = (XCB_XKB_STATE_PART_MODIFIER_BASE | XCB_XKB_STATE_PART_MODIFIER_LATCH | XCB_XKB_STATE_PART_MODIFIER_LOCK | XCB_XKB_STATE_PART_GROUP_BASE | XCB_XKB_STATE_PART_GROUP_LATCH | XCB_XKB_STATE_PART_GROUP_LOCK), }; static const xcb_xkb_select_events_details_t details = { .affectNewKeyboard = required_nkn_details, .newKeyboardDetails = required_nkn_details, .affectState = required_state_details, .stateDetails = required_state_details, }; xcb_void_cookie_t cookie = xcb_xkb_select_events_aux_checked(conn, device_id, required_events, /* affectWhich */ 0, /* clear */ 0, /* selectAll */ required_map_parts, /* affectMap */ required_map_parts, /* map */ &details); /* details */ xcb_generic_error_t *error = xcb_request_check(conn, cookie); if (error) { free(error); return -1; } return 0; } static int update_keymap(struct keyboard *kbd) { struct xkb_keymap *new_keymap; if (custom_keymap) { assert(use_local_state); /* Keymap is set only the first time, then we only reference it. */ new_keymap = xkb_keymap_ref(custom_keymap); /* Do not reset state if already defined */ if (!kbd->state) { /* Ignore state from the server */ kbd->state = xkb_state_new(new_keymap); if (!kbd->state) goto err_state; } } else { new_keymap = xkb_x11_keymap_new_from_device(kbd->ctx, kbd->conn, kbd->device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!new_keymap) goto err_keymap; /* Reset state on keymap reset. * Ignore state from server if using local state. */ struct xkb_state * const new_state = (use_local_state) ? xkb_state_new(new_keymap) : xkb_x11_state_new_from_device(new_keymap, kbd->conn, kbd->device_id); if (!new_state) goto err_state; if (kbd->keymap) printf("Keymap updated!\n"); xkb_state_unref(kbd->state); kbd->state = new_state; } xkb_keymap_unref(kbd->keymap); kbd->keymap = new_keymap; return 0; err_state: xkb_keymap_unref(new_keymap); err_keymap: return -1; } static int init_kbd(struct keyboard *kbd, xcb_connection_t *conn, uint8_t first_xkb_event, int32_t device_id, struct xkb_context *ctx, struct xkb_compose_table *compose_table) { int ret; kbd->conn = conn; kbd->first_xkb_event = first_xkb_event; kbd->ctx = ctx; kbd->keymap = NULL; kbd->state = NULL; kbd->compose_state = NULL; kbd->device_id = device_id; ret = update_keymap(kbd); if (ret) goto err_out; #ifdef KEYMAP_DUMP /* Dump the keymap */ char *dump = xkb_keymap_get_as_string2(kbd->keymap, keymap_format, serialize_flags); fprintf(stdout, "%s", dump); free(dump); terminate = true; return 0; #endif if (compose_table) kbd->compose_state = xkb_compose_state_new(compose_table, XKB_COMPOSE_STATE_NO_FLAGS); ret = select_xkb_events_for_device(conn, device_id); if (ret) goto err_state; return 0; err_state: xkb_state_unref(kbd->state); xkb_compose_state_unref(kbd->compose_state); xkb_keymap_unref(kbd->keymap); err_out: return -1; } static void deinit_kbd(struct keyboard *kbd) { xkb_state_unref(kbd->state); xkb_compose_state_unref(kbd->compose_state); xkb_keymap_unref(kbd->keymap); } #ifndef KEYMAP_DUMP static void process_xkb_event(xcb_generic_event_t *gevent, struct keyboard *kbd) { union xkb_event { struct { uint8_t response_type; uint8_t xkbType; uint16_t sequence; xcb_timestamp_t time; uint8_t deviceID; } any; xcb_xkb_new_keyboard_notify_event_t new_keyboard_notify; xcb_xkb_map_notify_event_t map_notify; xcb_xkb_state_notify_event_t state_notify; } *event = (union xkb_event *) gevent; if (event->any.deviceID != kbd->device_id) return; /* * XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap * updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent * recompilations. */ switch (event->any.xkbType) { case XCB_XKB_NEW_KEYBOARD_NOTIFY: if (event->new_keyboard_notify.changed & XCB_XKB_NKN_DETAIL_KEYCODES) update_keymap(kbd); break; case XCB_XKB_MAP_NOTIFY: update_keymap(kbd); break; case XCB_XKB_STATE_NOTIFY: { if (use_local_state) { /* Ignore state update if using a local state machine */ break; } const enum xkb_state_component changed = xkb_state_update_mask(kbd->state, event->state_notify.baseMods, event->state_notify.latchedMods, event->state_notify.lockedMods, event->state_notify.baseGroup, event->state_notify.latchedGroup, event->state_notify.lockedGroup); tools_print_state_changes(NULL, kbd->state, changed, print_options); break; } default: /* Ignore */ break; } } static void process_event(xcb_generic_event_t *gevent, struct keyboard *kbd) { switch (gevent->response_type) { case XCB_KEY_PRESS: { xcb_key_press_event_t *event = (xcb_key_press_event_t *) gevent; xkb_keycode_t keycode = event->detail; if (kbd->compose_state) { xkb_keysym_t keysym = xkb_state_key_get_one_sym(kbd->state, keycode); xkb_compose_state_feed(kbd->compose_state, keysym); } tools_print_keycode_state(NULL, kbd->state, kbd->compose_state, keycode, XKB_KEY_DOWN, XKB_CONSUMED_MODE_XKB, print_options); if (kbd->compose_state) { enum xkb_compose_status status = xkb_compose_state_get_status(kbd->compose_state); if (status == XKB_COMPOSE_CANCELLED || status == XKB_COMPOSE_COMPOSED) xkb_compose_state_reset(kbd->compose_state); } if (use_local_state) { /* Run our local state machine */ const enum xkb_state_component changed = xkb_state_update_key(kbd->state, keycode, XKB_KEY_DOWN); if (changed) tools_print_state_changes(NULL, kbd->state, changed, print_options); } /* Exit on ESC. */ if (xkb_state_key_get_one_sym(kbd->state, keycode) == XKB_KEY_Escape) terminate = true; break; } case XCB_KEY_RELEASE: { xcb_key_press_event_t *event = (xcb_key_press_event_t *) gevent; xkb_keycode_t keycode = event->detail; tools_print_keycode_state(NULL, kbd->state, kbd->compose_state, keycode, XKB_KEY_UP, XKB_CONSUMED_MODE_XKB, print_options); if (use_local_state) { /* Run our local state machine */ const enum xkb_state_component changed = xkb_state_update_key(kbd->state, keycode, XKB_KEY_UP); if (changed) tools_print_state_changes(NULL, kbd->state, changed, print_options); } break; } default: if (gevent->response_type == kbd->first_xkb_event) process_xkb_event(gevent, kbd); break; } } static int loop(xcb_connection_t *conn, struct keyboard *kbd) { while (!terminate) { xcb_generic_event_t *event; switch (xcb_connection_has_error(conn)) { case 0: break; case XCB_CONN_ERROR: fprintf(stderr, "Closed connection to X server: connection error\n"); return -1; case XCB_CONN_CLOSED_EXT_NOTSUPPORTED: fprintf(stderr, "Closed connection to X server: extension not supported\n"); return -1; default: fprintf(stderr, "Closed connection to X server: error code %d\n", xcb_connection_has_error(conn)); return -1; } event = xcb_wait_for_event(conn); if (!event) { continue; } process_event(event, kbd); free(event); } return 0; } static int create_capture_window(xcb_connection_t *conn) { xcb_generic_error_t *error; xcb_void_cookie_t cookie; xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(conn)).data; xcb_window_t window = xcb_generate_id(conn); uint32_t values[2] = { screen->white_pixel, XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE, }; cookie = xcb_create_window_checked(conn, XCB_COPY_FROM_PARENT, window, screen->root, 10, 10, 100, 100, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, values); if ((error = xcb_request_check(conn, cookie)) != NULL) { free(error); return -1; } cookie = xcb_map_window_checked(conn, window); if ((error = xcb_request_check(conn, cookie)) != NULL) { free(error); return -1; } return 0; } #endif static void usage(FILE *fp, char *progname) { fprintf(fp, "Usage: %s [--help] [--verbose]" #ifndef KEYMAP_DUMP " [--uniline] [--multiline] [--local-state] [--keymap FILE ]" #endif " [--format=]" #ifndef KEYMAP_DUMP " [--enable-compose]" #endif "\n", progname); fprintf(fp, #ifndef KEYMAP_DUMP " --enable-compose enable Compose\n" " --local-state enable local state handling and ignore modifiers/layouts\n" " state updates from the X11 server\n" " --keymap [] use the given keymap instead of the keymap from the\n" " compositor. It implies --local-state.\n" " If is \"-\" or missing, then load from stdin.\n" #endif " --format use keymap format \n" #ifdef KEYMAP_DUMP " --no-pretty do not pretty-print when serializing a keymap\n" " --drop-unused disable unused bits serialization\n" #else " -1, --uniline enable uniline event output\n" " --multiline enable multiline event output\n" #endif " --verbose enable verbose debugging output\n" " --help display this help and exit\n" ); } int main(int argc, char *argv[]) { int ret; bool verbose = false; xcb_connection_t *conn; uint8_t first_xkb_event; int32_t core_kbd_device_id; struct xkb_context *ctx; struct keyboard core_kbd = {0}; struct xkb_compose_table *compose_table = NULL; #ifndef KEYMAP_DUMP bool with_keymap_file = false; enum xkb_keymap_format keymap_format = DEFAULT_INPUT_KEYMAP_FORMAT; const char *keymap_path = NULL; bool with_compose = false; const char *locale; #endif enum options { OPT_VERBOSE, OPT_UNILINE, OPT_MULTILINE, OPT_COMPOSE, OPT_LOCAL_STATE, OPT_KEYMAP_FORMAT, OPT_KEYMAP_NO_PRETTY, OPT_KEYMAP_DROP_UNUSED, OPT_KEYMAP, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, OPT_VERBOSE}, {"format", required_argument, 0, OPT_KEYMAP_FORMAT}, #ifdef KEYMAP_DUMP {"no-pretty", no_argument, 0, OPT_KEYMAP_NO_PRETTY}, {"drop-unused", no_argument, 0, OPT_KEYMAP_DROP_UNUSED}, #else {"uniline", no_argument, 0, OPT_UNILINE}, {"multiline", no_argument, 0, OPT_MULTILINE}, {"enable-compose", no_argument, 0, OPT_COMPOSE}, {"local-state", no_argument, 0, OPT_LOCAL_STATE}, {"keymap", optional_argument, 0, OPT_KEYMAP}, #endif {0, 0, 0, 0}, }; setlocale(LC_ALL, ""); while (1) { int opt; int option_index = 0; opt = getopt_long(argc, argv, "*1h", opts, &option_index); if (opt == -1) break; switch (opt) { case OPT_VERBOSE: verbose = true; break; case OPT_KEYMAP_FORMAT: /* * This is either: * - the input format for the interactive tool * - the output format for the dump tool */ keymap_format = xkb_keymap_parse_format(optarg); if (!keymap_format) { fprintf(stderr, "ERROR: invalid --format \"%s\"\n", optarg); usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } break; #ifdef KEYMAP_DUMP case OPT_KEYMAP_NO_PRETTY: serialize_flags &= ~XKB_KEYMAP_SERIALIZE_PRETTY; break; case OPT_KEYMAP_DROP_UNUSED: serialize_flags &= ~XKB_KEYMAP_SERIALIZE_KEEP_UNUSED; break; #else case OPT_COMPOSE: with_compose = true; break; case OPT_LOCAL_STATE: local_state: use_local_state = true; break; case OPT_KEYMAP: with_keymap_file = true; /* Optional arguments require `=`, but we want to make this * requirement optional too, so that both `--keymap=xxx` and * `--keymap xxx` work. */ if (!optarg && argv[optind] && (argv[optind][0] != '-' || strcmp(argv[optind], "-") == 0 )) { keymap_path = argv[optind++]; } else { keymap_path = optarg; } /* --local-state is implied */ goto local_state; case '1': case OPT_UNILINE: print_options |= PRINT_UNILINE; break; case '*': case OPT_MULTILINE: print_options &= ~PRINT_UNILINE; break; #endif case 'h': usage(stdout, argv[0]); return EXIT_SUCCESS; default: #ifndef KEYMAP_DUMP invalid_usage: #endif usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } } #ifndef KEYMAP_DUMP if (optind < argc && !isempty(argv[optind])) { /* Some positional arguments left: use as a keymap input */ if (keymap_path) goto too_much_arguments; keymap_path = argv[optind++]; if (optind < argc) { /* Further positional arguments is an error */ too_much_arguments: fprintf(stderr, "ERROR: Too many positional arguments\n"); goto invalid_usage; } with_keymap_file = true; } else if (is_pipe_or_regular_file(STDIN_FILENO) && !with_keymap_file) { /* No positional argument: piping detected */ with_keymap_file = true; } if (with_keymap_file) { /* --local-state is implied with custom keymap */ use_local_state = true; } if (isempty(keymap_path) || strcmp(keymap_path, "-") == 0) keymap_path = NULL; #endif conn = xcb_connect(NULL, NULL); if (!conn || xcb_connection_has_error(conn)) { fprintf(stderr, "Couldn't connect to X server: error code %d\n", conn ? xcb_connection_has_error(conn) : -1); ret = -1; goto err_out; } ret = xkb_x11_setup_xkb_extension(conn, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION, XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, NULL, NULL, &first_xkb_event, NULL); if (!ret) { fprintf(stderr, "Couldn't setup XKB extension\n"); goto err_conn; } ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!ctx) { ret = -1; fprintf(stderr, "Couldn't create xkb context\n"); goto err_conn; } if (verbose) tools_enable_verbose_logging(ctx); #ifndef KEYMAP_DUMP if (with_keymap_file) { FILE *file = NULL; if (keymap_path) { /* Read from regular file */ file = fopen(keymap_path, "rb"); } else { /* Read from stdin */ file = tools_read_stdin(); } if (!file) { fprintf(stderr, "ERROR: Failed to open keymap file \"%s\": %s\n", keymap_path ? keymap_path : "stdin", strerror(errno)); xkb_context_unref(ctx); goto err_out; } custom_keymap = xkb_keymap_new_from_file(ctx, file, keymap_format, XKB_KEYMAP_COMPILE_NO_FLAGS); } if (with_compose) { locale = setlocale(LC_CTYPE, NULL); compose_table = xkb_compose_table_new_from_locale(ctx, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); if (!compose_table) { fprintf(stderr, "Couldn't create compose from locale\n"); goto err_compose; } } else { compose_table = NULL; } #endif core_kbd_device_id = xkb_x11_get_core_keyboard_device_id(conn); if (core_kbd_device_id == -1) { ret = -1; fprintf(stderr, "Couldn't find core keyboard device\n"); goto err_ctx; } ret = init_kbd(&core_kbd, conn, first_xkb_event, core_kbd_device_id, ctx, compose_table); if (ret) { fprintf(stderr, "Couldn't initialize core keyboard device\n"); goto err_ctx; } #ifndef KEYMAP_DUMP ret = create_capture_window(conn); if (ret) { fprintf(stderr, "Couldn't create a capture window\n"); goto err_window; } tools_disable_stdin_echo(); ret = loop(conn, &core_kbd); tools_enable_stdin_echo(); err_window: xkb_compose_table_unref(compose_table); err_compose: #endif deinit_kbd(&core_kbd); err_ctx: xkb_context_unref(ctx); err_conn: xcb_disconnect(conn); err_out: #ifndef KEYMAP_DUMP xkb_keymap_unref(custom_keymap); #endif exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE); } xkbcommon-libxkbcommon-54ee7ac/tools/interactive.c000066400000000000000000000021441510033435100225050ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include "src/utils.h" #include "tools-common.h" #ifdef KEYMAP_DUMP #define TOOL "dump-keymap" #else #define TOOL "interactive" #endif int main(int argc, char **argv) { const char *new_argv[64] = {NULL}; new_argv[0] = select_backend( #if HAVE_XKBCLI_INTERACTIVE_WAYLAND TOOL "-wayland", #else NULL, #endif #if HAVE_XKBCLI_INTERACTIVE_X11 TOOL "-x11", #else NULL, #endif #if HAVE_XKBCLI_INTERACTIVE_EVDEV && !defined(KEYMAP_DUMP) TOOL "-evdev" #else NULL #endif ); if (new_argv[0] == NULL) { fprintf( stderr, "ERROR: Unable to find a proper backend for " #ifdef KEYMAP_DUMP "keymap dumping\n" #else "interactive debugging\n" #endif ); return EXIT_FAILURE; } for (int k = 1; k < MIN(argc, (int) ARRAY_SIZE(new_argv)); k++) { new_argv[k] = argv[k]; } return tools_exec_command("xkbcli", argc, new_argv); } xkbcommon-libxkbcommon-54ee7ac/tools/introspection-query.py.in000077500000000000000000000654331510033435100250630ustar00rootroot00000000000000#!/usr/bin/env python3 # Copyright © 2025 Pierre Le Marre # SPDX-License-Identifier: MIT from __future__ import annotations import argparse from collections import defaultdict from collections.abc import Callable, Iterable, Iterator import dataclasses from dataclasses import dataclass from enum import StrEnum, auto, unique from functools import partial import itertools import multiprocessing import os from pathlib import Path import re import subprocess import sys import textwrap from typing import Any, ClassVar, Protocol, Self, TextIO, TypeVar, cast import rdflib import yaml # Meson needs to fill this in so we can call the tool in the buildir. EXTRA_PATH = "@MESON_BUILD_ROOT@" os.environ["PATH"] = ":".join(filter(bool, (EXTRA_PATH, os.getenv("PATH")))) @unique class Component(StrEnum): Keycodes = auto() Compatibility = auto() Geometry = auto() Symbols = auto() Types = auto() @classmethod def parse(cls, raw: str) -> Self: for c in cls: if c.value == raw: return c raise ValueError(raw) @property def dir(self) -> Path: match self: case self.Compatibility: return Path("compat") case _: return Path(self) @dataclass class Model: name: str @dataclass class Layout: name: str variants: set[str] PATTERN: ClassVar[re.Pattern[str]] = re.compile( r"^(?P[^\(]+)(?:\((?P
[^\)]+)\))$" ) @classmethod def parse(cls, raw: str) -> Self: if m := cls.PATTERN.match(raw): return cls(name=m.group("file"), variants={m.group("section")}) else: return cls(name=raw, variants=set()) @dataclass class Option: name: str @dataclass class RMLVO: rules: str model: str layout: str variant: str option: str def __iter__(self) -> Iterator[tuple[str, str]]: yield from dataclasses.asdict(self).items() @dataclass(unsafe_hash=True) class XkbFileRef: file: str section: str = "" path: Path | None = None PATTERN: ClassVar[re.Pattern[str]] = re.compile( r"^(?P[^\(]+)(?:\((?P
[^\)]+)\))$" ) @classmethod def parse(cls, raw: str) -> Self: if m := cls.PATTERN.match(raw): return cls(file=m.group("file"), section=m.group("section")) else: return cls(file=raw) def resolve_path(self, xkb_roots: Iterable[Path], component: Component) -> bool: args = ["introspection"] + list( itertools.chain.from_iterable(("--include", str(p)) for p in xkb_roots) ) args += ["--resolve", "--type", str(component.dir)] if self.section: args += ["--section", self.section] args.append(self.file) try: completed = subprocess.run(args, check=True, capture_output=True) raw = yaml.safe_load(completed.stdout) self.path = raw["path"] self.section = raw["section"] return True except subprocess.CalledProcessError: print(f"ERROR cannot resolve: {self}", file=sys.stderr) return False @property def uri(self) -> str: if self.path is not None: return f"file:{self.path}#section={self.section}" else: # FIXME return f"file:{self.file}#section={self.section}" @dataclass class KcCGSTAcc: keycodes: set[XkbFileRef] compat: set[XkbFileRef] geometry: set[XkbFileRef] symbols: set[XkbFileRef] types: set[XkbFileRef] @classmethod def parse_component(cls, raw: str) -> Iterator[XkbFileRef]: start = 0 for k in range(0, len(raw)): if raw[k] in ("+", "|", "^"): current = raw[start:k] start = k + 1 if not current: continue raw_ref, *_ = current.split(":") yield XkbFileRef.parse(raw_ref) current = raw[start:] if current: raw_ref, *_ = current.split(":") yield XkbFileRef.parse(raw_ref) @classmethod def parse(cls, raw: dict[str, str]) -> Self: return cls( keycodes=set(cls.parse_component(raw["keycodes"])), compat=set(cls.parse_component(raw["compat"])), geometry=set(cls.parse_component(raw.get("geometry", ""))), symbols=set(cls.parse_component(raw["symbols"])), types=set(cls.parse_component(raw["types"])), ) def __iter__(self) -> Iterator[tuple[Component, XkbFileRef]]: yield from ((Component.Keycodes, ref) for ref in self.keycodes) yield from ((Component.Compatibility, ref) for ref in self.compat) yield from ((Component.Geometry, ref) for ref in self.geometry) yield from ((Component.Symbols, ref) for ref in self.symbols) yield from ((Component.Types, ref) for ref in self.types) @classmethod def empty(cls) -> Self: return cls(set(), set(), set(), set(), set()) def merge(self, other: Self): self.keycodes.update(other.keycodes) self.compat.update(other.compat) self.geometry.update(other.geometry) self.symbols.update(other.symbols) self.types.update(other.types) @classmethod def _resolve_paths( cls, xkb_roots: Iterable[Path], component: Component, refs: Iterable[XkbFileRef] ): for ref in refs: ref.resolve_path(xkb_roots, component) def resolve_paths(self, *xkb_roots: Path): self._resolve_paths( xkb_roots=xkb_roots, component=Component.Keycodes, refs=self.keycodes ) self._resolve_paths( xkb_roots=xkb_roots, component=Component.Compatibility, refs=self.compat ) self._resolve_paths( xkb_roots=xkb_roots, component=Component.Geometry, refs=self.geometry ) self._resolve_paths( xkb_roots=xkb_roots, component=Component.Symbols, refs=self.symbols ) self._resolve_paths( xkb_roots=xkb_roots, component=Component.Types, refs=self.types ) @dataclass class Registry: rules: str models: tuple[Model, ...] layouts: tuple[Layout, ...] options: tuple[Option, ...] DEFAULT_RULES: ClassVar[str] = "@DEFAULT_XKB_RULES@" DEFAULT_MODEL: ClassVar[str] = "@DEFAULT_XKB_MODEL@" DEFAULT_LAYOUT: ClassVar[str] = "@DEFAULT_XKB_LAYOUT@" DEFAULT_VARIANT: ClassVar[str] = "@DEFAULT_XKB_VARIANT@" DEFAULT_OPTIONS: ClassVar[str] = "@DEFAULT_XKB_OPTIONS@" @classmethod def parse(cls, rules: str, *include: Path) -> Self: args = ( "xkbcli-list", "--ruleset", rules, "--load-exotic", "--skip-default-paths", ) + tuple(map(str, include)) try: completed = subprocess.run(args, check=True, capture_output=True) except subprocess.CalledProcessError as err: raise ValueError(err.stderr) raw: dict[str, Any] = yaml.safe_load(completed.stdout) return cls( rules=rules, models=tuple(cls.parse_models(raw)), layouts=tuple(cls.parse_layouts(raw)), options=tuple(cls.parse_options(raw)), ) @classmethod def parse_models(cls, raw: dict[str, Iterable[dict[str, str]]]) -> Iterator[Model]: for model in raw["models"]: yield Model(model["name"]) @classmethod def parse_layouts( cls, raw: dict[str, Iterable[dict[str, str]]] ) -> Iterator[Layout]: layouts: dict[str, set[str]] = defaultdict(set) for layout in raw["layouts"]: layouts[layout["layout"]].add(layout.get("variant", "")) yield from ( Layout(name=layout, variants=variants) for layout, variants in layouts.items() ) @classmethod def parse_options( cls, raw: dict[str, Iterable[dict[str, Any]]] ) -> Iterator[Option]: for option_group in raw["option_groups"]: for option in option_group["options"]: yield Option(option["name"]) def mlvo_iterator( self, models: Iterable[Model] | None = None, layouts: Iterable[Layout] | None = None, options: Iterable[Option] | None = None, ) -> tuple[int, Callable[[], Iterator[RMLVO]]]: models = self.models if models is None else models layouts = self.layouts if layouts is None else layouts options = self.options if options is None else options # In order to avoid combinatorial explosion, we limit to # model/layout/variant and layout/variant/options combinations. count1 = len(models) * sum(len(l.variants) for l in layouts) count2 = sum(len(l.variants) for l in layouts) * len(options) count = count1 + count2 def iterate(): for m in models: for l in layouts: for v in l.variants: yield RMLVO( rules=self.rules, model=m.name, layout=l.name, variant=v, option="", ) for opt in options: for m in (Model(self.DEFAULT_MODEL),): for l in layouts: for v in l.variants: yield RMLVO( rules=self.rules, model=m.name, layout=l.name, variant=v, option=opt.name, ) return count, iterate @classmethod def _get_kccgst( cls, xkb_roots: tuple[Path, ...], rmlvo: RMLVO ) -> tuple[bool, KcCGSTAcc]: args = ["xkbcli-compile-keymap", "--kccgst-yaml"] args += list( itertools.chain.from_iterable(("--include", str(p)) for p in xkb_roots) ) args += list(itertools.chain.from_iterable((f"--{c}", v) for c, v in rmlvo)) try: completed = subprocess.run(args, check=True, capture_output=True) raw = yaml.safe_load(completed.stdout) return True, KcCGSTAcc.parse(raw) except subprocess.CalledProcessError: return False, KcCGSTAcc.empty() def get_kccgst( self, xkb_roots: Iterable[Path], combos: Iterable[RMLVO], combos_count: int, njobs: int, chunksize: int, progress_bar: ProgressBar[Iterable[tuple[bool, KcCGSTAcc]]], ) -> KcCGSTAcc: # failed = False acc = KcCGSTAcc.empty() roots = tuple(xkb_roots) with multiprocessing.Pool(njobs) as p: f = partial(self._get_kccgst, roots) results = p.imap_unordered(f, combos, chunksize=chunksize) for ok, result in progress_bar( results, total=combos_count, file=sys.stdout ): if not ok: # failed = True pass else: acc.merge(result) return acc T = TypeVar("T") # Needed because Callable does not handle keywords args class ProgressBar(Protocol[T]): def __call__(self, x: T, total: int, file: TextIO | None) -> T: ... # The function generating the progress bar (if any). def create_progress_bar(verbose: bool) -> ProgressBar[T]: def noop_progress_bar(x: T, total: int, file: TextIO | None = None) -> T: return x progress_bar: ProgressBar[T] = noop_progress_bar if not verbose and os.isatty(sys.stdout.fileno()): try: from tqdm import tqdm progress_bar = cast(ProgressBar[T], tqdm) except ImportError: pass return progress_bar @unique class OutputFormat(StrEnum): Dot = auto() Rdf = auto() # Svg = auto() Yaml = auto() # RDF namespaces namespaces = {"xkb": "xkb:", "flags": "xkb:flags/"} def parse_file(path: Path) -> rdflib.Graph: g = rdflib.Graph() return g.parse(path) def run_dependencies(args: argparse.Namespace): g = parse_file(args.path) property_path = "(xkb:includes+/(rdf:first|rdf:rest)+/rdf:first)" query_keymap = "SELECT (true AS ?ok) WHERE { [] rdf:type xkb:keymap . }" query_root = """ SELECT ?path ?section WHERE { [] rdf:type xkb:Introspection; xkb:path ?path ; xkb:section ?section . } """ query_default = """ SELECT ?path ?section ?index ?default WHERE { [] rdf:type xkb:Introspection; xkb:path ?path . ?node xkb:path ?path ; xkb:section ?section ; xkb:section-index ?index ; OPTIONAL { ?node xkb:flag flags:default . BIND (true as ?default) } } ORDER BY ASC(?index) """ if args.file: # Look for specific file ref = XkbFileRef(file=args.file, section=args.section or "") if args.file.is_absolute(): ref.path = args.file.resolve() elif args.type: if not ref.resolve_path(xkb_roots=args.include or (), component=args.type): raise ValueError(f"Cannot resolve: {ref}") else: raise ValueError(f"Missing file type to resolve {ref}") node = f"<{ref.uri}>" elif r := g.query(query_keymap, initNs=namespaces): # Look for keymap sections node = "[ rdf:type xkb:keymap ] xkb:includes ?node . ?node" elif rs := g.query(query_root, initNs=namespaces): r0 = tuple(rs)[0] if args.debug: print(r0, file=sys.stderr) path = Path(r0[0].toPython()) # Try to use the section from the CLI or from the xkb:Inspection if (section := args.section) is None and not ( section := tuple(rs)[0][1].toPython() ): # No section defined: look for the default map (implicit or explicit) if rs := g.query(query_default, initNs=namespaces): rs = tuple(rs) r0 = rs[0] path = Path(r0[0].toPython()) for r in rs: if r[3].toPython(): r0 = r break if args.debug: print( *map( lambda x: tuple( map(lambda f: None if f is None else f.toPython(), x) ), rs, ), sep="\n", file=sys.stderr, ) print("Found:", r0, file=sys.stderr) section = r0[1] else: raise ValueError("Cannot determine map") ref = XkbFileRef(path, section, path) node = f"<{ref.uri}>" else: raise ValueError() type_ = ( f"VALUES (?type) {{ (xkb:{args.type.value}) }}" if args.type is not None else "" ) transitive = "+" if args.transitive else "" query = textwrap.dedent(f"""\ SELECT DISTINCT ?type ?path ?section WHERE {{ {type_} {node} rdf:type ?type ; {property_path}{transitive} [ xkb:path ?path ; xkb:section ?section ] . }} """) if args.debug: print(query, file=sys.stderr) results: dict[str, list[dict[str, str]]] = defaultdict(list) for r in g.query(query, initNs=namespaces): data = {"path": r[1].toPython(), "section": r[2].toPython()} results[r[0].toPython().split(":")[1]].append(data) for r in results.values(): r.sort(key=lambda x: x["path"]) yaml.dump(dict(results), stream=sys.stdout) def run_use(args: argparse.Namespace): g = parse_file(args.path) # Apply inference xkb = rdflib.Namespace("xkb:") used_in = xkb["used-in-rules"] inc = xkb["includes"] ts = [] def traverseList(node, g): for f in g.objects(node, rdflib.RDF.first): yield f for r in g.objects(node, rdflib.RDF.rest): yield from traverseList(r, g) def includes(node, g): for l in g.objects(node, inc): for x in g.transitiveClosure(traverseList, l): for y in g.transitiveClosure(traverseList, x): yield from g.objects(y, inc) for f, rules in g.subject_objects(used_in): for node in g.transitiveClosure(includes, f): ts.append((node, used_in, rules)) for t in ts: g.add(t) type_ = ( f"VALUES (?type) {{ (xkb:{args.type.value}) }}" if args.type is not None else "" ) rules = f'VALUES (?rules) {{ ("{args.rules}") }}' if args.rules is not None else "" if args.file: # Check for a specific file if args.type is None: raise ValueError("Missing mandatory component type") ref = XkbFileRef(file=args.file, section=args.section) ref.resolve_path(xkb_roots=args.include, component=args.type) values = "VALUES " + ( f'(?path ?section) {{ ("{ref.path}" "{ref.section}") }}' if args.section else f'(?path) {{ ("{ref.path}") }}' ) else: values = "" # property_path = "(xkb:includes/(rdf:first|rdf:rest)+/rdf:first/xkb:includes)" if args.unused: # filter = f"""\ # FILTER NOT EXISTS {{ ?node xkb:used-in-rules ?rules . }} # FILTER NOT EXISTS {{ # ?parent {property_path}+ ?node ; # rdf:type ?type ; # xkb:used-in-rules ?rules . # }}""" filter = "FILTER NOT EXISTS { ?node xkb:used-in-rules ?rules . }" else: # filter = f"""\ # FILTER EXISTS {{ # {{ ?node xkb:used-in-rules ?rules . }} # UNION # {{ # ?parent {property_path}+ ?node ; # rdf:type ?type ; # xkb:used-in-rules ?rules . # }} # }} # """ filter = "?node xkb:used-in-rules ?rules ." query = textwrap.dedent(f"""\ SELECT DISTINCT ?rules ?type ?path ?section WHERE {{ {type_} {rules} {values} ?node rdf:type ?type ; xkb:path ?path ; xkb:section ?section . {filter} FILTER NOT EXISTS {{ ?node rdf:type xkb:Introspection }} }} """) if args.debug: print(query, file=sys.stderr) result: dict[str, dict[str, str]] = defaultdict(list) for r in g.query(query, initNs=namespaces): data = {"path": r[2].toPython(), "section": r[3].toPython()} if not args.unused: data["rules"] = r[0].toPython() # if args.type is None: # data["type"] = r[1].toPython().split(":")[1] ty = r[1].toPython().split(":")[1] result[ty].append(data) for r in result.values(): r.sort(key=lambda x: x["path"]) yaml.dump(dict(result), stream=sys.stdout) def run_query(args: argparse.Namespace): g = parse_file(args.path) for r in g.query(args.query, initNs=namespaces): print(r) def run_pretty(args: argparse.Namespace): g = parse_file(args.path) print(g.serialize()) def get_xkb_files(path: Path, components: Iterable[Component]) -> Iterator[Path]: for component in components: for dirpath, _dirnames, filenames in (path / component.dir).walk(): # Discard files with suffixes, such as *.md files yield from ( dirpath / f for f in map(Path, filenames) if not f.suffix and f.stem != "README" ) def run_process_trees(args: argparse.Namespace): components = args.type if args.type else Component paths = tuple( itertools.chain.from_iterable( map(partial(get_xkb_files, components=components), args.path) ) ) tool_args: list[str] = ["introspection"] tool_args += list( itertools.chain.from_iterable(("--include", p) for p in args.path) ) tool_args += args.extra tool_args += list(map(str, paths)) try: completed = subprocess.run( tool_args, check=True, ) return completed.returncode except subprocess.CalledProcessError as err: return err.returncode def run_process_rules(args: argparse.Namespace): registry = Registry.parse(args.rules, *args.path) count, iterator = registry.mlvo_iterator( models=args.model, layouts=args.layout, options=args.option ) progress_bar: ProgressBar[Iterable[Any]] = create_progress_bar(False) acc = registry.get_kccgst( xkb_roots=args.path, combos=iterator(), combos_count=count, njobs=args.jobs, chunksize=args.chunksize, progress_bar=progress_bar, ) acc.resolve_paths(*args.path) with args.output.open("wt", encoding="utf-8") as fd: if args.rdf: print("@prefix\txkb:\t .", file=fd) for _ty, ref in acc: print(f'<{ref.uri}>\txkb:used-in-rules\t"{args.rules}" .', file=fd) else: prev_ty = None for ty, ref in acc: if ty != prev_ty: print(f"{ty}:", file=fd) prev_ty = ty print(f'- file: "{ref.file}"', file=fd) print(f' section: "{ref.section}"', file=fd) if ref.path is not None: print(f' path: "{ref.path}"', file=fd) else: print(" path: null", file=fd) if __name__ == "__main__": parser = argparse.ArgumentParser( # FIXME: description description="Tool to process the RDF output of xkbcommon introspection" ) parser.add_argument("--debug", action="store_true", help="Debug mode") subparsers = parser.add_subparsers() # Dependencies parser_deps = subparsers.add_parser( "dependencies", aliases=("deps",), help="Dependencies of a map" ) parser_deps.add_argument( "path", type=argparse.FileType("rt", encoding="utf-8"), help="RDF Turtle file" ) parser_deps.add_argument( "-i", "--include", type=Path, action="append", default=[], help="XKB root path" ) parser_deps.add_argument("-f", "--file", type=Path, help="XKB file") parser_deps.add_argument("-s", "--section", type=str, help="Section in a XKB file") parser_deps.add_argument( "-t", "--type", type=Component.parse, help="Component type" ) parser_deps.add_argument( "-T", "--transitive", action="store_true", help="Enable transitive dependencies" ) parser_deps.set_defaults(run=run_dependencies) # Used/unused parser_use = subparsers.add_parser("use", help="List used/unused file & sections") parser_use.add_argument( "path", type=argparse.FileType("rt", encoding="utf-8"), help="RDF Turtle file" ) parser_use.add_argument( "-U", "--unused", action="store_true", help="Search unused files" ) parser_use.add_argument( "-i", "--include", type=Path, action="append", default=[], help="XKB root path" ) parser_use.add_argument("-r", "--rules", type=str, help="XKB ruleset") parser_use.add_argument("-f", "--file", type=Path, help="XKB file") parser_use.add_argument("-s", "--section", type=str, help="Section in a XKB file") parser_use.add_argument("-t", "--type", type=Component.parse, help="Component type") parser_use.set_defaults(run=run_use) # Query parser_query = subparsers.add_parser("query", help="SPARQL query") parser_query.add_argument( "path", type=argparse.FileType("rt", encoding="utf-8"), help="RDF Turtle file" ) parser_query.add_argument( "-q", "--query", type=str, help="SPARQL query", required=True ) parser_query.set_defaults(run=run_query) # Prettyfier parser_pretty = subparsers.add_parser("pretty", help="Prettyfier") parser_pretty.add_argument( "path", type=argparse.FileType("rt", encoding="utf-8"), help="RDF Turtle file" ) parser_pretty.set_defaults(run=run_pretty) # XKB tree analyzer parser_tree = subparsers.add_parser( "tree", help="Analyze XKB trees", description="Analyze XKB trees", epilog="Use `--` to pass extra arguments to the `introspection` tool", ) parser_tree.add_argument( "path", nargs="*", type=Path, help="Path to a XKB tree", ) parser_tree.add_argument( "-t", "--type", default=[], action="append", type=Component.parse, help="Component type", ) parser_tree.set_defaults(run=run_process_trees) # XKB rules analyzer parser_rules = subparsers.add_parser( "rules", help="Analyze XKB rules", description="Analyze XKB rules", epilog="Use `--` to pass extra arguments to the `introspection` tool", ) parser_rules.add_argument( "path", nargs="*", type=Path, help="Path to a XKB tree", ) parser_rules.add_argument( "-j", "--jobs", type=int, default=4 * (os.cpu_count() or 1), help="number of processes to use", ) parser_rules.add_argument("--chunksize", default=1, type=int) parser_rules.add_argument( "-r", "--rules", default="evdev", type=str, help="Ruleset", ) parser_rules.add_argument( "-m", "--model", action="append", type=Model, help="Only specific models", ) parser_rules.add_argument( "-l", "--layout", action="append", type=Layout.parse, help="Only specific layouts", ) parser_rules.add_argument( "-o", "--option", action="append", type=Option, help="Only specific options", ) parser_rules.add_argument( "-t", "--type", default=[], action="append", type=Component.parse, help="Component type", ) parser_rules.add_argument( "--rdf", action="store_true", help="Output in RDF format", ) parser_rules.add_argument("--output", type=Path, help="Output file", required=True) parser_rules.set_defaults(run=run_process_rules) # Misc if "--" in sys.argv: idx = sys.argv.index("--") argv = sys.argv[1:idx] extra = sys.argv[idx + 1 :] else: argv = sys.argv[1:] extra = [] # Run args = parser.parse_args(argv) args.extra = extra # [HACK] if hasattr(args, "option") and args.option == [Option("-")]: args.option = () exit(args.run(args)) xkbcommon-libxkbcommon-54ee7ac/tools/introspection.c000066400000000000000000001243061510033435100230750ustar00rootroot00000000000000/* * Copyright © 2025 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include #include #include #include #include "xkbcommon/xkbcommon.h" #include "ast.h" #include "tools-common.h" #include "src/darray.h" #include "src/utils.h" #include "src/utils-paths.h" #include "src/keymap-formats.h" #include "src/xkbcomp/keymap-file-iterator.h" /* * The output is meant to be valid YAML; however we do not enforce it * because we expect the file and section names to be valid text values. */ enum input_source { INPUT_SOURCE_AUTO = 0, INPUT_SOURCE_STDIN, INPUT_SOURCE_PATH }; enum output_format { OUTPUT_FORMAT_YAML = 0, OUTPUT_FORMAT_DOT, OUTPUT_FORMAT_RDF_TURTLE, OUTPUT_FORMAT_RESOLVED_PATH, }; enum output_options { OUTPUT_NO_OPTIONS = 0, OUTPUT_YAML_SHORT_LABELS = (1u << 0), }; static const unsigned int indent_size = 2; static enum xkb_file_type xkb_parse_file_type(const char *raw) { static struct { enum xkb_file_type type; const char *name; } xkb_file_type_strings[_FILE_TYPE_NUM_ENTRIES] = { {FILE_TYPE_KEYCODES, "keycodes"}, {FILE_TYPE_TYPES, "types"}, {FILE_TYPE_COMPAT, "compat"}, {FILE_TYPE_SYMBOLS, "symbols"}, {FILE_TYPE_GEOMETRY, "geometry"}, {FILE_TYPE_RULES, "rules"}, }; for (size_t t = 0; t < ARRAY_SIZE(xkb_file_type_strings); t++) { if (streq_not_null(raw, xkb_file_type_strings[t].name)) return xkb_file_type_strings[t].type; } return FILE_TYPE_INVALID; } /** * Try to get the relative path of a file in a XKB hierarchy * * This is a fragile! We could improve it by using the context include paths, * but the analyzed path may be in a XKB hierarchy but not in the include paths. */ static const char* xkb_relative_path(const char *path) { static const char * xkb_file_type_include_dirs[] = { "keycodes/", "types/", "compat/", "symbols/", "geometry/", // TODO: "keymap/", // TODO: "rules/", }; for (size_t t = 0; t < ARRAY_SIZE(xkb_file_type_include_dirs); t++) { const char * const rel = strstr(path, xkb_file_type_include_dirs[t]); if (rel != NULL) { return rel + strlen(xkb_file_type_include_dirs[t]); } } return NULL; } static bool is_stdin_path(const char *path) { return isempty(path) || strcmp(path, "-") == 0; } static bool print_included_section(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_format output_format, enum output_options output_options, enum xkb_keymap_format keymap_input_format, const char *path, const char *map, unsigned int include_depth, unsigned int ident_depth, const char *parent); /******************************************************************************* * YAML output ******************************************************************************/ static void print_yaml_flags(unsigned int indent, enum xkb_map_flags flags) { printf("%*sflags: [", indent, ""); bool first = true; const char *flag_name = NULL; unsigned int index = 0; while ((flag_name = xkb_map_flags_string_iter(&index, flags))) { if (first) first = false; else printf(", "); printf("%s", flag_name); } printf("]\n"); } static bool print_yaml_included_sections(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_options output_options, enum xkb_keymap_format format, const struct xkb_file_section *section, unsigned int include_depth, unsigned int ident_depth, bool recursive) { if (darray_size(section->includes)) { bool ok = true; const unsigned int indent1 = ident_depth * indent_size; printf("%*sincludes:\n", indent1, ""); struct xkb_file_include_group *group; darray_foreach(group, section->include_groups) { assert(group->end < darray_size(section->includes)); unsigned int indent2 = indent1; unsigned int ident_depth2 = ident_depth; if (group->start != group->end) { /* Multiple files included in a single statement */ const enum merge_mode merge_mode = darray_item(section->includes, group->start).merge; printf("%*s- merge mode: %s\n", indent1, "", xkb_merge_mode_name(merge_mode)); printf("%*s files:\n", indent1, ""); ident_depth2 += 1; indent2 = ident_depth2 * indent_size; } for (darray_size_t i = group->start; i <= group->end; i++) { const struct xkb_file_include * const inc = &darray_item(section->includes, i); printf("%*s- merge mode: %s\n", indent2, "", xkb_merge_mode_name(inc->merge)); printf("%*s file: \"%s\"\n", indent2, "", xkb_file_section_get_string(section, inc->file)); printf("%*s section: \"%s\"\n", indent2, "", xkb_file_section_get_string(section, inc->section)); printf("%*s explicit section: %s\n", indent2, "", (inc->explicit_section ? "true" : "false")); printf("%*s path: \"%s\"\n", indent2, "", xkb_file_section_get_string(section, inc->path)); const char * const modifier = xkb_file_section_get_string(section, inc->modifier); if (!isempty(modifier)) printf("%*s modifier: \"%s\"\n", indent2, "", modifier); if (inc->valid) { print_yaml_flags(indent2 + indent_size, inc->flags); } else { printf("%*s valid: false\n", indent2, ""); } if (recursive && inc->valid) { ok = print_included_section( ctx, iterator_flags, OUTPUT_FORMAT_YAML, output_options, format, xkb_file_section_get_string(section, inc->path), xkb_file_section_get_string(section, inc->section), include_depth + 1, ident_depth2 + 1, NULL ); if (!ok) break; } } } return ok; } else { return true; } } static bool print_yaml(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_options output_options, enum xkb_keymap_format keymap_format, int path_index, const char *path, bool recursive, struct xkb_file_iterator *iter) { bool ok = true; const struct xkb_file_section *section; if (path_index > 0) { /* New YAML document */ printf("---\n"); } printf("path: \"%s\"\n", (is_stdin_path(path) ? "stdin" : path)); printf("sections:"); bool has_sections = false; while ((ok = xkb_file_iterator_next(iter, §ion)) && section) { has_sections = true; printf("\n- type: %s", xkb_file_type_name(section->file_type)); printf("\n section: \"%s\"\n", xkb_file_section_get_string(section, section->name)); print_yaml_flags(indent_size, section->flags); print_yaml_included_sections(ctx, iterator_flags, output_options, keymap_format, section, 0, 1, recursive); } if (!has_sections) printf(" []\n"); return ok; } /******************************************************************************* * Resolved path output ******************************************************************************/ static bool print_resolved_path(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_options output_options, enum xkb_keymap_format keymap_format, int path_index, const char *path, bool recursive, struct xkb_file_iterator *iter) { bool ok = true; const struct xkb_file_section *section; if (path_index > 0) { /* New YAML document */ printf("---\n"); } printf("path: \"%s\"\n", (is_stdin_path(path) ? "stdin" : path)); while ((ok = xkb_file_iterator_next(iter, §ion)) && section) { printf("type: %s\n", xkb_file_type_name(section->file_type)); printf("section: \"%s\"\n", xkb_file_section_get_string(section, section->name)); print_yaml_flags(0, section->flags); } return ok; } /******************************************************************************* * DOT output ******************************************************************************/ static bool print_dot_node(enum output_options output_options, const char *parent_node, darray_char *node, darray_char *label, const struct xkb_file_section *section, const struct xkb_file_include *inc) { /* Cannot print invalid includes */ if (!inc->valid) return true; /* Node identifier */ darray_size(*node) = 0; darray_append_string( *node, xkb_file_section_get_string(section, inc->path) ); if (inc->section) { darray_append_lit(*node, "("); darray_append_string( *node, xkb_file_section_get_string(section, inc->section) ); darray_append_lit(*node, ")"); } /* Node label */ darray_size(*label) = 0; darray_append_lit(*label, ""); darray_append_string( *label, ((output_options & OUTPUT_YAML_SHORT_LABELS) ? xkb_file_section_get_string(section, inc->file) : xkb_file_section_get_string(section, inc->path)) ); darray_append_lit(*label, ""); if (inc->section) { darray_append_lit(*label, "("); darray_append_string( *label, xkb_file_section_get_string(section, inc->section) ); darray_append_lit(*label, ")"); } printf("\t\"%s\" [label=<%s>];\n", darray_items(*node), darray_items(*label)); printf("\t\"%s\" -> \"%s\";\n", parent_node, darray_items(*node)); return true; } static bool print_dot_included_sections(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_options output_options, enum xkb_keymap_format format, const struct xkb_file_section *section, unsigned int include_depth, bool recursive, const char *parent) { if (darray_size(section->includes)) { bool ok = true; darray_char parent2_node = darray_new(); darray_char parent2_label = darray_new(); struct xkb_file_include *inc; darray_foreach(inc, section->includes) { assert(inc->valid); ok = print_dot_node(output_options, parent, &parent2_node, &parent2_label, section, inc); if (!ok) break; if (recursive && inc->valid) { ok = print_included_section( ctx, iterator_flags, OUTPUT_FORMAT_DOT, output_options, format, xkb_file_section_get_string(section, inc->path), xkb_file_section_get_string(section, inc->section), include_depth + 1, 0, darray_items(parent2_node) ); if (!ok) break; } } darray_free(parent2_node); darray_free(parent2_label); return ok; } else { return true; } } static bool print_dot(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_options output_options, enum xkb_keymap_format format, int path_index, const char *path, bool recursive, struct xkb_file_iterator *iter) { char root[PATH_MAX] = ""; if (is_stdin_path(path)) { if (unlikely(!strcpy_safe(root, sizeof(root), "stdin"))) { return false; } } else { #ifdef HAVE_REAL_PATH realpath(path, root); #else if (unlikely(!strcpy_safe(root, sizeof(root), path))) return false; #endif } const char * root_file = xkb_relative_path(root); bool ok = true; const struct xkb_file_section *section; darray_char root_node = darray_new(); darray_char parent_node = darray_new(); darray_char parent_label = darray_new(); unsigned int idx = 0; bool is_composite_file = false; while ((ok = xkb_file_iterator_next(iter, §ion)) && section) { if (idx == 0) { /* Check if this is a composite file */ if (section->file_type == FILE_TYPE_KEYMAP) { is_composite_file = true; } else { /* Root node set globally */ darray_append_string(root_node, root); printf("\t\"%s\" [label=<%s>, style=\"rounded,filled\"];\n", darray_items(root_node), root); if (path_index == 0) { // FIXME: handle multiple roots using subgraphs? printf("root=\"%s\";\n", darray_items(root_node)); } } } /* Node identifier */ darray_size(parent_node) = 0; /* Prefix with section type to avoid ID clashes */ if (is_composite_file) { darray_append_string(parent_node, xkb_file_type_name(section->file_type)); darray_append_lit(parent_node, ":"); } /* Append full path & section */ darray_append_string(parent_node, root); if (section->name) { darray_append_lit(parent_node, "("); darray_append_string( parent_node, xkb_file_section_get_string(section, section->name) ); darray_append_lit(parent_node, ")"); } if (section->file_type == FILE_TYPE_KEYMAP) { /* Root node set for each keymap */ assert(is_composite_file); darray_copy(root_node, parent_node); darray_append(root_node, '\0'); } /* Node label */ darray_size(parent_label) = 0; if (!is_composite_file || section->file_type == FILE_TYPE_KEYMAP) { /* Display file only for top-level components */ darray_append_lit(parent_label, ""); if (root_file && (output_options & OUTPUT_YAML_SHORT_LABELS)) { darray_append_string(parent_label, root_file); } else { darray_append_string(parent_label, root); } darray_append_lit(parent_label, ""); } if (section->name) { darray_append_lit(parent_label, "("); darray_append_string( parent_label, xkb_file_section_get_string(section, section->name) ); darray_append_lit(parent_label, ")"); } else { darray_append_string( parent_label, (is_composite_file ? "(unnamed)" : "(-)") ); } if (is_composite_file) { if (section->file_type == FILE_TYPE_KEYMAP && idx != 0) { /* Close the previous keymap subgraph */ printf("}\n"); } /* Draw each component in a subgraph */ printf("\nsubgraph \"cluster::%s\" {\n", darray_items(parent_node)); printf("\tlabel=<%s>;\n", xkb_file_type_name(section->file_type)); } /* Create edge */ if (section->file_type == FILE_TYPE_KEYMAP) { /* * Avoid keymap node being included in component clusters by * creating its own cluster. */ printf("\nsubgraph \"cluster::root::%s\" {\n", darray_items(parent_node)); printf("\tstyle=invis;\n"); printf("\t\"%s\" [label=<%s>, style=\"rounded,filled\"];\n", darray_items(parent_node), darray_items(parent_label)); printf("}\n"); printf("root=\"%s\";\n\n", darray_items(parent_node)); } else { printf("\t\"%s\" [label=<%s>];\n", darray_items(parent_node), darray_items(parent_label)); } /* Link to root */ if (section->file_type != FILE_TYPE_KEYMAP) { printf("\t\"%s\" -> \"%s\" [arrowhead=empty];\n", darray_items(root_node), darray_items(parent_node)); } print_dot_included_sections(ctx, iterator_flags, output_options, format, section, 0, recursive, darray_items(parent_node)); if (is_composite_file && section->file_type != FILE_TYPE_KEYMAP) { printf("}\n"); } idx++; } if (is_composite_file) { /* Close the keymap subgraph */ printf("}\n"); } darray_free(root_node); darray_free(parent_node); darray_free(parent_label); return ok; } /******************************************************************************* * Output format: RDF Turtle ******************************************************************************/ static void mk_rdf_path_id(darray_char *node, const char *path) { darray_append_lit(*node, "file:"); darray_append_string(*node, (is_stdin_path(path) ? "stdin" : path)); } static void mk_rdf_section_id(darray_char *node, const char *path, const char *section) { mk_rdf_path_id(node, path); darray_append_lit(*node, "#section="); darray_append_string(*node, section); } static void print_rdf_flags(enum xkb_map_flags flags) { bool first = true; const char *flag_name = NULL; unsigned int index = 0; while ((flag_name = xkb_map_flags_string_iter(&index, flags))) { if (first) first = false; else printf(", "); printf("flags:%s", flag_name); } } static bool print_rdf_sections(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_options output_options, enum xkb_keymap_format keymap_format, const struct xkb_file_section *section, unsigned int include_depth, bool recursive, const char *path, const char *map, unsigned int index, const char *node) { printf("<%s>\n", node); printf("\txkb:path\t\"%s\" ;\n", (is_stdin_path(path) ? "stdin" : path)); printf("\txkb:section\t\"%s\" ;\n", map); printf("\trdf:type\txkb:%s ;\n", xkb_file_type_name(section->file_type)); if (section->flags) { printf("\txkb:flag\t"); print_rdf_flags(section->flags); printf(" ;\n"); } printf("\txkb:section-index\t%u", index); if (darray_size(section->includes)) { bool ok = true; darray_char include_target = darray_new(); struct xkb_file_include_group *group; darray_size_t g = 0; printf(" ;\n\txkb:includes\t("); darray_enumerate(g, group, section->include_groups) { printf("\n\t\t("); for (darray_size_t f = group->start; f <= group->end; f++) { const struct xkb_file_include * const inc = &darray_item(section->includes, f); assert(inc->valid); darray_size(include_target) = 0; mk_rdf_section_id( &include_target, xkb_file_section_get_string(section, inc->path), xkb_file_section_get_string(section, inc->section) ); printf("\n\t\t\t[\n"); printf("\t\t\t\txkb:merge-mode\txkb:%s ;\n", xkb_merge_mode_name(inc->merge)); printf("\t\t\t\txkb:file\t\"%s\" ;\n", xkb_file_section_get_string(section, inc->file)); printf("\t\t\t\txkb:section\t\"%s\" ;\n", xkb_file_section_get_string(section, inc->section)); printf("\t\t\t\txkb:path\t\"%s\"", xkb_file_section_get_string(section, inc->path)); if (inc->flags) { printf(" ;\n\t\t\t\txkb:flag\t"); print_rdf_flags(inc->flags); } printf(" ;\n\t\t\t\txkb:includes\t<%s>\n", darray_items(include_target)); printf("\t\t\t]"); } printf("\n\t\t)"); } printf("\n\t) .\n\n"); if (recursive) { struct xkb_file_include * inc; darray_foreach(inc, section->includes) { if (!inc->valid) continue; darray_size(include_target) = 0; mk_rdf_section_id( &include_target, xkb_file_section_get_string(section, inc->path), xkb_file_section_get_string(section, inc->section) ); ok = print_included_section( ctx, iterator_flags, OUTPUT_FORMAT_RDF_TURTLE, output_options, keymap_format, xkb_file_section_get_string(section, inc->path), xkb_file_section_get_string(section, inc->section), include_depth + 1, 0, darray_items(include_target) ); if (!ok) break; } } darray_free(include_target); return ok; } else { printf(" .\n\n"); return true; } } static bool print_rdf(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_options output_options, enum xkb_keymap_format keymap_format, int path_index, const char *path, const char *map, bool recursive, struct xkb_file_iterator *iter) { bool ok = true; const struct xkb_file_section *section; bool is_composite_file = false; darray_char keymap = darray_new(); darray_char node = darray_new(); /* Save some CLI arguments, so that the graph is easier to query */ mk_rdf_path_id(&node, path); printf("<%s>\n", darray_items(node)); printf("\trdf:type\txkb:Introspection ;\n"); printf("\txkb:path\t\"%s\" ;\n", (is_stdin_path(path) ? "stdin" : path)); printf("\txkb:section\t\"%s\" .\n\n", (isempty(map) ? "" : map)); unsigned int index = 0; while ((ok = xkb_file_iterator_next(iter, §ion)) && section) { if (section->file_type == FILE_TYPE_KEYMAP) is_composite_file = true; darray_size(node) = 0; mk_rdf_section_id(&node, path, xkb_file_section_get_string(section, section->name)); if (is_composite_file) { /* Disambiguate components */ darray_append_lit(node, ":type="); darray_append_string(node, xkb_file_type_name(section->file_type)); if (section->file_type == FILE_TYPE_KEYMAP) { /* Backup keymap node */ darray_size(keymap) = 0; darray_copy(keymap, node); darray_append(keymap, '\0'); } else { /* Link component to parent keymap */ printf("<%s>\txkb:includes\t<%s> .\n\n", darray_items(keymap), darray_items(node)); } } print_rdf_sections(ctx, iterator_flags, output_options, keymap_format, section, 0, recursive, path, xkb_file_section_get_string(section, section->name), index, darray_items(node)); index++; } darray_free(keymap); darray_free(node); return ok; } /******************************************************************************* * Common output ******************************************************************************/ static bool print_included_section(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_format output_format, enum output_options output_options, enum xkb_keymap_format format, const char *path, const char *map, unsigned int include_depth, unsigned int ident_depth, const char *parent) { if (isempty(map)) map = NULL; struct xkb_file_section section = {0}; xkb_file_section_init(§ion); bool ok = xkb_file_section_parse(ctx, iterator_flags, format, XKB_KEYMAP_COMPILE_NO_FLAGS, include_depth, path, map, §ion); if (!ok) goto out; switch (output_format) { case OUTPUT_FORMAT_YAML: ok = print_yaml_included_sections(ctx, iterator_flags, output_options, format, §ion, include_depth, ident_depth, true); break; case OUTPUT_FORMAT_DOT: ok = print_dot_included_sections(ctx, iterator_flags, output_options, format, §ion, include_depth, true, parent); break; case OUTPUT_FORMAT_RDF_TURTLE: ok = print_rdf_sections(ctx, iterator_flags, output_options, format, §ion, include_depth, true, path, map, 0, parent); break; default: /* unreachable */ assert(!"unreachable"); } out: xkb_file_section_free(§ion); return ok; } static void print_sections_header(enum output_format output_format) { switch (output_format) { case OUTPUT_FORMAT_YAML: case OUTPUT_FORMAT_RESOLVED_PATH: break; case OUTPUT_FORMAT_DOT: printf("digraph {\n"); printf("node [shape=box, style=rounded];\n"); printf("overlap=false;\n"); printf("concentrate=true;\n"); printf("rankdir=\"LR\";\n"); printf("fontsize=\"20pt\";\n"); break; case OUTPUT_FORMAT_RDF_TURTLE: printf("@prefix\trdf:\t .\n"); printf("@prefix\txkb:\t .\n"); printf("@prefix\tflags:\t .\n\n"); break; default: assert(!"unreachable"); } } static void print_sections_footer(enum output_format output_format) { switch (output_format) { case OUTPUT_FORMAT_YAML: case OUTPUT_FORMAT_RESOLVED_PATH: case OUTPUT_FORMAT_RDF_TURTLE: break; case OUTPUT_FORMAT_DOT: /* Close graph */ printf("}\n"); break; default: assert(!"unreachable"); } } static int print_sections(struct xkb_context *ctx, enum xkb_file_iterator_flags iterator_flags, enum output_format output_format, enum output_options output_options, enum xkb_keymap_format keymap_format, enum input_source source, enum xkb_file_type file_type, int path_index, const char *path, const char *map, bool recursive) { if (source == INPUT_SOURCE_PATH && is_stdin_path(path)) { source = INPUT_SOURCE_STDIN; path = NULL; } int ret = EXIT_FAILURE; FILE *file = NULL; char resolved_path[PATH_MAX] = {0}; char resolved_section[1024] = {0}; if (source == INPUT_SOURCE_PATH && !is_stdin_path(path)) { /* Read from regular file */ const bool absolute = is_absolute_path(path); if (output_format != OUTPUT_FORMAT_RESOLVED_PATH && (absolute || file_type > FILE_TYPE_KEYMAP)) { /* * Absolute path or undefined file type: open directly. * Relative paths are resolved using the working directory as usual. */ file = fopen(path, "rb"); if (!file) { fprintf(stderr, "ERROR: Failed to open keymap file \"%s\": %s\n", path, strerror(errno)); return ret; } if (unlikely(!strcpy_safe(resolved_path, sizeof(resolved_path), path))) { goto map_error; } } else { /* * Relative path: interpret as a file in a XKB tree of the given * file type */ // TODO: this is currently a bit silly, since we are parsing the // file here and then again in the file iterator. file = xkb_resolve_file(ctx, file_type, path, (isempty(map) ? NULL : map), resolved_path, sizeof(resolved_path), resolved_section, sizeof(resolved_section)); if (!file) { fprintf(stderr, "ERROR: File not found in XKB paths: %s (section: %s)\n", path, (isempty(map)) ? "(none)" : map); return ret; } if (output_format == OUTPUT_FORMAT_RESOLVED_PATH && !isempty(resolved_section)) { assert(isempty(map) || streq(map, resolved_section)); map = resolved_section; } } } else { /* Read from stdin */ file = tools_read_stdin(); } char *string; size_t string_len; if (!map_file(file, &string, &string_len)) { fprintf(stderr, "ERROR: cannot map file\n"); goto map_error; } // FIXME: check that file_type is respected in the iterator struct xkb_file_iterator * iter = xkb_file_iterator_new_from_buffer( ctx, iterator_flags, keymap_format, XKB_KEYMAP_COMPILE_NO_FLAGS, (is_stdin_path(path) ? "(stdin)" : path), map, file_type, string, string_len ); if (!iter) { fprintf(stderr, "ERROR: cannot create iterator\n"); goto iter_error; } bool ok = true; switch (output_format) { case OUTPUT_FORMAT_YAML: ok = print_yaml(ctx, iterator_flags, output_options, keymap_format, path_index, path, recursive, iter); break; case OUTPUT_FORMAT_RESOLVED_PATH: ok = print_resolved_path(ctx, iterator_flags, output_options, keymap_format, path_index, resolved_path, recursive, iter); break; case OUTPUT_FORMAT_DOT: ok = print_dot(ctx, iterator_flags, output_options, keymap_format, path_index, path, recursive, iter); break; case OUTPUT_FORMAT_RDF_TURTLE: ok = print_rdf(ctx, iterator_flags, output_options, keymap_format, path_index, resolved_path, map, recursive, iter); break; default: /* unreachable */ assert(!"unreachable"); } xkb_file_iterator_free(iter); ret = (ok) ? EXIT_SUCCESS : EXIT_FAILURE; iter_error: unmap_file(string, string_len); map_error: if (file) fclose(file); return ret; } /******************************************************************************* * CLI handling ******************************************************************************/ static void usage(FILE *file, const char *progname) { fprintf(file, "Usage: %s [OPTIONS] [FILES]\n" "\n" "Introspect a XKB file\n" "\n" "General options:\n" " --help\n" " Print this help and exit\n" " --verbose\n" " Enable verbose debugging output\n" "\n" "Input options:\n" " --include\n" " Add the given path to the include path list. This option is\n" " order-dependent, include paths given first are searched first.\n" " If an include path is given, the default include path list is\n" " not used. Use --include-defaults to add the default include\n" " paths\n" " --include-defaults\n" " Add the default set of include directories.\n" " This option is order-dependent, include paths given first\n" " are searched first.\n" " --format \n" " The keymap format to use for parsing (default: '%d')\n" " --section \n" " The name of a specific section to parse\n" " --type \n" " The type of XKB file (KcCGST): keycodes, compatibility, geometry, symbols, types.\n" " --recursive\n" " Recursive analysis of the included sections\n" " --include-failures\n" " Do not stop on include failures but collect them (YAML only)\n" " --resolve\n" " Output resolved paths (YAML only)\n" " --yaml\n" " Output YAML\n" " --dot\n" " Output a DOT graph\n" " --rdf\n" " Output a RDF graph in the Turtle format\n" " --long-labels\n" " Output long nodes labels\n" "\n" "This program can process multiple files. Use e.g.:\n" " %s \\\n" " $(find \"" DFLT_XKB_CONFIG_ROOT "/symbols\" -type f -not -name README | xargs)\n" "to process all symbols files." "\n", progname, DEFAULT_INPUT_KEYMAP_FORMAT, progname); } #define DEFAULT_INCLUDE_PATH_PLACEHOLDER "__defaults__" static const char *includes[64] = { 0 }; static size_t num_includes = 0; static bool parse_options(int argc, char **argv, bool *verbose, enum input_source *input_source, enum xkb_keymap_format *keymap_input_format, enum xkb_file_iterator_flags *iterator_flags, int *paths_start, char **section, enum xkb_file_type *section_type, bool *recursive, enum output_format *output_format, enum output_options *output_options) { enum input_source input_format = INPUT_SOURCE_AUTO; enum options { /* General */ OPT_VERBOSE, /* Input */ OPT_INCLUDE, OPT_INCLUDE_DEFAULTS, OPT_INCLUDE_FAILURES, OPT_KEYMAP_FORMAT, OPT_SECTION_NAME, OPT_SECTION_TYPE, OPT_RECURSIVE, OPT_OUTPUT_RESOLVED_PATH, OPT_OUTPUT_YAML, OPT_OUTPUT_DOT, OPT_OUTPUT_RDF, OPT_LONG_LABELS, }; static struct option opts[] = { /* * General */ {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, OPT_VERBOSE}, /* * Input */ {"include", required_argument, 0, OPT_INCLUDE}, {"include-defaults", no_argument, 0, OPT_INCLUDE_DEFAULTS}, {"include-failures", no_argument, 0, OPT_INCLUDE_FAILURES}, {"format", required_argument, 0, OPT_KEYMAP_FORMAT}, {"section", required_argument, 0, OPT_SECTION_NAME}, {"type", required_argument, 0, OPT_SECTION_TYPE}, {"recursive", no_argument, 0, OPT_RECURSIVE}, {"resolve", no_argument, 0, OPT_OUTPUT_RESOLVED_PATH}, {"yaml", no_argument, 0, OPT_OUTPUT_YAML}, {"dot", no_argument, 0, OPT_OUTPUT_DOT}, {"rdf", no_argument, 0, OPT_OUTPUT_RDF}, {"long-labels", no_argument, 0, OPT_LONG_LABELS}, {0, 0, 0, 0}, }; int option_index = 0; while (1) { option_index = 0; int c = getopt_long(argc, argv, "h", opts, &option_index); if (c == -1) break; switch (c) { /* General */ case 'h': usage(stdout, argv[0]); exit(0); case OPT_VERBOSE: *verbose = true; break; /* Input */ case OPT_INCLUDE: if (num_includes >= ARRAY_SIZE(includes)) goto too_many_includes; includes[num_includes++] = optarg; break; case OPT_INCLUDE_DEFAULTS: if (num_includes >= ARRAY_SIZE(includes)) goto too_many_includes; includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER; break; case OPT_INCLUDE_FAILURES: *iterator_flags &= ~XKB_FILE_ITERATOR_FAIL_ON_INCLUDE_ERROR; break; case OPT_KEYMAP_FORMAT: *keymap_input_format = xkb_keymap_parse_format(optarg); if (!(*keymap_input_format)) { fprintf(stderr, "ERROR: invalid --format: \"%s\"\n", optarg); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } break; case OPT_SECTION_NAME: *section = optarg; break; case OPT_SECTION_TYPE: *section_type = xkb_parse_file_type(optarg); if (*section_type == FILE_TYPE_INVALID) { fprintf(stderr, "ERROR: invalid --type: \"%s\"\n", optarg); usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } break; case OPT_RECURSIVE: *recursive = true; break; case OPT_OUTPUT_RESOLVED_PATH: *output_format = OUTPUT_FORMAT_RESOLVED_PATH; *iterator_flags |= XKB_FILE_ITERATOR_NO_INCLUDES; break; case OPT_OUTPUT_YAML: *output_format = OUTPUT_FORMAT_YAML; break; case OPT_OUTPUT_DOT: *output_format = OUTPUT_FORMAT_DOT; break; case OPT_OUTPUT_RDF: *output_format = OUTPUT_FORMAT_RDF_TURTLE; break; case OPT_LONG_LABELS: *output_options &= ~OUTPUT_YAML_SHORT_LABELS; break; default: goto invalid_usage; } } if (*output_format != OUTPUT_FORMAT_YAML && !(*iterator_flags & XKB_FILE_ITERATOR_FAIL_ON_INCLUDE_ERROR)) { fprintf(stderr, "ERROR: --include-failures is only compatible with YAML output\n"); goto invalid_usage; } if (optind < argc && !isempty(argv[optind])) { /* Some positional arguments left: use as a file input */ if (input_format != INPUT_SOURCE_AUTO) { fprintf(stderr, "ERROR: Too many positional arguments\n"); goto invalid_usage; } input_format = INPUT_SOURCE_PATH; *paths_start = optind; } else if (is_pipe_or_regular_file(STDIN_FILENO) && input_format == INPUT_SOURCE_AUTO && *output_format != OUTPUT_FORMAT_RESOLVED_PATH) { /* No positional argument: detect piping */ input_format = INPUT_SOURCE_STDIN; } *input_source = input_format; return true; too_many_includes: fprintf(stderr, "ERROR: too many includes (max: %zu)\n", ARRAY_SIZE(includes)); invalid_usage: usage(stderr, argv[0]); exit(EXIT_INVALID_USAGE); } int main(int argc, char **argv) { struct xkb_context *ctx; bool verbose = false; int paths_start = argc; char *map = NULL; enum xkb_file_type section_type = FILE_TYPE_INVALID; enum xkb_keymap_format keymap_input_format = DEFAULT_INPUT_KEYMAP_FORMAT; enum xkb_file_iterator_flags iterator_flags = XKB_FILE_ITERATOR_FAIL_ON_INCLUDE_ERROR; bool recursive = false; enum output_format output_format = OUTPUT_FORMAT_YAML; enum output_options output_options = OUTPUT_YAML_SHORT_LABELS; int rc = 1; setlocale(LC_ALL, ""); if (argc < 1) { usage(stderr, argv[0]); return EXIT_INVALID_USAGE; } enum input_source input_source = INPUT_SOURCE_AUTO; if (!parse_options(argc, argv, &verbose, &input_source, &keymap_input_format, &iterator_flags, &paths_start, &map, §ion_type, &recursive, &output_format, &output_options)) return EXIT_INVALID_USAGE; enum xkb_context_flags ctx_flags = XKB_CONTEXT_NO_DEFAULT_INCLUDES; ctx = xkb_context_new(ctx_flags); assert(ctx); if (verbose) tools_enable_verbose_logging(ctx); if (num_includes == 0) includes[num_includes++] = DEFAULT_INCLUDE_PATH_PLACEHOLDER; for (size_t i = 0; i < num_includes; i++) { const char *include = includes[i]; if (strcmp(include, DEFAULT_INCLUDE_PATH_PLACEHOLDER) == 0) xkb_context_include_path_append_default(ctx); else xkb_context_include_path_append(ctx, include); } static char * no_paths[] = { NULL }; if (input_source == INPUT_SOURCE_STDIN) { /* Dummy list of paths */ argv = no_paths; argc = (int) ARRAY_SIZE(no_paths); paths_start = 0; } print_sections_header(output_format); for (int p = paths_start; p < argc; p++) { // fprintf(stderr, // "------\nProcessing: %s\n", // (is_stdin_path(argv[p]) ? "stdin" : argv[p])); rc = print_sections(ctx, iterator_flags, output_format, output_options, keymap_input_format, input_source, section_type, p - paths_start, argv[p], map, recursive); if (rc != EXIT_SUCCESS) break; } print_sections_footer(output_format); xkb_context_unref(ctx); return rc; } xkbcommon-libxkbcommon-54ee7ac/tools/messages.c000066400000000000000000000136561510033435100220110ustar00rootroot00000000000000/* * NOTE: This file has been generated automatically by “update-message-registry.py”. * Do not edit manually! * */ /* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "messages-codes.h" #include "messages.h" #include "utils.h" static const struct xkb_message_entry xkb_messages[] = { {XKB_ERROR_MALFORMED_NUMBER_LITERAL, "Malformed number literal"}, {XKB_WARNING_CONFLICTING_KEY_TYPE_PRESERVE_ENTRIES, "Conflicting key type preserve entries"}, {XKB_ERROR_INTEGER_OVERFLOW, "Integer overflow"}, {XKB_ERROR_UNSUPPORTED_MODIFIER_MASK, "Unsupported modifier mask"}, {XKB_ERROR_EXPECTED_ARRAY_ENTRY, "Expected array entry"}, {XKB_ERROR_INVALID_NUMERIC_KEYSYM, "Invalid numeric keysym"}, {XKB_WARNING_ILLEGAL_KEYCODE_ALIAS, "Illegal keycode alias"}, {XKB_WARNING_UNRECOGNIZED_KEYSYM, "Unrecognized keysym"}, {XKB_ERROR_UNDECLARED_VIRTUAL_MODIFIER, "Undeclared virtual modifier"}, {XKB_ERROR_INSUFFICIENT_BUFFER_SIZE, "Insufficient buffer size"}, {XKB_ERROR_WRONG_STATEMENT_TYPE, "Wrong statement type"}, {XKB_ERROR_INVALID_PATH, "Invalid path"}, {XKB_WARNING_UNSUPPORTED_GEOMETRY_SECTION, "Unsupported geometry section"}, {XKB_WARNING_CANNOT_INFER_KEY_TYPE, "Cannot infer key type"}, {XKB_WARNING_INVALID_ESCAPE_SEQUENCE, "Invalid escape sequence"}, {XKB_WARNING_ILLEGAL_KEY_TYPE_PRESERVE_RESULT, "Illegal key type preserve result"}, {XKB_ERROR_INVALID_INCLUDE_STATEMENT, "Invalid include statement"}, {XKB_ERROR_INVALID_MODMAP_ENTRY, "Invalid modmap entry"}, {XKB_ERROR_UNSUPPORTED_GROUP_INDEX, "Unsupported group index"}, {XKB_WARNING_CONFLICTING_KEY_TYPE_LEVEL_NAMES, "Conflicting key type level names"}, {XKB_ERROR_INVALID_SET_DEFAULT_STATEMENT, "Invalid set default statement"}, {XKB_WARNING_CONFLICTING_KEY_TYPE_MAP_ENTRY, "Conflicting key type map entry"}, {XKB_WARNING_UNDEFINED_KEY_TYPE, "Undefined key type"}, {XKB_WARNING_DEPRECATED_KEYSYM, "Deprecated keysym"}, {XKB_WARNING_DEPRECATED_KEYSYM_NAME, "Deprecated keysym name"}, {XKB_WARNING_NON_BASE_GROUP_NAME, "Non base group name"}, {XKB_ERROR_UNSUPPORTED_SHIFT_LEVEL, "Unsupported shift level"}, {XKB_ERROR_INCLUDED_FILE_NOT_FOUND, "Included file not found"}, {XKB_ERROR_UNKNOWN_OPERATOR, "Unknown operator"}, {XKB_WARNING_UNSUPPORTED_LEGACY_ACTION, "Unsupported legacy action"}, {XKB_WARNING_DUPLICATE_ENTRY, "Duplicate entry"}, {XKB_ERROR_RECURSIVE_INCLUDE, "Recursive include"}, {XKB_WARNING_CONFLICTING_KEY_TYPE_DEFINITIONS, "Conflicting key type definitions"}, {XKB_ERROR_GLOBAL_DEFAULTS_WRONG_SCOPE, "Global defaults wrong scope"}, {XKB_WARNING_MISSING_DEFAULT_SECTION, "Missing default section"}, {XKB_WARNING_CONFLICTING_KEY_SYMBOL, "Conflicting key symbol"}, {XKB_ERROR_INVALID_OPERATION, "Invalid operation"}, {XKB_WARNING_NUMERIC_KEYSYM, "Numeric keysym"}, {XKB_WARNING_EXTRA_SYMBOLS_IGNORED, "Extra symbols ignored"}, {XKB_WARNING_CONFLICTING_KEY_NAME, "Conflicting key name"}, {XKB_ERROR_INVALID_FILE_ENCODING, "Invalid file encoding"}, {XKB_ERROR_ALLOCATION_ERROR, "Allocation error"}, {XKB_ERROR_INVALID_ACTION_FIELD, "Invalid action field"}, {XKB_ERROR_WRONG_FIELD_TYPE, "Wrong field type"}, {XKB_ERROR_CANNOT_RESOLVE_RMLVO, "Cannot resolve rmlvo"}, {XKB_WARNING_INVALID_UNICODE_ESCAPE_SEQUENCE, "Invalid unicode escape sequence"}, {XKB_ERROR_INVALID_REAL_MODIFIER, "Invalid real modifier"}, {XKB_ERROR_UNKNOWN_DEFAULT_FIELD, "Unknown default field"}, {XKB_WARNING_UNKNOWN_CHAR_ESCAPE_SEQUENCE, "Unknown char escape sequence"}, {XKB_ERROR_INVALID_INCLUDED_FILE, "Invalid included file"}, {XKB_ERROR_INVALID_COMPOSE_LOCALE, "Invalid compose locale"}, {XKB_ERROR_INVALID_COMPOSE_SYNTAX, "Invalid compose syntax"}, {XKB_ERROR_INCOMPATIBLE_ACTIONS_AND_KEYSYMS_COUNT, "Incompatible actions and keysyms count"}, {XKB_WARNING_MULTIPLE_GROUPS_AT_ONCE, "Multiple groups at once"}, {XKB_WARNING_UNSUPPORTED_SYMBOLS_FIELD, "Unsupported symbols field"}, {XKB_ERROR_INCOMPATIBLE_KEYMAP_TEXT_FORMAT, "Incompatible keymap text format"}, {XKB_ERROR_RULES_INVALID_LAYOUT_INDEX_PERCENT_EXPANSION, "Rules invalid layout index percent expansion"}, {XKB_ERROR_INVALID_XKB_SYNTAX, "Invalid xkb syntax"}, {XKB_WARNING_UNDEFINED_KEYCODE, "Undefined keycode"}, {XKB_ERROR_INVALID_EXPRESSION_TYPE, "Invalid expression type"}, {XKB_ERROR_INVALID_VALUE, "Invalid value"}, {XKB_WARNING_CONFLICTING_MODMAP, "Conflicting modmap"}, {XKB_ERROR_UNKNOWN_FIELD, "Unknown field"}, {XKB_ERROR_KEYMAP_COMPILATION_FAILED, "Keymap compilation failed"}, {XKB_ERROR_UNKNOWN_ACTION_TYPE, "Unknown action type"}, {XKB_WARNING_CONFLICTING_KEY_ACTION, "Conflicting key action"}, {XKB_WARNING_CONFLICTING_KEY_TYPE_MERGING_GROUPS, "Conflicting key type merging groups"}, {XKB_ERROR_CONFLICTING_KEY_SYMBOLS_ENTRY, "Conflicting key symbols entry"}, {XKB_WARNING_MISSING_SYMBOLS_GROUP_NAME_INDEX, "Missing symbols group name index"}, {XKB_WARNING_CONFLICTING_KEY_FIELDS, "Conflicting key fields"}, {XKB_ERROR_INVALID_IDENTIFIER, "Invalid identifier"}, {XKB_WARNING_UNRESOLVED_KEYMAP_SYMBOL, "Unresolved keymap symbol"}, {XKB_ERROR_INVALID_RULES_SYNTAX, "Invalid rules syntax"}, {XKB_WARNING_UNDECLARED_MODIFIERS_IN_KEY_TYPE, "Undeclared modifiers in key type"} }; int xkb_message_get_all(const struct xkb_message_entry **messages) { *messages = xkb_messages; return ARRAY_SIZE(xkb_messages); } const struct xkb_message_entry* xkb_message_get(xkb_message_code_t code) { if (code < _XKB_LOG_MESSAGE_MIN_CODE || code > _XKB_LOG_MESSAGE_MAX_CODE) return NULL; for (size_t idx = 0; idx < ARRAY_SIZE(xkb_messages); idx++) { if (xkb_messages[idx].code == code) return &xkb_messages[idx]; } /* no matching message code found */ return NULL; } xkbcommon-libxkbcommon-54ee7ac/tools/messages.c.jinja000066400000000000000000000021741510033435100230740ustar00rootroot00000000000000/* * NOTE: This file has been generated automatically by “{{script}}”. * Do not edit manually! * */ /* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include "messages-codes.h" #include "messages.h" #include "utils.h" static const struct xkb_message_entry xkb_messages[] = { {% for entry in entries %} { {#--#}{{ entry.message_code_constant}}, "{{entry.message_name}}"}{{ "" if loop.last else "," }} {% endfor %} }; int xkb_message_get_all(const struct xkb_message_entry **messages) { *messages = xkb_messages; return ARRAY_SIZE(xkb_messages); } const struct xkb_message_entry* xkb_message_get(xkb_message_code_t code) { {# Binary search seems overkill for now #} if (code < _XKB_LOG_MESSAGE_MIN_CODE || code > _XKB_LOG_MESSAGE_MAX_CODE) return NULL; for (size_t idx = 0; idx < ARRAY_SIZE(xkb_messages); idx++) { if (xkb_messages[idx].code == code) return &xkb_messages[idx]; } /* no matching message code found */ return NULL; } xkbcommon-libxkbcommon-54ee7ac/tools/messages.h000066400000000000000000000006111510033435100220010ustar00rootroot00000000000000/* * Copyright © 2023 Pierre Le Marre * SPDX-License-Identifier: MIT */ #pragma once #include "config.h" #include "messages-codes.h" struct xkb_message_entry { const xkb_message_code_t code; const char *label; }; int xkb_message_get_all(const struct xkb_message_entry **xkb_messages); const struct xkb_message_entry* xkb_message_get(xkb_message_code_t code); xkbcommon-libxkbcommon-54ee7ac/tools/registry-list.c000066400000000000000000000152651510033435100230210ustar00rootroot00000000000000/* * Copyright © 2020 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include #include "xkbcommon/xkbregistry.h" static void usage(const char *progname, FILE *fp) { fprintf(fp, "Usage: %s [OPTIONS] [/path/to/xkb_base_directory [/path2]...]\n" "\n" "Options:\n" " --verbose, -v .......... Increase verbosity, use multiple times for debugging output\n" " --ruleset=foo .......... Load the 'foo' ruleset\n" " --skip-default-paths ... Do not load the default XKB paths\n" " --load-exotic .......... Load the exotic (extra) rulesets\n" " --help ................. Print this help and exit\n" "\n" "Trailing arguments are treated as XKB base directory installations.\n", progname); } int main(int argc, char **argv) { int rc = 1; struct rxkb_context *ctx = NULL; struct rxkb_model *m; struct rxkb_layout *l; struct rxkb_option_group *g; enum rxkb_context_flags flags = RXKB_CONTEXT_NO_FLAGS; bool load_defaults = true; int verbosity = 0; const char *ruleset = DEFAULT_XKB_RULES; static const struct option opts[] = { {"help", no_argument, 0, 'h'}, {"verbose", no_argument, 0, 'v'}, {"load-exotic", no_argument, 0, 'e'}, {"skip-default-paths", no_argument, 0, 'd'}, {"ruleset", required_argument, 0, 'r'}, {0, 0, 0, 0}, }; setlocale(LC_ALL, ""); while (1) { int c; int option_index = 0; c = getopt_long(argc, argv, "hev", opts, &option_index); if (c == -1) break; switch (c) { case 'h': usage(argv[0], stdout); return 0; case 'd': load_defaults = false; break; case 'e': flags |= RXKB_CONTEXT_LOAD_EXOTIC_RULES; break; case 'r': ruleset = optarg; break; case 'v': verbosity++; break; default: usage(argv[0], stderr); return EXIT_INVALID_USAGE; } } if (optind < argc) flags |= RXKB_CONTEXT_NO_DEFAULT_INCLUDES; ctx = rxkb_context_new(flags); if (!ctx) { fprintf(stderr, "Failed to create a registry context\n"); rc = EXIT_FAILURE; goto err; } switch (verbosity) { case 0: rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_ERROR); break; case 1: rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_INFO); break; default: rxkb_context_set_log_level(ctx, RXKB_LOG_LEVEL_DEBUG); break; } if (optind < argc) { for (int i = optind; i < argc; i++) { if (!rxkb_context_include_path_append(ctx, argv[i])) { fprintf(stderr, "Failed to append include path '%s'\n", argv[i]); goto err; } } if (load_defaults) { if (!rxkb_context_include_path_append_default(ctx)) { fprintf(stderr, "Failed to include default paths.\n"); goto err; } } } if (!rxkb_context_parse(ctx, ruleset)) { fprintf(stderr, "Failed to parse XKB descriptions.\n"); goto err; } printf("models:\n"); m = rxkb_model_first(ctx); assert(m); /* Empty model list is usually a bug or a bad xml file */ while (m) { const char *vendor = rxkb_model_get_vendor(m); printf("- name: %s\n" " vendor: %s\n" " description: %s\n", rxkb_model_get_name(m), vendor ? vendor : "''", rxkb_model_get_description(m)); m = rxkb_model_next(m); } printf("\n"); printf("layouts:\n"); l = rxkb_layout_first(ctx); assert(l); /* Empty layout list is usually a bug or a bad xml file */ while (l) { struct rxkb_iso639_code *iso639; struct rxkb_iso3166_code *iso3166; const char *variant = rxkb_layout_get_variant(l); const char *brief = rxkb_layout_get_brief(l); printf("- layout: '%s'\n" " variant: '%s'\n" " brief: '%s'\n" " description: %s\n", rxkb_layout_get_name(l), variant ? variant : "", brief ? brief : "''", rxkb_layout_get_description(l)); printf(" iso639: ["); iso639 = rxkb_layout_get_iso639_first(l); if (iso639) { const char *sep = ""; while (iso639) { printf("%s'%s'", sep, rxkb_iso639_code_get_code(iso639)); iso639 = rxkb_iso639_code_next(iso639); sep = ", "; } } printf("]\n"); printf(" iso3166: ["); iso3166 = rxkb_layout_get_iso3166_first(l); if (iso3166) { const char *sep = ""; while (iso3166) { printf("%s'%s'", sep, rxkb_iso3166_code_get_code(iso3166)); iso3166 = rxkb_iso3166_code_next(iso3166); sep = ", "; } } printf("]\n"); l = rxkb_layout_next(l); } printf("\n"); printf("option_groups:\n"); g = rxkb_option_group_first(ctx); assert(g); /* Empty option goups list is usually a bug or a bad xml file */ while (g) { struct rxkb_option *o; printf("- name: '%s'\n" " description: %s\n" " allows_multiple: %s\n" " options:\n", rxkb_option_group_get_name(g), rxkb_option_group_get_description(g), rxkb_option_group_allows_multiple(g) ? "true" : "false"); o = rxkb_option_first(g); assert(o); /* Empty option list is usually a bug or a bad xml file */ while (o) { const char *brief = rxkb_option_get_brief(o); printf(" - name: '%s'\n" " brief: '%s'\n" " description: '%s'\n" " layout-specific: %s\n", rxkb_option_get_name(o), brief ? brief : "", rxkb_option_get_description(o), rxkb_option_is_layout_specific(o) ? "true" : "false"); o = rxkb_option_next(o); } g = rxkb_option_group_next(g); } rc = EXIT_SUCCESS; err: rxkb_context_unref(ctx); return rc; } xkbcommon-libxkbcommon-54ee7ac/tools/tools-common.c000066400000000000000000000610321510033435100226170ustar00rootroot00000000000000/* * Copyright © 2009 Dan Nicholson * Copyright © 2012 Intel Corporation * Copyright © 2012 Ran Benita * SPDX-License-Identifier: MIT-open-group * * Author: Dan Nicholson * Daniel Stone * Ran Benita */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #include #include #else #include #include #endif #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-compose.h" #include "tools-common.h" #include "src/compose/constants.h" #include "src/utils.h" #include "src/utf8-decoding.h" #include "src/keysym.h" #include "src/keymap.h" #include "src/messages-codes.h" #if defined(_WIN32) && !defined(S_ISFIFO) #define S_ISFIFO(mode) 0 #endif static void print_keycode(struct xkb_keymap *keymap, const char* prefix, xkb_keycode_t keycode, const char *suffix) { const char *keyname = xkb_keymap_key_get_name(keymap, keycode); if (keyname) { printf("%s%-4s%s", prefix, keyname, suffix); } else { printf("%s%-4d%s", prefix, keycode, suffix); } } /* Variant of ModMaskText of main lib */ static void print_mod_mask(struct xkb_keymap *keymap, enum mod_type type, xkb_mod_mask_t mask) { /* We want to avoid boolean blindness, but we expected only 2 values */ assert(type == MOD_REAL || type == MOD_BOTH); if (!mask) { printf("0"); return; } const xkb_mod_index_t num_mods = xkb_keymap_num_mods(keymap); const xkb_mod_mask_t keymap_named_mods = (type == MOD_REAL) ? MOD_REAL_MASK_ALL : (xkb_mod_mask_t) ((UINT64_C(1) << num_mods) - 1); /* Print known mods */ bool first = true; xkb_mod_mask_t named = mask & keymap_named_mods; for (xkb_mod_index_t mod = 0; named && mod < num_mods; mod++, named >>= 1) { if (named & UINT32_C(0x1)) { if (first) { first = false; printf("%s", xkb_keymap_mod_get_name(keymap, mod)); } else { printf(" + %s", xkb_keymap_mod_get_name(keymap, mod)); } } } if (mask & ~keymap_named_mods) { /* If some bits of the mask cannot be expressed with the known modifiers * of the given type, print it as hexadecimal */ printf("%s%#"PRIx32, (first ? "" : " + "), mask & ~keymap_named_mods); } } /* Modifiers encodings, formatted as YAML */ void print_modifiers_encodings(struct xkb_keymap *keymap) { printf("Modifiers encodings:"); /* Find the padding required for modifier names */ int padding = 0; for (xkb_mod_index_t mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { const char* name = xkb_keymap_mod_get_name(keymap, mod); padding = MAX(padding, (int) strlen(name)); } /* Print encodings */ static const char indent[] = "\n "; for (xkb_mod_index_t mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { if (mod == 0) printf("%s# Real modifiers (predefined)", indent); else if (mod == _XKB_MOD_INDEX_NUM_ENTRIES) printf("\n%s# Virtual modifiers (keymap-dependent)", indent); const xkb_mod_mask_t encoding = xkb_keymap_mod_get_mask2(keymap, mod); const char* name = xkb_keymap_mod_get_name(keymap, mod); const int count = printf("%s%s", indent, name); printf(":%*s 0x%08"PRIx32, MAX(0, padding - count + (int)sizeof(indent) - 1), "", encoding); if (mod >= _XKB_MOD_INDEX_NUM_ENTRIES) { printf(" # "); if (encoding) { if (!(encoding & MOD_REAL_MASK_ALL)) { /* Prevent printing the numeric form again */ if (encoding == (UINT32_C(1) << mod)) printf("Canonical virtual modifier"); else printf("Non-canonical virtual modifier"); } else { print_mod_mask(keymap, MOD_REAL, encoding); } if (encoding & ~MOD_REAL_MASK_ALL) printf(" (incompatible with X11)"); } else { printf("(unmapped)"); } } } printf("\n"); } /* Key modifier maps, formatted as YAML */ void print_keys_modmaps(struct xkb_keymap *keymap) { printf("Keys modifier maps:"); uint32_t count = 0; const struct xkb_key *key; xkb_keys_foreach(key, keymap) { if (!key->modmap && !key->vmodmap) continue; print_keycode(keymap, "\n ", key->keycode, ":"); printf("\n real: "); print_mod_mask(keymap, MOD_REAL, key->modmap); printf("\n virtual: "); print_mod_mask(keymap, MOD_BOTH, key->vmodmap); count++; } if (count == 0) printf(" {} # No modifier map"); printf("\n"); } static void print_modifiers_names(struct xkb_state *state, enum xkb_state_component components, xkb_keycode_t keycode, enum xkb_consumed_mode consumed_mode) { struct xkb_keymap * const keymap = xkb_state_get_keymap(state); for (xkb_mod_index_t mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { if (xkb_state_mod_index_is_active(state, mod, components) <= 0) continue; const bool consumed = keycode != XKB_KEYCODE_INVALID && xkb_state_mod_index_is_consumed2(state, keycode, mod, consumed_mode); printf(" %s%s", (consumed ? "-" : ""), xkb_keymap_mod_get_name(keymap, mod)); } } #define INDENT " " static void print_modifiers(struct xkb_state *state, enum xkb_state_component changed, xkb_keycode_t keycode, bool show_consumed, enum xkb_consumed_mode consumed_mode, bool verbose) { static const struct { enum xkb_state_component component; unsigned int padding; const char *label; } types[] = { { XKB_STATE_MODS_DEPRESSED, 0, "depressed" }, { XKB_STATE_MODS_LATCHED, 2, "latched" }, { XKB_STATE_MODS_LOCKED, 3, "locked" }, { XKB_STATE_MODS_EFFECTIVE, 0, "effective" }, }; if (verbose) { static const char label[] = INDENT "modifiers: "; printf("%s", label); for (unsigned int k = 0; k < ARRAY_SIZE(types); k++) { const xkb_mod_mask_t mods = xkb_state_serialize_mods(state, types[k].component); const char * const changed_indicator = (changed) ? (changed & types[k].component ? "*" : " ") : ""; printf("%*s%s%s: %*s0x%08"PRIx32, (k == 0) ? 0 : (unsigned int) sizeof(label) - 1, "", changed_indicator, types[k].label, types[k].padding, "", mods); print_modifiers_names( state, types[k].component, (show_consumed ? keycode : XKB_KEYCODE_INVALID), consumed_mode ); printf("\n"); } } else { if (changed) { for (unsigned int k = 0; k < ARRAY_SIZE(types); k++) { if (!(changed & types[k].component)) continue; const xkb_mod_mask_t mods = xkb_state_serialize_mods(state, types[k].component); printf("%s-mods: 0x%08"PRIx32"; ", types[k].label, mods); } } else { const xkb_mod_mask_t mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE); printf("modifiers: 0x%08"PRIx32, mods); print_modifiers_names(state, XKB_STATE_MODS_EFFECTIVE, keycode, consumed_mode); printf("\n"); } } } static void print_layouts(struct xkb_state *state, enum xkb_state_component changed, xkb_keycode_t keycode, bool verbose) { struct xkb_keymap * const keymap = xkb_state_get_keymap(state); static const char label[] = INDENT "layout: "; static const struct { enum xkb_state_component component; unsigned int padding; const char *label; } types[] = { { XKB_STATE_LAYOUT_DEPRESSED, 0, "depressed" }, { XKB_STATE_LAYOUT_LATCHED, 2, "latched" }, { XKB_STATE_LAYOUT_LOCKED, 3, "locked" }, { XKB_STATE_LAYOUT_EFFECTIVE, 0, "effective" }, }; if (verbose) { printf("%s", label); for (unsigned int k = 0; k < ARRAY_SIZE(types); k++) { const xkb_layout_index_t layout = xkb_state_serialize_layout(state, types[k].component); const char * const changed_indicator = (changed) ? (changed & types[k].component ? "*" : " ") : ""; printf("%*s%s%s: %*s%"PRId32, (k == 0) ? 0 : (unsigned int) sizeof(label) - 1, "", changed_indicator, types[k].label, types[k].padding, "", layout); if (types[k].component == XKB_STATE_LAYOUT_LOCKED || types[k].component == XKB_STATE_LAYOUT_EFFECTIVE) printf(" \"%s\"\n", xkb_keymap_layout_get_name(keymap, layout)); else printf("\n"); } } else if (changed) { for (unsigned int k = 0; k < ARRAY_SIZE(types); k++) { if (!(changed & types[k].component)) continue; const xkb_layout_index_t layout = xkb_state_serialize_layout(state, types[k].component); printf("%s-layout: %"PRId32"; ", types[k].label, layout); } } if (keycode != XKB_KEYCODE_INVALID) { const xkb_layout_index_t layout = xkb_state_key_get_layout(state, keycode); if (verbose) { printf("%*s%skey: %"PRIu32" \"%s\"\n", (unsigned int) sizeof(label) - 1, "", (changed ? " " : ""), layout, xkb_keymap_layout_get_name(keymap, layout)); } else { printf(INDENT "layout: %"PRIu32" \"%s\"\n", layout, xkb_keymap_layout_get_name(keymap, layout)); } } } static void print_leds(struct xkb_state *state, bool verbose) { struct xkb_keymap * const keymap = xkb_state_get_keymap(state); unsigned int count = 0; for (xkb_led_index_t led = 0; led < xkb_keymap_num_leds(keymap); led++) { if (xkb_state_led_index_is_active(state, led) <= 0) continue; if (count > 0) printf(", "); if (verbose) { printf("%"PRIu32" \"%s\"", led, xkb_keymap_led_get_name(keymap, led)); } else { printf("%s", xkb_keymap_led_get_name(keymap, led)); } count++; } } static void tools_print_detailed_keycode_state(const char *prefix, struct xkb_state *state, struct xkb_compose_state *compose_state, xkb_keycode_t keycode, enum xkb_key_direction direction, enum xkb_consumed_mode consumed_mode, enum print_state_options options) { printf("------------\n"); if (prefix) printf("%s", prefix); struct xkb_keymap * const keymap = xkb_state_get_keymap(state); const char * const keyname = xkb_keymap_key_get_name(keymap, keycode); printf("key %s 0x%03"PRIx32" <%s>\n", (direction == XKB_KEY_UP ? "up: " : "down:"), keycode, (keyname ? keyname : "(no name)")); if (direction == XKB_KEY_UP) return; const xkb_layout_index_t layout = xkb_state_key_get_layout(state, keycode); const bool verbose = options & PRINT_VERBOSE; if (options & PRINT_LAYOUT) print_layouts(state, 0, keycode, verbose); if (verbose) { print_modifiers(state, 0, keycode, true, consumed_mode, verbose); printf(INDENT "level: %"PRIu32"\n", xkb_state_key_get_level(state, keycode, layout)); } else { printf(INDENT "level: %"PRIu32", ", xkb_state_key_get_level(state, keycode, layout)); print_modifiers(state, 0, keycode, true, consumed_mode, verbose); } enum xkb_compose_status status = XKB_COMPOSE_NOTHING; if (compose_state) status = xkb_compose_state_get_status(compose_state); #define BUFFER_SIZE MAX(XKB_COMPOSE_MAX_STRING_SIZE, XKB_KEYSYM_NAME_MAX_SIZE) static_assert(XKB_KEYSYM_UTF8_MAX_SIZE <= BUFFER_SIZE, "buffer too small"); char s[BUFFER_SIZE]; #undef BUFFER_SIZE bool show_unicode = false; const xkb_keysym_t *syms; const int nsyms = xkb_state_key_get_syms(state, keycode, &syms); if (nsyms > 0) { show_unicode = true; printf(INDENT "%skeysyms:", (status == XKB_COMPOSE_NOTHING ? "" : "raw ")); for (int i = 0; i < nsyms; i++) { xkb_keysym_get_name(syms[i], s, sizeof(s)); printf(" %s", s); } } switch (status) { case XKB_COMPOSE_NOTHING: break; case XKB_COMPOSE_COMPOSING: printf("\n" INDENT "compose: pending\n"); show_unicode = false; break; case XKB_COMPOSE_COMPOSED: { const xkb_keysym_t sym = xkb_compose_state_get_one_sym(compose_state); xkb_keysym_get_name(sym, s, sizeof(s)); printf("\n" INDENT "composed: %s", s); show_unicode = true; break; } case XKB_COMPOSE_CANCELLED: printf("\n" INDENT "compose: cancelled\n"); show_unicode = false; break; default: fprintf(stderr, "\nERROR: Unexpected compose state: %d\n", status); assert(!"Unexpected compose state"); } if ((options & PRINT_UNICODE) && show_unicode) { if (status == XKB_COMPOSE_COMPOSED) xkb_compose_state_get_utf8(compose_state, s, sizeof(s)); else xkb_state_key_get_utf8(state, keycode, s, sizeof(s)); if (!*s) { printf("\n"); } else { /* * HACK: escape single control characters from C0 set using the * Unicode codepoint convention. Ideally we would like to escape * any non-printable character in the string. */ if (strlen(s) == 1 && (*s <= 0x1F || *s == 0x7F)) printf(" ("); else printf(" \"%s\" (", s); /* Print Unicode code points */ size_t offset = 0; size_t count = 0; uint32_t cp = utf8_next_code_point(s, sizeof(s), &offset); while (cp && cp != INVALID_UTF8_CODE_POINT) { if (count++ > 0) printf(" "); printf("U+%04"PRIX32, cp); cp = utf8_next_code_point(s + offset, sizeof(s) - offset, &offset); } printf(", %zu code point%s)\n", count, (count > 1 ? "s" : "")); } } else if (show_unicode) { printf("\n"); } printf(INDENT "LEDs: "); print_leds(state, true); printf("\n"); } static void tools_print_one_liner_keycode_state(const char *prefix, struct xkb_state *state, struct xkb_compose_state *compose_state, xkb_keycode_t keycode, enum xkb_key_direction direction, enum xkb_consumed_mode consumed_mode, enum print_state_options options) { if (prefix) printf("%s", prefix); struct xkb_keymap * const keymap = xkb_state_get_keymap(state); printf("key %s", (direction == XKB_KEY_UP ? "up " : "down")); print_keycode(keymap, " [ ", keycode, " ] "); if (direction == XKB_KEY_UP) return; const xkb_keysym_t *syms; int nsyms = xkb_state_key_get_syms(state, keycode, &syms); if (nsyms <= 0) return; enum xkb_compose_status status = XKB_COMPOSE_NOTHING; if (compose_state) status = xkb_compose_state_get_status(compose_state); xkb_keysym_t sym; if (status == XKB_COMPOSE_COMPOSED) { sym = xkb_compose_state_get_one_sym(compose_state); syms = &sym; nsyms = 1; } else if (nsyms == 1) { sym = xkb_state_key_get_one_sym(state, keycode); syms = &sym; } #define BUFFER_SIZE MAX(XKB_COMPOSE_MAX_STRING_SIZE, XKB_KEYSYM_NAME_MAX_SIZE) static_assert(XKB_KEYSYM_UTF8_MAX_SIZE <= BUFFER_SIZE, "buffer too small"); char s[BUFFER_SIZE]; #undef BUFFER_SIZE printf("keysyms [ "); for (int i = 0; i < nsyms; i++) { xkb_keysym_get_name(syms[i], s, sizeof(s)); printf("%-*s ", XKB_KEYSYM_NAME_MAX_SIZE, s); } printf("] "); if (!(options & PRINT_UNICODE)) { /* Do nothing */ } else if (status == XKB_COMPOSE_COMPOSING) { printf("composing [ ] "); } else if (status == XKB_COMPOSE_CANCELLED) { printf("cancelled [ ] "); } else { assert(status == XKB_COMPOSE_NOTHING || status == XKB_COMPOSE_COMPOSED); if (status == XKB_COMPOSE_COMPOSED) { printf("composed "); xkb_compose_state_get_utf8(compose_state, s, sizeof(s)); } else { printf("unicode "); if (compose_state) printf(" "); xkb_state_key_get_utf8(state, keycode, s, sizeof(s)); } if (!*s) { printf("[ ] "); } else if (strlen(s) == 1 && (*s <= 0x1F || *s == 0x7F)) { /* * HACK: escape single control characters from C0 set using the * Unicode codepoint convention. Ideally we would like to escape * any non-printable character in the string. */ printf("[ U+%04hX ] ", *s); } else { printf("[ %s ] ", s); } } const xkb_layout_index_t layout = xkb_state_key_get_layout(state, keycode); if (options & PRINT_LAYOUT) { printf("layout [ #%"PRIu32" %s ] ", layout, xkb_keymap_layout_get_name(keymap, layout)); } printf("level [ %"PRIu32" ] ", xkb_state_key_get_level(state, keycode, layout)); printf("mods ["); print_modifiers_names(state, XKB_STATE_MODS_EFFECTIVE, keycode, consumed_mode); printf(" ] "); printf("leds [ "); print_leds(state, false); printf(" ] "); } void tools_print_keycode_state(const char *prefix, struct xkb_state *state, struct xkb_compose_state *compose_state, xkb_keycode_t keycode, enum xkb_key_direction direction, enum xkb_consumed_mode consumed_mode, enum print_state_options options) { if (keycode == XKB_KEYCODE_INVALID) return; if (options & PRINT_UNILINE) { tools_print_one_liner_keycode_state( prefix, state, compose_state, keycode, direction, consumed_mode, options ); printf("\n"); } else { tools_print_detailed_keycode_state( prefix, state, compose_state, keycode, direction, consumed_mode, options ); } } void tools_print_state_changes(const char *prefix, struct xkb_state *state, enum xkb_state_component changed, enum print_state_options options) { if (changed == 0) return; if (prefix) printf("%s", prefix); if (options & PRINT_UNILINE) { printf("state [ "); print_layouts(state, changed, XKB_KEYCODE_INVALID, false); print_modifiers(state, changed, XKB_KEYCODE_INVALID, false, XKB_CONSUMED_MODE_XKB /* unused*/, false); if (changed & XKB_STATE_LEDS) printf("leds "); printf("]\n"); } else { printf("state changes:\n"); static const enum xkb_state_component mod_mask = XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_MODS_LOCKED | XKB_STATE_MODS_EFFECTIVE; if (changed & mod_mask) { print_modifiers(state, changed, XKB_KEYCODE_INVALID, false, XKB_CONSUMED_MODE_XKB /* unused*/, true); } static const enum xkb_state_component layout_mask = XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_LAYOUT_LATCHED | XKB_STATE_LAYOUT_LOCKED | XKB_STATE_LAYOUT_EFFECTIVE; if (changed & layout_mask) { print_layouts(state, changed, XKB_KEYCODE_INVALID, true); } if (changed & XKB_STATE_LEDS) { printf(INDENT "LEDs: "); print_leds(state, true); printf("\n"); } } } #undef INDENT #ifdef _WIN32 void tools_disable_stdin_echo(void) { HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; GetConsoleMode(stdin_handle, &mode); SetConsoleMode(stdin_handle, mode & ~ENABLE_ECHO_INPUT); } void tools_enable_stdin_echo(void) { HANDLE stdin_handle = GetStdHandle(STD_INPUT_HANDLE); DWORD mode = 0; GetConsoleMode(stdin_handle, &mode); SetConsoleMode(stdin_handle, mode | ENABLE_ECHO_INPUT); } #else void tools_disable_stdin_echo(void) { /* Same as `stty -echo`. */ struct termios termios; if (tcgetattr(STDIN_FILENO, &termios) == 0) { termios.c_lflag &= ~ECHO; (void) tcsetattr(STDIN_FILENO, TCSADRAIN, &termios); } } void tools_enable_stdin_echo(void) { /* Same as `stty echo`. */ struct termios termios; if (tcgetattr(STDIN_FILENO, &termios) == 0) { termios.c_lflag |= ECHO; (void) tcsetattr(STDIN_FILENO, TCSADRAIN, &termios); } } #endif void tools_enable_verbose_logging(struct xkb_context *ctx) { xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_DEBUG); xkb_context_set_log_verbosity(ctx, XKB_LOG_VERBOSITY_VERBOSE); } static inline bool is_wayland_session(void) { /* This simple check should be enough for our use case. */ return !isempty(getenv("WAYLAND_DISPLAY")); } static inline bool is_x11_session(void) { /* This simple check should be enough for our use case. */ return !isempty(getenv("DISPLAY")); } const char * select_backend(const char *wayland, const char *x11, const char *fallback) { if (wayland && is_wayland_session()) return wayland; else if (x11 && is_x11_session()) return x11; else return fallback; } int tools_exec_command(const char *prefix, int real_argc, const char **real_argv) { const char *argv[64] = {NULL}; char executable[PATH_MAX]; const char *command; int rc; if (((size_t)real_argc >= ARRAY_SIZE(argv))) { fprintf(stderr, "Too many arguments\n"); return EXIT_INVALID_USAGE; } command = real_argv[0]; rc = snprintf(executable, sizeof(executable), "%s/%s-%s", LIBXKBCOMMON_TOOL_PATH, prefix, command); if (rc < 0 || (size_t) rc >= sizeof(executable)) { fprintf(stderr, "Failed to assemble command\n"); return EXIT_FAILURE; } argv[0] = executable; for (int i = 1; i < MIN(real_argc, (int) ARRAY_SIZE(argv)); i++) argv[i] = real_argv[i]; execv(executable, (char **) argv); if (errno == ENOENT) { fprintf(stderr, "Command '%s' is not available\n", command); return EXIT_INVALID_USAGE; } else { fprintf(stderr, "Failed to execute '%s' (%s)\n", command, strerror(errno)); } return EXIT_FAILURE; } bool is_pipe_or_regular_file(int fd) { struct stat info; if (fstat(fd, &info) == 0) { return S_ISFIFO(info.st_mode) || S_ISREG(info.st_mode); } else { return false; } } FILE* tools_read_stdin(void) { FILE *file = tmpfile(); if (!file) { fprintf(stderr, "Failed to create tmpfile\n"); return NULL; } while (true) { char buf[4096] = {0}; const size_t len = fread(buf, 1, sizeof(buf), stdin); if (ferror(stdin)) { fprintf(stderr, "Failed to read from stdin\n"); goto err; } if (len > 0) { size_t wlen = fwrite(buf, 1, len, file); if (wlen != len) { fprintf(stderr, "Failed to write to tmpfile\n"); goto err; } } if (feof(stdin)) break; } fseek(file, 0, SEEK_SET); return file; err: fclose(file); return NULL; } xkbcommon-libxkbcommon-54ee7ac/tools/tools-common.h000066400000000000000000000045471510033435100226340ustar00rootroot00000000000000/* * Copyright © 2012 Intel Corporation * SPDX-License-Identifier: MIT * * Author: Daniel Stone */ #pragma once #include "config.h" #include #include /* Don't use compat names in internal code. */ #define _XKBCOMMON_COMPAT_H #include "xkbcommon/xkbcommon.h" #include "xkbcommon/xkbcommon-compose.h" #define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr)))) enum { DEFAULT_KEYMAP_SERIALIZE_FLAGS = XKB_KEYMAP_SERIALIZE_PRETTY | XKB_KEYMAP_SERIALIZE_KEEP_UNUSED }; /* Fields that are printed in the interactive tools. */ enum print_state_options { PRINT_LAYOUT = (1u << 0), PRINT_UNICODE = (1u << 1), PRINT_ALL_FIELDS = ((PRINT_UNICODE << 1) - 1), /* * Fields that can be hidden with the option --short. * NOTE: If this value is modified, remember to update the documentation of * the --short option in the corresponding tools. */ PRINT_VERBOSE_ONE_LINE_FIELDS = (PRINT_LAYOUT | PRINT_UNICODE), PRINT_VERBOSE = (1u << 2), PRINT_UNILINE = (1u << 3), DEFAULT_PRINT_OPTIONS = PRINT_ALL_FIELDS | PRINT_VERBOSE | PRINT_UNILINE }; void print_modifiers_encodings(struct xkb_keymap *keymap); void print_keys_modmaps(struct xkb_keymap *keymap); void tools_enable_verbose_logging(struct xkb_context *ctx); void tools_print_keycode_state(const char *prefix, struct xkb_state *state, struct xkb_compose_state *compose_state, xkb_keycode_t keycode, enum xkb_key_direction direction, enum xkb_consumed_mode consumed_mode, enum print_state_options options); void tools_print_state_changes(const char *prefix, struct xkb_state *state, enum xkb_state_component changed, enum print_state_options options); void tools_disable_stdin_echo(void); void tools_enable_stdin_echo(void); const char * select_backend(const char *wayland, const char *x11, const char *fallback); int tools_exec_command(const char *prefix, int argc, const char **argv); bool is_pipe_or_regular_file(int fd); FILE* tools_read_stdin(void); #ifdef _WIN32 #define setenv(varname, value, overwrite) _putenv_s((varname), (value)) #define unsetenv(varname) _putenv_s(varname, "") #endif xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-bash-completion.sh000066400000000000000000000075461510033435100247310ustar00rootroot00000000000000# bash completion support for xkbcli. # See completion API documentation: https://github.com/scop/bash-completion # NOTE: The script parses the commands help messages to provide the completions, # thus any new subcommand or option will be supported, as long as it has its # entry in the help messages. This should result in low maintenancei effort. ___xkbcli_main() { # Initialization: https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L205 local cur prev words cword cmd _init_completion -s || return # Find subcommand local i=1 while [[ "$i" -lt "$COMP_CWORD" ]]; do local s="${COMP_WORDS[i]}" case "$s" in -*) ;; *) cmd="$s" break ;; esac (( i++ )) done # Parse available subcommands local line local is_command_list=false local subcommands=() while IFS='' read -r line; do # Traverse subcommand list if [[ "$is_command_list" == true ]]; then # Check for subcommand based on the indentation if [[ "$line" =~ ^[[:blank:]]{2}([[:alpha:]]([[:alnum:]]|-)+)$ ]]; then subcommands+=("${BASH_REMATCH[1]}") # Detect end of subcommand list based on indentation elif [[ "$line" =~ ^[[:graph:]] ]]; then is_command_list=false fi # Detect start of subcommand list elif [[ "$line" == "Commands:" ]]; then is_command_list=true fi # NOTE: <( COMMAND ) Bash construct is “process substitution”. done < <(xkbcli --help) # No previous subcommand or incomplete: completion for root xkbcli command if [[ "$i" -eq "$COMP_CWORD" ]]; then local opts # Doc for _parse_help: https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L311 opts=$(_parse_help xkbcli) local cur="${COMP_WORDS[COMP_CWORD]}" COMPREPLY=($(compgen -W "${subcommands[*]} $opts" -- "$cur")) return fi # Found a supported subcommand: proceed to completion if [[ "${subcommands[*]}" =~ (^| )$cmd( |$) ]]; then ___xkbcli_subcommand "$cmd" fi } ___xkbcli_subcommand() { # Some special cases case $1 in compile-keymap | interactive-evdev) case ${COMP_WORDS[COMP_CWORD-1]} in --include | --keymap) _filedir return;; esac if [[ ${COMP_WORDS[COMP_CWORD]} != -* ]]; then _filedir return fi ;; compile-compose) case ${COMP_WORDS[COMP_CWORD-1]} in --file) _filedir return;; esac if [[ ${COMP_WORDS[COMP_CWORD]} != -* ]]; then _filedir return fi ;; list) if [[ ${COMP_WORDS[COMP_CWORD]} != -* ]]; then _filedir return fi ;; esac # Parse help to get command options local opts # Doc for _parse_usage and _parse_help: # • https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L335 # • https://github.com/scop/bash-completion/blob/fdf4456186eb4548ef628e65fb1be73d8e4695e9/bash_completion.d/000_bash_completion_compat.bash#L311 # We need both as the current help messages adopt both GNU and BSD styles. opts=$(_parse_usage xkbcli "$1 --help") opts+=" " opts+=$(_parse_help xkbcli "$1 --help") local cur="${COMP_WORDS[COMP_CWORD]}" COMPREPLY=($(compgen -W "$opts" -- "$cur")) } complete -F ___xkbcli_main xkbcli xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-compile-compose.1000066400000000000000000000016351510033435100244570ustar00rootroot00000000000000.Dd June 4, 2024 .Dt XKBCLI\-COMPILE\-COMPOSE 1 .Os . .Sh NAME .Nm "xkbcli\-compile\-compose" .Nd compile an X Keyboard Compose file . .Sh SYNOPSIS .Nm .Op Ar options .Op Ar COMPOSE_FILE . .Sh DESCRIPTION .Nm compile and print a Compose file based on the given options . .Bl -tag -width .It Ar COMPOSE_FILE Path to the compose file to load, or .Dq \- to read the standard input . .It Fl \-help Print help and exit . .It Fl \-verbose Enable verbose debugging output . .It Fl \-file Ar FILE Specify a Compose file to load, or .Dq \- to read the standard input. .Pp DEPRECATED: add the file path without the flag. . .It Fl \-locale Ar LOCALE Specify the locale directly, instead of relying on the environment variables LC_ALL, LC_TYPE and LANG. . .It Fl \-test Test compilation but do not print the Compose file .El . .Sh SEE ALSO .Xr xkbcli 1 , .Xr Compose 5 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-compile-keymap.1000066400000000000000000000051161510033435100242760ustar00rootroot00000000000000.Dd June 4, 2024 .Dt XKBCLI\-COMPILE\-KEYMAP 1 .Os . .Sh NAME .Nm "xkbcli\-compile\-keymap" .Nd compile an X Keyboard keymap . .Sh SYNOPSIS .Nm .Op Ar options .Op Ar KEYMAP_PATH . .Sh DESCRIPTION .Nm compiles and prints a keymap based on the given options. . .Bl -tag -width Ds .It Ar KEYMAP_PATH Path to a keymap file, or .Dq \- to read the standard input . .It Fl \-help Print help and exit . .It Fl \-verbose Enable verbose debugging output . .It Fl \-test Test compilation but do not print the keymap . .It Fl \-rmlvo Print the full RMLVO with the defaults filled in for missing elements in YAML format . .It Fl \-kccgst Print a keymap which only includes the KcCGST component names instead of the full keymap . .It Fl \-kccgst-yaml Print the KcCGST component names in YAML format. . .It Fl \-modmaps Print real and virtual key modmaps and modifiers encodings in YAML format. . .It Fl \-include Ar PATH Add the given path to the include path list. This option is order\-dependent, include paths given first are searched first. If an include path is given, the default include path list is not used. Use .Fl \-include\-defaults to add the default include paths. . .It Fl \-include\-defaults Add the default set of include directories. This option is order-dependent, include paths given first are searched first. . .It Fl \-input\-format Ar keymap_format The keymap format (numeric or label, e.g.\& .Dq v1 ) for parsing . .It Fl \-output\-format Ar keymap_format The keymap format (numeric or label, e.g.\& .Dq v1 ) for serializing . .It Fl \-format Ar keymap_format The keymap format (numeric or label, e.g.\& .Dq v1 ) for both parsing and serializing . .It Fl \-no\-pretty Disable pretty-printing for keymap serialization. . .It Fl \-drop\-unused Disable unused bits serialization. . .It Fl \-keymap Oo Ar PATH Oc , Fl \-from\-xkb Oo Ar PATH Oc Load the XKB keymap from a file, ignore RMLVO options. If .Ar PATH is empty or .Dq \- , read the stdin. . .It Fl \-rules Ar rules The XKB ruleset . .It Fl \-model Ar model The XKB model . .It Fl \-layout Ar layout The XKB layout . .It Fl \-variant Ar variant The XKB layout variant . .It Fl \-options Ar options The XKB options . .It Fl \-enable\-environment\-names Allow to set the default RMLVO values via the following environment variables: .Bl -dash -compact -hang .It .Ev XKB_DEFAULT_RULES .It .Ev XKB_DEFAULT_MODEL .It .Ev XKB_DEFAULT_LAYOUT .It .Ev XKB_DEFAULT_VARIANT .It .Ev XKB_DEFAULT_OPTIONS .El Note that this option may affect the default values of the previous options. . .El . .Sh SEE ALSO .Xr xkbcli 1 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-dump-keymap-wayland.1000066400000000000000000000023161510033435100252470ustar00rootroot00000000000000.Dd September 20, 2024 .Dt XKBCLI\-DUMP\-KEYMAP\-WAYLAND 1 .Os . .Sh NAME .Nm "xkbcli\-dump\-keymap\-wayland" .Nd Debugger for XKB keyboard keymaps on Wayland . .Sh SYNOPSIS .Nm .Op Ar options . .Sh DESCRIPTION .Nm is a commandline tool to dump XKB keymaps from Wayland compositor. . .Pp This requires a Wayland compositor to be running. . .Pp This is a debugging tool, its behavior or output is not guaranteed to be stable. . .Bl -tag -width Ds .It Fl \-help Print help and exit . .It Fl \-verbose Enable verbose debugging output . .It Fl \-input\-format Ar keymap_format The keymap format (numeric or label, e.g.\& .Dq v1 ) for parsing . .It Fl \-output\-format Ar keymap_format The keymap format (numeric or label, e.g.\& .Dq v1 ) for serializing . .It Fl \-format Ar keymap_format The keymap format (numeric or label, e.g.\& .Dq v1 ) for both parsing and serializing . .It Fl \-no\-pretty Disable pretty-printing for keymap serialization. . .It Fl \-drop\-unused Disable unused bits serialization. . .It Fl \-raw Print the raw keymap, without parsing it. .El . .Sh SEE ALSO .Xr xkbcli 1 , .Xr xkbcli\-interactive\-wayland 1 , .Xr xkbcli\-dump\-keymap\-x11 1 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-dump-keymap-x11.1000066400000000000000000000016031510033435100242170ustar00rootroot00000000000000.Dd September 20, 2024 .Dt XKBCLI\-DUMP\-KEYMAP\-X11 1 .Os . .Sh NAME .Nm "xkbcli\-dump\-keymap\-x11" .Nd Debugger for XKB keyboard keymaps on X11 . .Sh SYNOPSIS .Nm .Op Ar options . .Sh DESCRIPTION .Nm is a commandline tool to dump XKB keymaps from X servers. . .Pp This requires an X server to be running. . .Pp This is a debugging tool, its behavior or output is not guaranteed to be stable. . .Bl -tag -width Ds .It Fl \-format Ar keymap_format Specify the keymap format (numeric or label, e.g.\& .Dq v1 ) . .It Fl \-no\-pretty Disable pretty-printing for keymap serialization. . .It Fl \-drop\-unused Disable unused bits serialization. . .It Fl \-help Print help and exit . .It Fl \-verbose Enable verbose debugging output .El . .Sh SEE ALSO .Xr xkbcli 1 , .Xr xkbcli\-interactive\-x11 1 , .Xr xkbcli\-dump\-keymap\-wayland 1 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-how-to-type.1000066400000000000000000000053551510033435100235630ustar00rootroot00000000000000.Dd September 11, 2024 .Dt XKBCLI\-HOW\-TO\-TYPE 1 .Os . .Sh NAME .Nm "xkbcli\-how\-to\-type" .Nd query how to type a given Unicode code point or keysym . .Sh SYNOPSIS .Nm .Op options .Ar character/code point/keysym . .Sh DESCRIPTION .Nm prints the key combinations (keycode + modifiers) in the keymap’s layouts which would produce the given Unicode code point or keysym. . .Pp .Ar code point/keysym is either: . .Bl -bullet -compact .It a single character (requires a terminal which uses UTF-8 character encoding); .It a Unicode code point, interpreted as hexadecimal if prefixed with .Li 0x or .Li U+ else as decimal; . .It a keysym if either the previous interpretations failed or if .Fl \-keysym is used. The parameter is then either a keysym \fIname\fP or a \fInumeric\fP value (hexadecimal if prefixed with .Li 0x else decimal). Note that values .Li 0 – .Li 9 are special: they are both names and numeric values. The default interpretation is \fInames\fP; use the hexadecimal form .Li 0x0 – .Li 0x9 in order to interpret as numeric values. .El . .Sh EXAMPLES .Bl -tag -width Ds .It Nm Fl \-layout Ar us 97 .It Nm Fl \-layout Ar us 0x61 .It Nm Fl \-layout Ar us U+0061 .It Nm Fl \-layout Ar us a Print the key combinations that produce the letter “a” .Po decimal code point: .Ar 97 , hexadecimal code point: .Ar 61 .Pc in the default .Ar us layout. .It Nm Fl \-layout Ar us Fl \-keysym Ar 97 .It Nm Fl \-layout Ar us Fl \-keysym Ar 0x61 .It Nm Fl \-layout Ar us Fl \-keysym Ar a Print the key combinations that produce the keysym “a” .Po decimal code: .Ar 97 , hexadecimal code: .Ar 61 .Pc in the default .Ar us layout. .El . .Sh OPTIONS .Bl -tag -width Ds .It Fl \-keysym Treat the argument as only as a keysym . .It Fl \-disable\-compose Disable Compose support . .It Fl \-format Ar keymap_format Specify the keymap format (numeric or label, e.g.\& .Dq v1 ) . .It Fl \-keymap Oo = Ar PATH Oc Load the XKB keymap from a file, ignore RMLVO options. If .Ar PATH is empty or .Dq \- , read the stdin. . .It Fl \-rules Ar rules The XKB ruleset . .It Fl \-model Ar model The XKB model . .It Fl \-layout Ar layout The XKB layout . .It Fl \-variant Ar variant The XKB layout variant . .It Fl \-options Ar options The XKB options . .It Fl \-enable\-environment\-names Allow to set the default RMLVO values via the following environment variables: .Bl -dash -compact -hang .It .Ev XKB_DEFAULT_RULES .It .Ev XKB_DEFAULT_MODEL .It .Ev XKB_DEFAULT_LAYOUT .It .Ev XKB_DEFAULT_VARIANT .It .Ev XKB_DEFAULT_OPTIONS .El Note that this option may affect the default values of the previous options. . .It Fl \-verbose Enable verbose debugging output . .It Fl \-help Print a help message and exit. .El . .Sh SEE ALSO .Xr xkbcli 1 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-interactive-evdev.1000066400000000000000000000051761510033435100250140ustar00rootroot00000000000000.Dd June 4, 2024 .Dt XKBCLI\-INTERACTIVE\-EVDEV 1 .Os . .Sh NAME .Nm "xkbcli\-interactive\-evdev" .Nd interactive debugger for X Keyboard keymaps . .Sh SYNOPSIS .Nm .Op Ar options .Op Ar KEYMAP_PATH . .Sh DESCRIPTION .Nm is a commandline tool to interactively debug XKB keymaps by listening to .Pa /dev/input/eventX evdev devices. . .Pp .Nm requires permission to open the evdev device nodes. This usually requires being the .Dq root user or belonging to the .Dq input group. . .Pp Press the .Aq Escape key to exit. . .Pp This is a debugging tool, its behavior or output is not guaranteed to be stable. . .Bl -tag -width Ds .It Ar KEYMAP_PATH Path to a keymap file, or .Dq \- to read the standard input . .It Fl \-help Print help and exit . .It Fl \-verbose Enable verbose debugging output . .It Fl \-include Ar PATH Add the given path to the include path list. This option is order\-dependent, include paths given first are searched first. If an include path is given, the default include path list is not used. Use .Fl \-include\-defaults to add the default include paths. . .It Fl \-include\-defaults Add the default set of include directories. This option is order-dependent, include paths given first are searched first. . .It Fl \-format Ar keymap_format Specify the keymap format (numeric or label, e.g.\& .Dq v1 ) . .It Fl \-rules Ar rules The XKB ruleset . .It Fl \-model Ar model The XKB model . .It Fl \-layout Ar layout The XKB layout . .It Fl \-variant Ar variant The XKB layout variant . .It Fl \-option Ar options The XKB options . .It Fl \-enable\-environment\-names Allow to set the default RMLVO values via the following environment variables: .Bl -dash -compact -hang .It .Ev XKB_DEFAULT_RULES .It .Ev XKB_DEFAULT_MODEL .It .Ev XKB_DEFAULT_LAYOUT .It .Ev XKB_DEFAULT_VARIANT .It .Ev XKB_DEFAULT_OPTIONS .El Note that this option may affect the default values of the previous options. . .It Fl \-keymap Ar file Specify a keymap path. This option is mutually exclusive with the RMLVO options. . .It Fl \-enable\-compose Enable Compose functionality . .It Fl \-consumed\-mode Brq xkb|gtk Set the consumed modifiers mode (default: xkb) . .It Fl \-without\-x11\-offset Don't add an offset of 8 when converting an evdev keycode to an XKB keycode. You probably don't want this option. . .It Fl \-report\-state\-changes Report changes to the keyboard state .It Fl 1, \-uniline Enable uniline event output. . .It Fl \-multiline Enable multiline event output. . .It Fl \-short Print shorter event output. . .El . .Sh SEE ALSO .Xr xkbcli 1 , .Xr xkbcli\-interactive\-wayland 1 , .Xr xkbcli\-interactive\-x11 1 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-interactive-wayland.1000066400000000000000000000024441510033435100253350ustar00rootroot00000000000000.Dd June 4, 2024 .Dt XKBCLI\-INTERACTIVE\-WAYLAND 1 .Os . .Sh NAME .Nm "xkbcli\-interactive\-wayland" .Nd interactive debugger for Wayland keyboard keymaps . .Sh SYNOPSIS .Nm .Op Ar options . .Sh DESCRIPTION .Nm is a commandline tool to interactively debug XKB keymaps by listening to Wayland events. . .Pp This requires a Wayland compositor to be running. . .Pp Press the .Aq Escape key to exit. . .Pp This is a debugging tool, its behavior or output is not guaranteed to be stable. . .Bl -tag -width Ds .It Fl \-help Print help and exit . .It Fl \-format Ar keymap_format Specify the keymap format (numeric or label, e.g.\& .Dq v1 ) . .It Fl \-local\-state Enable local state handling and ignore modifiers/layouts state updates from the compositor . .It Fl \-keymap Oo Ar PATH Oc Load the XKB keymap from a file instead of the keymap from the compositor. It implies .Fl \-local\-state \&. If .Ar PATH is empty or .Dq \- , read the stdin. . .It Fl \-enable\-compose Enable Compose functionality . .It Fl \-verbose Enable verbose debugging output . .It Fl 1, \-uniline Enable uniline event output . .It Fl \-multiline Enable multiline event output .El . .Sh SEE ALSO .Xr xkbcli 1 , .Xr xkbcli\-interactive\-evdev 1 , .Xr xkbcli\-interactive\-x11 1 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-interactive-x11.1000066400000000000000000000024161510033435100243060ustar00rootroot00000000000000.Dd June 4, 2024 .Dt XKBCLI\-INTERACTIVE\-X11 1 .Os . .Sh NAME .Nm "xkbcli\-interactive\-x11" .Nd interactive debugger for X Keyboard keymaps . .Sh SYNOPSIS .Nm .Op Ar options . .Sh DESCRIPTION .Nm is a commandline tool to interactively debug XKB keymaps by listening to X11 events. . .Pp This requires an X server to be running. . .Pp Press the .Aq Escape key to exit. . .Pp This is a debugging tool, its behavior or output is not guaranteed to be stable. . .Bl -tag -width Ds .It Fl \-help Print help and exit . .It Fl \-local\-state Enable local state handling and ignore modifiers/layouts state updates from the X11 server. . .It Fl \-keymap Oo Ar PATH Oc Load the XKB keymap from a file instead of the keymap from the compositor. It implies .Fl \-local\-state \&. If .Ar PATH is empty or .Dq \- , read the stdin. . .It Fl \-format Ar keymap_format Specify the keymap format (numeric or label, e.g.\& .Dq v1 ) . .It Fl \-enable\-compose Enable Compose functionality . .It Fl \-verbose Enable verbose debugging output . .It Fl 1, \-uniline Enable uniline event output . .It Fl \-multiline Enable multiline event output .El . .Sh SEE ALSO .Xr xkbcli 1 , .Xr xkbcli\-interactive\-evdev 1 , .Xr xkbcli\-interactive\-wayland 1 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli-list.1000066400000000000000000000015221510033435100223320ustar00rootroot00000000000000.Dd June 04, 2024 .Dt XKBCLI\-LIST 1 .Os . .Sh NAME .Nm "xkbcli\-list" .Nd list available X Keyboard models, layouts, variants and options . .Sh SYNOPSIS .Nm .Op Pa /path/to/xkbbase Oo Pa /path/to/xkbbase Oc ... . .Sh DESCRIPTION List available model, layout, variant and option (MLVO) values from the XKB registry. The output is in YAML 1.2 format. . .Pp Positional arguments are treated as XKB base directory installations. . .Bl -tag -width Ds .It Fl \-help Print help and exit . .It Fl \-verbose Increase verbosity, use multiple times for debugging output . .It Fl \-ruleset Ar name Load the ruleset with the given name . .It Fl \-skip\-default\-paths Do not load the default XKB include paths . .It Fl \-load\-exotic Load exotic (extra) layouts .El . .Sh SEE ALSO .Xr xkbcli 1 , .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli.1000066400000000000000000000036101510033435100213610ustar00rootroot00000000000000.Dd June 4, 2024 .Dt XKBCLI 1 .Os . .Sh NAME .Nm xkbcli .Nd tool to interact with X Keyboard keymaps . .Sh SYNOPSIS .Nm .Ar command Bo arguments Bc . .Nm .Op Fl \-help | Fl \-version . .Sh DESCRIPTION .Nm is a commandline tool to query, compile and test XKB keymaps, layouts and other elements. . .Bl -tag -width Ds .It Fl \-help Print help and exit . .It Fl \-version Print the version and exit .El . .Ss COMMANDS .Bl -tag -width Ds .It Ic compile\-keymap Compile an XKB keymap, see .Xr xkbcli\-compile\-keymap 1 . .It Ic compile\-compose Compile a compose file, see .Xr xkbcli\-compile\-compose 1 . .It Ic how\-to\-type Show how to type a given Unicode codepoint, see .Xr xkbcli\-how\-to\-type 1 . .It Ic interactive Interactive debugger for XKB keymaps that automatically select from the following backends, if available: Wayland, X11 and evdev. See the corresponding entries hereinafter. . .It Ic interactive\-evdev Interactive debugger for XKB keymaps for evdev, see .Xr xkbcli\-interactive\-evdev 1 . .It Ic interactive\-wayland Interactive debugger for XKB keymaps for Wayland, see .Xr xkbcli\-interactive\-wayland 1 . .It Ic interactive\-x11 Interactive debugger for XKB keymaps for X11, see .Xr xkbcli\-interactive\-x11 1 . .It Ic dump\-keymap Dump a XKB keymap from a Wayland or X11 compositor, see the corresponding entries hereinafter. . .It Ic dump\-keymap\-wayland Dump a XKB keymap from a Wayland compositor, see .Xr xkbcli\-dump\-keymap\-wayland 1 . .It Ic dump\-keymap\-x11 Dump a XKB keymap from an X server, see .Xr xkbcli\-dump\-keymap\-x11 1 . .It Ic list List available layouts and more, see .Xr xkbcli\-list 1 .El . .Pp Note that not all tools may be available on your system. . .Sh EXIT STATUS .Bl -tag -compact -width Ds .It 0 exited successfully .It 1 an error occured .It 2 program was called with invalid arguments .El . .Sh SEE ALSO .Lk https://xkbcommon.org "The libxkbcommon online documentation" xkbcommon-libxkbcommon-54ee7ac/tools/xkbcli.c000066400000000000000000000070141510033435100214450ustar00rootroot00000000000000/* * Copyright © 2020 Red Hat, Inc. * SPDX-License-Identifier: MIT */ #include "config.h" #include #include #include #include #include "tools-common.h" static void usage(void) { printf("Usage: xkbcli [--help|-h] [--version|-V] []\n" "\n" "Global options:\n" " -h, --help ...... show this help and exit\n" " -V, --version ... show version information and exit\n" /* WARNING: The following is parsed by the bash completion script. * Any change to the format (in particular to the indentation) * should kept in the script in sync. */ "Commands:\n" #if HAVE_XKBCLI_LIST " list\n" " List available rules, models, layouts, variants and options\n" "\n" #endif #if HAVE_XKBCLI_INTERACTIVE_WAYLAND || HAVE_XKBCLI_INTERACTIVE_X11 " interactive\n" " Interactive debugger for XKB keymaps; automatically select from" " the following backends, if available: Wayland, X11 and evdev.\n" "\n" #endif #if HAVE_XKBCLI_INTERACTIVE_WAYLAND " interactive-wayland\n" " Interactive debugger for XKB keymaps for Wayland\n" "\n" #endif #if HAVE_XKBCLI_INTERACTIVE_X11 " interactive-x11\n" " Interactive debugger for XKB keymaps for X11\n" "\n" #endif #if HAVE_XKBCLI_INTERACTIVE_EVDEV " interactive-evdev\n" " Interactive debugger for XKB keymaps for evdev\n" "\n" #endif #if HAVE_XKBCLI_DUMP_KEYMAP_WAYLAND || HAVE_XKBCLI_DUMP_KEYMAP_X11 " dump-keymap\n" " Dump a XKB keymap from a Wayland or X11 compositor\n" "\n" #endif #if HAVE_XKBCLI_DUMP_KEYMAP_WAYLAND " dump-keymap-wayland\n" " Dump a XKB keymap from a Wayland compositor\n" "\n" #endif #if HAVE_XKBCLI_DUMP_KEYMAP_X11 " dump-keymap-x11\n" " Dump a XKB keymap from an X server\n" "\n" #endif #if HAVE_XKBCLI_COMPILE_KEYMAP " compile-keymap\n" " Compile an XKB keymap\n" "\n" #endif #if HAVE_XKBCLI_COMPILE_COMPOSE " compile-compose\n" " Compile a Compose file\n" "\n" #endif #if HAVE_XKBCLI_HOW_TO_TYPE " how-to-type\n" " Print key sequences to type a Unicode codepoint\n" "\n" #endif ); } int main(int argc, char **argv) { enum options { OPT_HELP = 1, OPT_VERSION, }; int option_index = 0; setlocale(LC_ALL, ""); while (1) { int c; static struct option opts[] = { { "help", no_argument, 0, OPT_HELP }, { "version", no_argument, 0, OPT_VERSION }, { 0, 0, 0, 0} }; c = getopt_long(argc, argv, "+hV", opts, &option_index); if (c == -1) break; switch(c) { case 'h': case OPT_HELP: usage(); return EXIT_SUCCESS; case 'V': case OPT_VERSION: printf("%s\n", LIBXKBCOMMON_VERSION); return EXIT_SUCCESS; default: usage(); return EXIT_INVALID_USAGE; } } if (optind >= argc) { usage(); return EXIT_INVALID_USAGE; } argv += optind; argc -= optind; return tools_exec_command("xkbcli", argc, (const char **) argv); } xkbcommon-libxkbcommon-54ee7ac/towncrier.toml000066400000000000000000000022601510033435100215740ustar00rootroot00000000000000[tool.towncrier] name = "libxkbcommon" directory = "changes" filename = "NEWS.md" start_string = "\n" all_bullets = true single_file = true orphan_prefix = "+" title_format = """\ {name} [{version}] – {project_date} ================================== [{version}]: https://github.com/xkbcommon/libxkbcommon/tree/xkbcommon-{version}\ """ issue_format = "[#{issue}](https://github.com/xkbcommon/libxkbcommon/issues/{issue})" # Sections configuration [[tool.towncrier.section]] name = "Keymap text format" path = "keymap-text-format" [[tool.towncrier.section]] name = "Rules text format" path = "rules-text-format" [[tool.towncrier.section]] name = "API" path = "api" [[tool.towncrier.section]] name = "Tools" path = "tools" [[tool.towncrier.section]] name = "Build system" path = "build" # Fragments configuration [[tool.towncrier.type]] directory = "breaking" name = "Breaking changes" showcontent = true [[tool.towncrier.type]] directory = "deprecated" name = "Deprecated" showcontent = true [[tool.towncrier.type]] directory = "feature" name = "New" showcontent = true [[tool.towncrier.type]] directory = "bugfix" name = "Fixes" showcontent = true xkbcommon-libxkbcommon-54ee7ac/xkbcommon-x11.map000066400000000000000000000002641510033435100217700ustar00rootroot00000000000000V_0.5.0 { global: xkb_x11_setup_xkb_extension; xkb_x11_get_core_keyboard_device_id; xkb_x11_keymap_new_from_device; xkb_x11_state_new_from_device; local: *; }; xkbcommon-libxkbcommon-54ee7ac/xkbcommon.map000066400000000000000000000071471510033435100213700ustar00rootroot00000000000000V_0.5.0 { global: xkb_keysym_get_name; xkb_keysym_from_name; xkb_keysym_to_utf8; xkb_keysym_to_utf32; xkb_context_new; xkb_context_ref; xkb_context_unref; xkb_context_set_user_data; xkb_context_get_user_data; xkb_context_include_path_append; xkb_context_include_path_append_default; xkb_context_include_path_reset_defaults; xkb_context_include_path_clear; xkb_context_num_include_paths; xkb_context_include_path_get; xkb_context_set_log_level; xkb_context_get_log_level; xkb_context_set_log_verbosity; xkb_context_get_log_verbosity; xkb_context_set_log_fn; xkb_keymap_new_from_names; xkb_keymap_new_from_file; xkb_keymap_new_from_string; xkb_keymap_new_from_buffer; xkb_keymap_ref; xkb_keymap_unref; xkb_keymap_get_as_string; xkb_keymap_min_keycode; xkb_keymap_max_keycode; xkb_keymap_key_for_each; xkb_keymap_num_mods; xkb_keymap_mod_get_name; xkb_keymap_mod_get_index; xkb_keymap_num_layouts; xkb_keymap_layout_get_name; xkb_keymap_layout_get_index; xkb_keymap_num_leds; xkb_keymap_led_get_name; xkb_keymap_led_get_index; xkb_keymap_num_layouts_for_key; xkb_keymap_num_levels_for_key; xkb_keymap_key_get_syms_by_level; xkb_keymap_key_repeats; xkb_state_new; xkb_state_ref; xkb_state_unref; xkb_state_get_keymap; xkb_state_update_key; xkb_state_update_mask; xkb_state_key_get_syms; xkb_state_key_get_utf8; xkb_state_key_get_utf32; xkb_state_key_get_one_sym; xkb_state_key_get_layout; xkb_state_key_get_level; xkb_state_serialize_mods; xkb_state_serialize_layout; xkb_state_mod_name_is_active; xkb_state_mod_names_are_active; xkb_state_mod_index_is_active; xkb_state_mod_indices_are_active; xkb_state_mod_index_is_consumed; xkb_state_mod_mask_remove_consumed; xkb_state_key_get_consumed_mods; xkb_state_layout_name_is_active; xkb_state_layout_index_is_active; xkb_state_led_name_is_active; xkb_state_led_index_is_active; xkb_compose_table_new_from_locale; xkb_compose_table_new_from_file; xkb_compose_table_new_from_buffer; xkb_compose_table_ref; xkb_compose_table_unref; xkb_compose_state_new; xkb_compose_state_ref; xkb_compose_state_unref; xkb_compose_state_get_compose_table; xkb_compose_state_feed; xkb_compose_state_reset; xkb_compose_state_get_status; xkb_compose_state_get_utf8; xkb_compose_state_get_one_sym; local: *; }; V_0.6.0 { global: xkb_keymap_key_get_name; xkb_keymap_key_by_name; } V_0.5.0; V_0.7.0 { global: xkb_state_key_get_consumed_mods2; xkb_state_mod_index_is_consumed2; } V_0.6.0; V_0.8.0 { global: xkb_keysym_to_lower; xkb_keysym_to_upper; } V_0.7.0; V_1.0.0 { global: xkb_utf32_to_keysym; xkb_keymap_key_get_mods_for_level; } V_0.8.0; V_1.6.0 { global: xkb_compose_table_entry_sequence; xkb_compose_table_entry_keysym; xkb_compose_table_entry_utf8; xkb_compose_table_iterator_new; xkb_compose_table_iterator_free; xkb_compose_table_iterator_next; } V_1.0.0; V_1.9.0 { global: xkb_components_names_from_rules; } V_1.6.0; V_1.10.0 { global: xkb_keymap_mod_get_mask; xkb_state_update_latched_locked; } V_1.9.0; V_1.11.0 { global: xkb_rmlvo_builder_new; xkb_rmlvo_builder_append_layout; xkb_rmlvo_builder_append_option; xkb_rmlvo_builder_ref; xkb_rmlvo_builder_unref; xkb_keymap_mod_get_mask2; xkb_keymap_new_from_rmlvo; xkb_keymap_new_from_names2; } V_1.10.0; V_1.12.0 { global: xkb_keymap_get_as_string2; } V_1.11.0; xkbcommon-libxkbcommon-54ee7ac/xkbregistry.map000066400000000000000000000033011510033435100217340ustar00rootroot00000000000000/* versions are kept in sync with libxkbcommon.so */ V_1.0.0 { global: rxkb_context_new; rxkb_context_parse; rxkb_context_parse_default_ruleset; rxkb_context_ref; rxkb_context_unref; rxkb_context_set_user_data; rxkb_context_get_user_data; rxkb_context_set_log_level; rxkb_context_get_log_level; rxkb_context_set_log_fn; rxkb_context_include_path_append; rxkb_context_include_path_append_default; rxkb_model_first; rxkb_model_next; rxkb_model_ref; rxkb_model_unref; rxkb_model_get_name; rxkb_model_get_description; rxkb_model_get_vendor; rxkb_model_get_popularity; rxkb_layout_first; rxkb_layout_next; rxkb_layout_ref; rxkb_layout_unref; rxkb_layout_get_name; rxkb_layout_get_brief; rxkb_layout_get_description; rxkb_layout_get_variant; rxkb_layout_get_popularity; rxkb_option_group_first; rxkb_option_group_next; rxkb_option_group_ref; rxkb_option_group_unref; rxkb_option_group_get_name; rxkb_option_group_get_description; rxkb_option_group_allows_multiple; rxkb_option_group_get_popularity; rxkb_option_first; rxkb_option_next; rxkb_option_ref; rxkb_option_unref; rxkb_option_get_name; rxkb_option_get_brief; rxkb_option_get_description; rxkb_option_get_popularity; rxkb_layout_get_iso639_first; rxkb_iso639_code_next; rxkb_iso639_code_ref; rxkb_iso639_code_unref; rxkb_iso639_code_get_code; rxkb_layout_get_iso3166_first; rxkb_iso3166_code_next; rxkb_iso3166_code_ref; rxkb_iso3166_code_unref; rxkb_iso3166_code_get_code; local: *; }; V_1.11.0 { global: rxkb_option_is_layout_specific; } V_1.0.0;

= ; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/keycodes-bounds-multiple-1.xkb000066400000000000000000000005321510033435100300170ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 300; = 1; = 300; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/keycodes-bounds-multiple-2.xkb000066400000000000000000000005451510033435100300240ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "high" { minimum = 2; maximum = 65535; = 2; = 65535; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/keycodes-bounds-multiple-3.xkb000066400000000000000000000005361510033435100300250ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 65538; = 1; = 65538; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/keycodes-bounds-single-1.xkb000066400000000000000000000004751510033435100274530ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 1; maximum = 255; = 1; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/keycodes-bounds-single-2.xkb000066400000000000000000000004771510033435100274560ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 300; = 300; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/level-index-names.xkb000066400000000000000000000005101510033435100262430ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; }; xkb_types { type "X" { modifiers= Shift; map[Shift]= 2048; level_name[2048]= "x"; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/masks-extra-bits.xkb000066400000000000000000000010231510033435100261240ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; = 38; }; xkb_types { virtual_modifiers X=0xf0000000; type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { virtual_modifiers X=0xf0000000; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetMods(modifiers=0x1100) ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/masks.xkb000066400000000000000000000011641510033435100240520ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; }; xkb_types { virtual_modifiers Test01,Test02=0xffffffff,Test11=all,Test12=Mod2+Mod3+Mod4+Mod5,Test13=0xfffffff0,Test14=0xffffffff,Test15=0xffffff00,Test16,Test17=Mod1+Mod2; type "XXX" { modifiers= Test12; map[Test12]= 2; }; }; xkb_compatibility { virtual_modifiers Test01,Test02=0xffffffff,Test11=all,Test12=Mod2+Mod3+Mod4+Mod5,Test13=0xfffffff0,Test14=0xffffffff,Test15=0xffffff00,Test16,Test17=Mod1+Mod2; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/000077500000000000000000000000001510033435100244305ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/augment.xkb000066400000000000000000001025331510033435100266020ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 93; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 158; = 161; = 164; = 167; = 170; = 173; = 176; = 179; = 182; = 185; = 188; = 191; = 194; = 197; = 200; = 212; = 215; = 218; <1> = 241; <2> = 242; <3> = 243; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 7 = "Suspend"; alias = <1>; alias = <2>; alias = <3>; }; xkb_types "" { virtual_modifiers NumLock=Mod2,LevelThree=none,LevelFive=Mod3,U1=0x800,U2=none,U3=0x300000,Z1=none,Z2=none,Z3=none,M1=0x1000,M2=0x2000,M3=0x3000,U7=0x100000,Z7=none,M7=0x700000; type "ONE_LEVEL" { modifiers= none; level_name[1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "XXX" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; level_name[1]= "1"; level_name[2]= "2"; level_name[3]= "3"; }; type "YYY" { modifiers= none; level_name[1]= "New"; }; }; xkb_compatibility "" { virtual_modifiers NumLock=Mod2,LevelThree=none,LevelFive=Mod3,U1=0x800,U2=none,U3=0x300000,Z1=none,Z2=none,Z3=none,M1=0x1000,M2=0x2000,M3=0x3000,U7=0x100000,Z7=none,M7=0x700000; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Kana" { whichModState= locked; modifiers= Control; }; }; xkb_symbols "" { key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ a ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a ], actions[1]= [ SetGroup(group=2) ] }; key { [ a ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a ], actions[1]= [ SetGroup(group=2) ] }; key { [ a, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ a, { A, Y } ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ a, A, Greek_alpha, NoSymbol ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2), SetGroup(group=3), NoAction() ] }; key { repeat= No, symbols[1]= [ a, A, Greek_alpha, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2), SetGroup(group=3), NoAction() ] }; key { [ a, A, a, NoSymbol ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2), SetGroup(group=2), NoAction() ] }; key { repeat= No, symbols[1]= [ a, A, a, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2), SetGroup(group=2), NoAction() ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, X ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { A, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ a, B ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, B ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, B ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, B ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ { a, y }, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ { a, y }, { A, Y } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ { a, y }, { X, B } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { repeat= No, symbols[1]= [ { a, y }, { X, B } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ { a, y }, { X, A } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { repeat= No, symbols[1]= [ { a, y }, { X, A } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { [ { a, y }, { X, A } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { repeat= No, symbols[1]= [ { a, y }, { X, A } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { [ NoSymbol, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, { A, Y } ], actions[1]= [ NoAction(), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ Greek_alpha, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ Greek_alpha, { A, Y } ], actions[1]= [ SetGroup(group=3), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ a, B ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, B ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ a, B ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, B ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ a, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ { a, b }, X ], actions[1]= [ SetGroup(group=3), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ { a, b }, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ a, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ { a, b }, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ { a, b }, { A, B } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ a, { A, B } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ { a, b }, B ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, B ], actions[1]= [ SetGroup(group=2), SetMods(modifiers=Control) ] }; key { repeat= No, symbols[1]= [ a, { A, B } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { A, B }, a ], actions[1]= [ SetGroup(group=3), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ a, { A, B } ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ A ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ A ], actions[1]= [ SetGroup(group=2) ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/compat.xkb000066400000000000000000000015501510033435100264220ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; <> = 8; indicator 1 = "A"; indicator 2 = "B"; indicator 3 = "C"; indicator 4 = "D"; }; xkb_types { type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret A+AnyOfOrNone(all) { repeat= True; action= SetMods(modifiers=Mod1); }; interpret B+AnyOfOrNone(all) { repeat= True; action= SetMods(modifiers=Mod1); }; interpret C+AnyOfOrNone(all) { repeat= True; action= SetMods(modifiers=Mod1); }; interpret D+AnyOfOrNone(all) { action= SetMods(modifiers=Mod1); }; indicator "A" { groups= 0x01; modifiers= Lock; }; indicator "B" { groups= 0x01; modifiers= Lock; }; indicator "C" { groups= 0x01; modifiers= Lock; }; indicator "D" { groups= 0x01; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/default.xkb000066400000000000000000001031641510033435100265670ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 93; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 158; = 161; = 164; = 167; = 170; = 173; = 176; = 179; = 182; = 185; = 188; = 191; = 194; = 197; = 200; = 212; = 215; = 218; <1> = 241; <3> = 243; <2> = 244; indicator 1 = "Caps Lock"; indicator 2 = "Kana"; indicator 4 = "XXXX"; indicator 5 = "Scroll Lock"; indicator 6 = "Num Lock"; indicator 7 = "Suspend"; alias = <1>; alias = <3>; alias = <3>; }; xkb_types "" { virtual_modifiers NumLock=Mod2,LevelThree=Mod5,LevelFive=Mod3,U1=0x800,U2=none,U3=0x300000,Z1=none,Z2=none,Z3=0x310000,M1=0x1000,M2=none,M3=0x320000,U7=0x100000,Z7=none,M7=0x700000; type "ONE_LEVEL" { modifiers= none; level_name[1]= "New"; }; type "TWO_LEVEL" { modifiers= Shift+M1; map[Shift]= 2; map[M1]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Lock; map[none]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "XXX" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Shift+LevelThree]= 4; level_name[1]= "A"; level_name[2]= "2"; level_name[3]= "3"; level_name[4]= "4"; }; type "YYY" { modifiers= none; level_name[1]= "New"; }; }; xkb_compatibility "" { virtual_modifiers NumLock=Mod2,LevelThree=Mod5,LevelFive=Mod3,U1=0x800,U2=none,U3=0x300000,Z1=none,Z2=none,Z3=0x310000,M1=0x1000,M2=none,M3=0x320000,U7=0x100000,Z7=none,M7=0x700000; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=NumLock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Kana" { whichModState= locked; modifiers= Control; }; indicator "Num Lock" { whichModState= base; modifiers= Lock; }; }; xkb_symbols "" { key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ a ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a ], actions[1]= [ SetGroup(group=2) ] }; key { [ a ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a ], actions[1]= [ SetGroup(group=2) ] }; key { [ a, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ a, { A, Y } ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] }; key { [ Greek_alpha, Greek_ALPHA, a, NoSymbol ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=2), NoAction() ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA, a, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=2), NoAction() ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ a, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, Greek_ALPHA ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, X ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ a, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, Greek_ALPHA ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { [ a, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, Greek_ALPHA ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ { a, y }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { a, y }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ { a, y }, { X, A } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { repeat= No, symbols[1]= [ { a, y }, { X, A } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ NoSymbol, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, { A, Y } ], actions[1]= [ NoAction(), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ a, B ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, B ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ { a, b }, X ], actions[1]= [ SetGroup(group=3), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ { a, b }, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ { x, y }, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ x, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ x, { A, B } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { x, y }, { A, B } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ y, { X, Y } ], actions[1]= [ SetGroup(group=3), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ y, X ], actions[1]= [ SetMods(modifiers=Mod5), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, { A, B } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { A, B }, a ], actions[1]= [ SetGroup(group=3), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { x, y }, X ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { A, A } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ Y ], actions[1]= [ SetGroup(group=3) ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/defaults-include.xkb000066400000000000000000000037631510033435100303770ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; = 38; = 39; = 40; = 41; = 42; indicator 1 = "A"; indicator 2 = "B"; indicator 3 = "C"; }; xkb_types { virtual_modifiers M1=0x1001,M2=0x2004,M3=0x4020,M4=0x8001; type "ONE_LEVEL" { modifiers= none; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; }; }; xkb_compatibility "merge_modes_defaults" { virtual_modifiers M1=0x1001,M2=0x2004,M3=0x4020,M4=0x8001; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret a+AnyOfOrNone(all) { virtualModifier= M4; repeat= True; action= SetGroup(group=1); }; interpret A+AnyOfOrNone(all) { virtualModifier= M1; action= SetMods(modifiers=M1); }; interpret s+AnyOfOrNone(all) { virtualModifier= M2; useModMapMods=level1; action= SetGroup(group=2); }; interpret S+AnyOfOrNone(all) { virtualModifier= M2; repeat= True; action= SetGroup(group=4); }; interpret g+AnyOfOrNone(all) { virtualModifier= M3; action= SetGroup(group=3); }; indicator "A" { whichGroupState= locked; groups= 0xfffffffe; whichModState= locked; modifiers= M2; controls= SlowKeys; }; indicator "B" { groups= 0xfffffffe; whichModState= base; modifiers= M4; controls= AudibleBell; }; indicator "C" { whichModState= locked; modifiers= M3; }; }; xkb_symbols "merge_modes_defaults" { name[1]="yyy"; key { [ a, A ] }; key { [ s, S ] }; key { repeat= No, virtualMods= M4, [ d, D ] }; key { repeat= No, virtualMods= M4, [ f, F ] }; key { type= "ONE_LEVEL", repeat= Yes, symbols[1]= [ g ] }; modifier_map Shift { }; modifier_map Control { }; modifier_map Mod3 { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/defaults-plain.xkb000066400000000000000000000037051510033435100300530ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; = 38; = 39; = 40; = 41; = 42; indicator 1 = "A"; indicator 2 = "B"; indicator 3 = "C"; }; xkb_types { virtual_modifiers M1=0x1001,M2=0x2004,M3=0x4020,M4=0x8001; type "ONE_LEVEL" { modifiers= none; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= 2; map[Lock]= 2; }; }; xkb_compatibility { virtual_modifiers M1=0x1001,M2=0x2004,M3=0x4020,M4=0x8001; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret a+AnyOfOrNone(all) { virtualModifier= M4; repeat= True; action= SetGroup(group=1); }; interpret A+AnyOfOrNone(all) { virtualModifier= M1; action= SetMods(modifiers=M1); }; interpret s+AnyOfOrNone(all) { virtualModifier= M2; useModMapMods=level1; action= SetGroup(group=2); }; interpret S+AnyOfOrNone(all) { virtualModifier= M2; repeat= True; action= SetGroup(group=4); }; interpret g+AnyOfOrNone(all) { virtualModifier= M3; action= SetGroup(group=3); }; indicator "A" { whichGroupState= locked; groups= 0xfffffffe; whichModState= locked; modifiers= M2; controls= SlowKeys; }; indicator "B" { groups= 0xfffffffe; whichModState= base; modifiers= M4; controls= AudibleBell; }; indicator "C" { whichModState= locked; modifiers= M3; }; }; xkb_symbols { name[1]="yyy"; key { [ a, A ] }; key { [ s, S ] }; key { repeat= No, virtualMods= M4, [ d, D ] }; key { repeat= No, virtualMods= M4, [ f, F ] }; key { type= "ONE_LEVEL", repeat= Yes, symbols[1]= [ g ] }; modifier_map Shift { }; modifier_map Control { }; modifier_map Mod3 { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/override.xkb000066400000000000000000001031641510033435100267620ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 93; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 158; = 161; = 164; = 167; = 170; = 173; = 176; = 179; = 182; = 185; = 188; = 191; = 194; = 197; = 200; = 212; = 215; = 218; <1> = 241; <3> = 243; <2> = 244; indicator 1 = "Caps Lock"; indicator 2 = "Kana"; indicator 4 = "XXXX"; indicator 5 = "Scroll Lock"; indicator 6 = "Num Lock"; indicator 7 = "Suspend"; alias = <1>; alias = <3>; alias = <3>; }; xkb_types "" { virtual_modifiers NumLock=Mod2,LevelThree=Mod5,LevelFive=Mod3,U1=0x800,U2=none,U3=0x300000,Z1=none,Z2=none,Z3=0x310000,M1=0x1000,M2=none,M3=0x320000,U7=0x100000,Z7=none,M7=0x700000; type "ONE_LEVEL" { modifiers= none; level_name[1]= "New"; }; type "TWO_LEVEL" { modifiers= Shift+M1; map[Shift]= 2; map[M1]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Lock; map[none]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "XXX" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Shift+LevelThree]= 4; level_name[1]= "A"; level_name[2]= "2"; level_name[3]= "3"; level_name[4]= "4"; }; type "YYY" { modifiers= none; level_name[1]= "New"; }; }; xkb_compatibility "" { virtual_modifiers NumLock=Mod2,LevelThree=Mod5,LevelFive=Mod3,U1=0x800,U2=none,U3=0x300000,Z1=none,Z2=none,Z3=0x310000,M1=0x1000,M2=none,M3=0x320000,U7=0x100000,Z7=none,M7=0x700000; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=NumLock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Kana" { whichModState= locked; modifiers= Control; }; indicator "Num Lock" { whichModState= base; modifiers= Lock; }; }; xkb_symbols "" { key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ a ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a ], actions[1]= [ SetGroup(group=2) ] }; key { [ a ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a ], actions[1]= [ SetGroup(group=2) ] }; key { [ a, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ a, { A, Y } ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] }; key { [ Greek_alpha, Greek_ALPHA, a, NoSymbol ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=2), NoAction() ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA, a, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=2), NoAction() ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ a, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, A ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ a, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, Greek_ALPHA ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, X ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ Greek_alpha, A ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, A ], actions[1]= [ SetGroup(group=3), SetGroup(group=2) ] }; key { [ a, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, Greek_ALPHA ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { [ a, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, Greek_ALPHA ], actions[1]= [ SetGroup(group=2), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ { a, y }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { a, y }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ { a, y }, { X, A } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { repeat= No, symbols[1]= [ { a, y }, { X, A } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] }; key { [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ NoSymbol, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, { A, Y } ], actions[1]= [ NoAction(), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ a, B ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a, B ], actions[1]= [ SetGroup(group=2), SetGroup(group=2) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ { a, b }, X ], actions[1]= [ SetGroup(group=3), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ { a, b }, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ { x, y }, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ x, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ x, { A, B } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { x, y }, { A, B } ], actions[1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ y, { X, Y } ], actions[1]= [ SetGroup(group=3), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ y, X ], actions[1]= [ SetMods(modifiers=Mod5), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ a, { A, B } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { A, B }, a ], actions[1]= [ SetGroup(group=3), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { x, y }, X ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { A, A } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ Y ], actions[1]= [ SetGroup(group=3) ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/replace.xkb000066400000000000000000000725071510033435100265640ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 93; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 158; = 161; = 164; = 167; = 170; = 173; = 176; = 179; = 182; = 185; = 188; = 191; = 194; = 197; = 200; = 212; = 215; = 218; <1> = 241; <3> = 243; <2> = 244; indicator 1 = "Caps Lock"; indicator 2 = "Kana"; indicator 4 = "XXXX"; indicator 5 = "Scroll Lock"; indicator 6 = "Num Lock"; indicator 7 = "Suspend"; alias = <1>; alias = <3>; alias = <3>; }; xkb_types "" { virtual_modifiers NumLock=Mod2,LevelThree=Mod5,LevelFive=Mod3,U1=0x800,U2=none,U3=0x300000,Z1=none,Z2=none,Z3=0x310000,M1=0x1000,M2=none,M3=0x320000,U7=0x100000,Z7=none,M7=0x700000; type "ONE_LEVEL" { modifiers= none; level_name[1]= "New"; }; type "TWO_LEVEL" { modifiers= Shift+M1; map[Shift]= 2; map[M1]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; type "ALPHABETIC" { modifiers= Lock; map[none]= 2; level_name[1]= "Base"; level_name[2]= "Caps"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= 2; map[NumLock]= 2; level_name[1]= "Base"; level_name[2]= "Number"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 4; map[Shift+Lock+LevelThree]= 3; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Lock]= 2; map[LevelThree]= 3; map[Shift+LevelThree]= 4; map[Lock+LevelThree]= 3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= 4; preserve[Shift+Lock+LevelThree]= Lock; level_name[1]= "Base"; level_name[2]= "Shift"; level_name[3]= "Alt Base"; level_name[4]= "Shift Alt"; }; type "XXX" { modifiers= Shift+Lock+LevelThree; map[Shift]= 2; map[Shift+LevelThree]= 4; level_name[1]= "A"; level_name[2]= "2"; level_name[3]= "3"; level_name[4]= "4"; }; type "YYY" { modifiers= none; level_name[1]= "New"; }; }; xkb_compatibility "" { virtual_modifiers NumLock=Mod2,LevelThree=Mod5,LevelFive=Mod3,U1=0x800,U2=none,U3=0x300000,Z1=none,Z2=none,Z3=0x310000,M1=0x1000,M2=none,M3=0x320000,U7=0x100000,Z7=none,M7=0x700000; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=NumLock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Kana" { whichModState= locked; modifiers= Control; }; indicator "Num Lock" { whichModState= base; modifiers= Lock; }; }; xkb_symbols "" { key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ a ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=2) ] }; key { repeat= No, symbols[1]= [ a ], actions[1]= [ SetGroup(group=2) ] }; key { [ a, { A, Y } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { repeat= No, symbols[1]= [ a, { A, Y } ], actions[1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, X ], actions[1]= [ SetGroup(group=3), NoAction() ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ Greek_alpha ] }; key { repeat= No, symbols[1]= [ NoSymbol ], actions[1]= [ SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha ], actions[1]= [ SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ NoSymbol, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, Greek_ALPHA ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, { Greek_ALPHA, Greek_UPSILON } ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { [ Greek_alpha, Greek_BETA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_BETA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { repeat= No, symbols[1]= [ { Greek_alpha, Greek_xi }, { Greek_XI, Greek_BETA } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { [ Greek_alpha, Greek_ALPHA ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ Greek_alpha, Greek_ALPHA ], actions[1]= [ SetGroup(group=3), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, NoAction() ] }; key { repeat= No, symbols[1]= [ NoSymbol, X ], actions[1]= [ SetGroup(group=3), NoAction() ] }; key { repeat= No, symbols[1]= [ NoSymbol, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, NoAction() ] }; key { repeat= No, symbols[1]= [ { x, y }, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ x, { X, Y } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ x, NoSymbol ], actions[1]= [ NoAction(), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { x, y }, NoSymbol ], actions[1]= [ NoAction(), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ y, { X, Y } ], actions[1]= [ SetGroup(group=3), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ y, X ], actions[1]= [ SetMods(modifiers=Mod5), SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ NoSymbol, NoSymbol ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { [ { A, B }, a ] }; key { repeat= No, symbols[1]= [ { x, y }, X ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] }; key { repeat= No, symbols[1]= [ { A, A } ], actions[1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) } ] }; key { repeat= No, symbols[1]= [ Y ], actions[1]= [ SetGroup(group=3) ] }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modes/vmods-other-component-direct.xkb000066400000000000000000000012431510033435100326550ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; }; xkb_types { virtual_modifiers U1=0x100,U2=none,U3=0x300000,U4=0x800,U5=none,U6=0x600000,Z1=none,Z2=none,Z3=none,Z4=none,Z5=none,Z6=0x610000,M1=0x1000,M2=0x2000,M3=0x3000,M4=0x4000,M5=none,M6=0x620000; type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility "" { virtual_modifiers U1=0x100,U2=none,U3=0x300000,U4=0x800,U5=none,U6=0x600000,Z1=none,Z2=none,Z3=none,Z4=none,Z5=none,Z6=0x610000,M1=0x1000,M2=0x2000,M3=0x3000,M4=0x4000,M5=none,M6=0x620000; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; vmods-same-component-include-default-augment.xkb000066400000000000000000000013361510033435100356360ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modesxkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; }; xkb_types "" { virtual_modifiers U1=0x100,U2=none,U3=0x300000,U4=0x800,U5=none,U6=0x600000,Z1=none,Z2=none,Z3=none,Z4=none,Z5=none,Z6=none,M1=0x1000,M2=0x2000,M3=0x3000,M4=0x4000,M5=0x5000,M6=0x6000,U7=0x4000000,Z7=none,M7=0x70000; type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility "" { virtual_modifiers U1=0x100,U2=none,U3=0x300000,U4=0x800,U5=none,U6=0x600000,Z1=none,Z2=none,Z3=none,Z4=none,Z5=none,Z6=none,M1=0x1000,M2=0x2000,M3=0x3000,M4=0x4000,M5=0x5000,M6=0x6000,U7=0x4000000,Z7=none,M7=0x70000; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; vmods-same-component-include-default-override.xkb000066400000000000000000000013561510033435100360170ustar00rootroot00000000000000xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/merge-modesxkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; }; xkb_types "" { virtual_modifiers U1=0x100,U2=none,U3=0x300000,U4=0x800,U5=none,U6=0x600000,Z1=none,Z2=none,Z3=0x310000,Z4=none,Z5=none,Z6=0x610000,M1=0x1000,M2=none,M3=0x320000,M4=0x4000,M5=none,M6=0x620000,U7=0x4000000,Z7=none,M7=0x70000; type "ONE_LEVEL" { modifiers= none; }; }; xkb_compatibility "" { virtual_modifiers U1=0x100,U2=none,U3=0x300000,U4=0x800,U5=none,U6=0x600000,Z1=none,Z2=none,Z3=0x310000,Z4=none,Z5=none,Z6=0x610000,M1=0x1000,M2=none,M3=0x320000,M4=0x4000,M5=none,M6=0x620000,U7=0x4000000,Z7=none,M7=0x70000; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret VoidSymbol+AnyOfOrNone(none) { repeat= True; }; }; xkb_symbols { }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/modmap-none.xkb000066400000000000000000000065471510033435100251600ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "test" { minimum = 8; maximum = 255; = 92; = 50; = 62; = 64; = 108; = 133; = 134; = 37; = 105; = 66; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; }; xkb_types "complete" { type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= 2; level_name[1]= "Base"; level_name[2]= "Shift"; }; }; xkb_compatibility "complete" { interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret.locking= False; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; }; xkb_symbols { name[group1]="Test"; // Reset modmap with a key with empty modmap key { [VoidSymbol] }; modmap None { }; // Reset modmap with one key key { [Shift_L] }; modmap Shift { }; modmap none { }; // Reset modmap with one symbol key { [Shift_R] }; modmap Shift { Shift_R }; modmap NONE { Shift_R }; // Cycle key { [Super_L] }; modmap Mod4 { }; modmap None { }; modmap Mod4 { }; // Cycle key { [Super_R] }; modmap Mod4 { }; modmap None { }; modmap Mod4 { Super_R }; // Mix keycode and keysym key { [Control_L] }; modmap Control { Control_L }; modmap None { }; // Mix keycode and keysym key { [Control_R] }; modmap Control { }; modmap None { Control_R }; // Re-set with different modifier key { [Alt_L] }; modmap Mod2 { }; modmap None { }; modmap Mod1 { }; // Re-set with different modifier with both key and keysym key { [ISO_Level3_Shift] }; modmap Mod1 { }; // Mod1 modmap None { }; // None modmap Mod2 { }; // Mod2 modmap Mod3 { ISO_Level3_Shift }; // Mod2 | Mod3 modmap None { ISO_Level3_Shift }; // Mod2 modmap Mod5 { ISO_Level3_Shift }; // Mod2 | Mod5 // Re-set with different modifier with both key and keysym key { [Caps_Lock] }; modmap Mod1 { Caps_Lock }; // Mod1 modmap None { }; // Mod1 modmap None { Caps_Lock }; // None modmap Lock { }; // Lock // Merge modes key { [q] }; modMap Mod1 { }; augment modMap None { }; key { [w] }; modMap Mod2 { }; override modMap None { }; key { [e] }; modMap Mod3 { }; replace modMap None { }; key { [r] }; modMap Mod1 { }; augment modMap None { r }; key { [t] }; modMap Mod2 { }; replace modMap None { t }; key { [y] }; modMap Mod3 { }; override modMap None { y }; key { [u] }; modMap Mod1 { }; replace key { [U] }; // Won’t affect the modMap key { [i] }; modMap Mod2 { i, I }; replace key { [I] }; modMap None { i }; // Does not resolve key { [1] }; modMap Mod3 { 1, 2 }; override key { [NoSymbol, 2] }; modMap None { 1 }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/no-aliases.xkb000066400000000000000000001260111510033435100247660ustar00rootroot00000000000000xkb_keymap { xkb_keycodes "evdev_aliases(qwerty)" { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; indicator 12 = "Shift Lock"; indicator 13 = "Group 2"; indicator 14 = "Mouse Keys"; }; xkb_types "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; type "ONE_LEVEL" { modifiers= none; level_name[Level1]= "Any"; }; type "TWO_LEVEL" { modifiers= Shift; map[Shift]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; }; type "ALPHABETIC" { modifiers= Shift+Lock; map[Shift]= Level2; map[Lock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Caps"; }; type "SHIFT+ALT" { modifiers= Shift+Alt; map[Shift+Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Shift+Alt"; }; type "PC_CONTROL_LEVEL2" { modifiers= Control; map[Control]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Control"; }; type "PC_LCONTROL_LEVEL2" { modifiers= LControl; map[LControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LControl"; }; type "PC_RCONTROL_LEVEL2" { modifiers= RControl; map[RControl]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RControl"; }; type "PC_ALT_LEVEL2" { modifiers= Alt; map[Alt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Alt"; }; type "PC_LALT_LEVEL2" { modifiers= LAlt; map[LAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "LAlt"; }; type "PC_RALT_LEVEL2" { modifiers= RAlt; map[RAlt]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "RAlt"; }; type "CTRL+ALT" { modifiers= Shift+Control+Alt+LevelThree; map[Shift]= Level2; preserve[Shift]= Shift; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; preserve[Shift+LevelThree]= Shift; map[Control+Alt]= Level5; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Ctrl+Alt"; }; type "LOCAL_EIGHT_LEVEL" { modifiers= Shift+Lock+Control+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Control]= Level5; map[Shift+Lock+Control]= Level5; map[Shift+Control]= Level6; map[Lock+Control]= Level6; map[Control+LevelThree]= Level7; map[Shift+Lock+Control+LevelThree]= Level7; map[Shift+Control+LevelThree]= Level8; map[Lock+Control+LevelThree]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; level_name[Level4]= "Shift Level3"; level_name[Level5]= "Ctrl"; level_name[Level6]= "Shift Ctrl"; level_name[Level7]= "Level3 Ctrl"; level_name[Level8]= "Shift Level3 Ctrl"; }; type "THREE_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Level3"; }; type "EIGHT_LEVEL" { modifiers= Shift+LevelThree+LevelFive; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level8; map[Shift+Lock+LevelThree+LevelFive]= Level7; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "EIGHT_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree+LevelFive; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; map[LevelFive]= Level5; map[Shift+LevelFive]= Level6; map[Lock+LevelFive]= Level6; preserve[Lock+LevelFive]= Lock; map[Shift+Lock+LevelFive]= Level6; preserve[Shift+Lock+LevelFive]= Lock; map[LevelThree+LevelFive]= Level7; map[Shift+LevelThree+LevelFive]= Level8; map[Lock+LevelThree+LevelFive]= Level7; preserve[Lock+LevelThree+LevelFive]= Lock; map[Shift+Lock+LevelThree+LevelFive]= Level8; preserve[Shift+Lock+LevelThree+LevelFive]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "X"; level_name[Level6]= "X Shift"; level_name[Level7]= "X Alt Base"; level_name[Level8]= "X Shift Alt"; }; type "FOUR_LEVEL" { modifiers= Shift+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level4; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_SEMIALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level4; preserve[Shift+Lock+LevelThree]= Lock; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_MIXED_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[NumLock]= Level2; map[Shift]= Level2; map[LevelThree]= Level3; map[NumLock+LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; }; type "FOUR_LEVEL_X" { modifiers= Shift+Control+Alt+LevelThree; map[LevelThree]= Level2; map[Shift+LevelThree]= Level3; map[Control+Alt]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Alt Base"; level_name[Level3]= "Shift Alt"; level_name[Level4]= "Ctrl+Alt"; }; type "SEPARATE_CAPS_AND_SHIFT_ALPHABETIC" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[Lock]= Level4; preserve[Lock]= Lock; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock+LevelThree]= Level3; preserve[Lock+LevelThree]= Lock; map[Shift+Lock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "AltGr Base"; level_name[Level4]= "Shift AltGr"; }; type "FOUR_LEVEL_PLUS_LOCK" { modifiers= Shift+Lock+LevelThree; map[Shift]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[Lock]= Level5; map[Shift+Lock]= Level2; map[Lock+LevelThree]= Level3; map[Shift+Lock+LevelThree]= Level4; level_name[Level1]= "Base"; level_name[Level2]= "Shift"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Shift Alt"; level_name[Level5]= "Lock"; }; type "KEYPAD" { modifiers= Shift+NumLock; map[Shift]= Level2; map[NumLock]= Level2; level_name[Level1]= "Base"; level_name[Level2]= "Number"; }; type "FOUR_LEVEL_KEYPAD" { modifiers= Shift+NumLock+LevelThree; map[Shift]= Level2; map[NumLock]= Level2; map[LevelThree]= Level3; map[Shift+LevelThree]= Level4; map[NumLock+LevelThree]= Level4; map[Shift+NumLock+LevelThree]= Level3; level_name[Level1]= "Base"; level_name[Level2]= "Number"; level_name[Level3]= "Alt Base"; level_name[Level4]= "Alt Number"; }; }; xkb_compatibility "complete" { virtual_modifiers NumLock,Alt,LevelThree,LAlt,RAlt,RControl,LControl,ScrollLock,LevelFive,AltGr,Meta,Super,Hyper; interpret.useModMapMods= AnyLevel; interpret.repeat= False; interpret ISO_Level2_Latch+Exactly(Shift) { useModMapMods=level1; action= LatchMods(modifiers=Shift,clearLocks,latchToLock); }; interpret Shift_Lock+AnyOf(Shift+Lock) { action= LockMods(modifiers=Shift); }; interpret Num_Lock+AnyOf(all) { virtualModifier= NumLock; action= LockMods(modifiers=NumLock); }; interpret ISO_Level3_Shift+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOf(all) { virtualModifier= LevelThree; useModMapMods=level1; action= LockMods(modifiers=LevelThree); }; interpret Alt_L+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Alt_R+AnyOf(all) { virtualModifier= Alt; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_L+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Meta_R+AnyOf(all) { virtualModifier= Meta; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_L+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Super_R+AnyOf(all) { virtualModifier= Super; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_L+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Hyper_R+AnyOf(all) { virtualModifier= Hyper; action= SetMods(modifiers=modMapMods,clearLocks); }; interpret Scroll_Lock+AnyOf(all) { virtualModifier= ScrollLock; action= LockMods(modifiers=modMapMods); }; interpret ISO_Level5_Shift+AnyOf(all) { virtualModifier= LevelFive; useModMapMods=level1; action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOf(all) { virtualModifier= LevelFive; action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOf(all) { virtualModifier= LevelFive; action= LockMods(modifiers=LevelFive); }; interpret Mode_switch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= SetGroup(group=+1); }; interpret ISO_Level3_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelThree,clearLocks); }; interpret ISO_Level3_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelThree,clearLocks,latchToLock); }; interpret ISO_Level3_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelThree); }; interpret ISO_Group_Latch+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LatchGroup(group=2); }; interpret ISO_Next_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=+1); }; interpret ISO_Prev_Group+AnyOfOrNone(all) { virtualModifier= AltGr; useModMapMods=level1; action= LockGroup(group=-1); }; interpret ISO_First_Group+AnyOfOrNone(all) { action= LockGroup(group=1); }; interpret ISO_Last_Group+AnyOfOrNone(all) { action= LockGroup(group=2); }; interpret KP_1+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_End+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret KP_2+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_Down+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=+1); }; interpret KP_3+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_Next+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret KP_4+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_Left+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+0); }; interpret KP_6+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_Right+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+0); }; interpret KP_7+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_Home+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret KP_8+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_Up+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+0,y=-1); }; interpret KP_9+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_Prior+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret KP_5+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_Begin+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret KP_F2+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_Divide+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret KP_F3+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_Multiply+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret KP_F4+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Subtract+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=3); }; interpret KP_Separator+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_Add+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default,count=2); }; interpret KP_0+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Insert+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=lock); }; interpret KP_Decimal+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret KP_Delete+AnyOfOrNone(all) { repeat= True; action= LockPtrBtn(button=default,affect=unlock); }; interpret F25+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=1); }; interpret F26+AnyOfOrNone(all) { repeat= True; action= SetPtrDflt(affect=button,button=2); }; interpret F27+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=-1); }; interpret F29+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=-1); }; interpret F31+AnyOfOrNone(all) { repeat= True; action= PtrBtn(button=default); }; interpret F33+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=-1,y=+1); }; interpret F35+AnyOfOrNone(all) { repeat= True; action= MovePtr(x=+1,y=+1); }; interpret Pointer_Button_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default); }; interpret Pointer_Button1+AnyOfOrNone(all) { action= PtrBtn(button=1); }; interpret Pointer_Button2+AnyOfOrNone(all) { action= PtrBtn(button=2); }; interpret Pointer_Button3+AnyOfOrNone(all) { action= PtrBtn(button=3); }; interpret Pointer_DblClick_Dflt+AnyOfOrNone(all) { action= PtrBtn(button=default,count=2); }; interpret Pointer_DblClick1+AnyOfOrNone(all) { action= PtrBtn(button=1,count=2); }; interpret Pointer_DblClick2+AnyOfOrNone(all) { action= PtrBtn(button=2,count=2); }; interpret Pointer_DblClick3+AnyOfOrNone(all) { action= PtrBtn(button=3,count=2); }; interpret Pointer_Drag_Dflt+AnyOfOrNone(all) { action= LockPtrBtn(button=default); }; interpret Pointer_Drag1+AnyOfOrNone(all) { action= LockPtrBtn(button=1); }; interpret Pointer_Drag2+AnyOfOrNone(all) { action= LockPtrBtn(button=2); }; interpret Pointer_Drag3+AnyOfOrNone(all) { action= LockPtrBtn(button=3); }; interpret Pointer_EnableKeys+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret Pointer_Accelerate+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Pointer_DfltBtnNext+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=+1); }; interpret Pointer_DfltBtnPrev+AnyOfOrNone(all) { action= SetPtrDflt(affect=button,button=-1); }; interpret AccessX_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXKeys); }; interpret AccessX_Feedback_Enable+AnyOfOrNone(all) { action= LockControls(controls=AccessXFeedback); }; interpret RepeatKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=RepeatKeys); }; interpret SlowKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=SlowKeys); }; interpret BounceKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=BounceKeys); }; interpret StickyKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=StickyKeys); }; interpret MouseKeys_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeys); }; interpret MouseKeys_Accel_Enable+AnyOfOrNone(all) { action= LockControls(controls=MouseKeysAccel); }; interpret Overlay1_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret Overlay2_Enable+AnyOfOrNone(all) { action= LockControls(controls=none); }; interpret AudibleBell_Enable+AnyOfOrNone(all) { action= LockControls(controls=AudibleBell); }; interpret Terminate_Server+AnyOfOrNone(all) { action= Terminate(); }; interpret Alt_L+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Alt_R+AnyOfOrNone(all) { action= SetMods(modifiers=Alt,clearLocks); }; interpret Meta_L+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Meta_R+AnyOfOrNone(all) { action= SetMods(modifiers=Meta,clearLocks); }; interpret Super_L+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Super_R+AnyOfOrNone(all) { action= SetMods(modifiers=Super,clearLocks); }; interpret Hyper_L+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Hyper_R+AnyOfOrNone(all) { action= SetMods(modifiers=Hyper,clearLocks); }; interpret Shift_L+AnyOfOrNone(all) { action= SetMods(modifiers=Shift,clearLocks); }; interpret XF86Switch_VT_1+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=1,!same); }; interpret XF86Switch_VT_2+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=2,!same); }; interpret XF86Switch_VT_3+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=3,!same); }; interpret XF86Switch_VT_4+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=4,!same); }; interpret XF86Switch_VT_5+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=5,!same); }; interpret XF86Switch_VT_6+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=6,!same); }; interpret XF86Switch_VT_7+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=7,!same); }; interpret XF86Switch_VT_8+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=8,!same); }; interpret XF86Switch_VT_9+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=9,!same); }; interpret XF86Switch_VT_10+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=10,!same); }; interpret XF86Switch_VT_11+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=11,!same); }; interpret XF86Switch_VT_12+AnyOfOrNone(all) { repeat= True; action= SwitchScreen(screen=12,!same); }; interpret XF86LogGrabInfo+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x47,data[3]=0x72,data[4]=0x62,data[5]=0x73,data[6]=0x00); }; interpret XF86LogWindowTree+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x50,data[1]=0x72,data[2]=0x57,data[3]=0x69,data[4]=0x6e,data[5]=0x73,data[6]=0x00); }; interpret XF86Next_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2b,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret XF86Prev_VMode+AnyOfOrNone(all) { repeat= True; action= Private(type=0x86,data[0]=0x2d,data[1]=0x56,data[2]=0x4d,data[3]=0x6f,data[4]=0x64,data[5]=0x65,data[6]=0x00); }; interpret ISO_Level5_Shift+AnyOfOrNone(all) { action= SetMods(modifiers=LevelFive,clearLocks); }; interpret ISO_Level5_Latch+AnyOfOrNone(all) { action= LatchMods(modifiers=LevelFive,clearLocks,latchToLock); }; interpret ISO_Level5_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=LevelFive); }; interpret Caps_Lock+AnyOfOrNone(all) { action= LockMods(modifiers=Lock); }; interpret Any+Exactly(Lock) { action= LockMods(modifiers=Lock); }; interpret Any+AnyOf(all) { action= SetMods(modifiers=modMapMods,clearLocks); }; indicator "Caps Lock" { whichModState= locked; modifiers= Lock; }; indicator "Num Lock" { whichModState= locked; modifiers= NumLock; }; indicator "Scroll Lock" { whichModState= locked; modifiers= ScrollLock; }; indicator "Shift Lock" { whichModState= locked; modifiers= Shift; }; indicator "Group 2" { groups= 0xfe; }; indicator "Mouse Keys" { controls= MouseKeys; }; }; xkb_symbols "pc_us_inet(evdev)" { name[group1]="English (US)"; key { [ Escape ] }; key { [ 1, exclam ] }; key { [ 2, at ] }; key { [ 3, numbersign ] }; key { [ 4, dollar ] }; key { [ 5, percent ] }; key { [ { H, E, L, L, O }, asciicircum ] }; key { [ { Y, E, S, space, T, H, I, S, space, I, S, space, D, O, G }, ampersand ] }; key { [ 8, asterisk ] }; key { [ 9, parenleft ] }; key { [ 0, parenright ] }; key { [ minus, underscore ] }; key { [ equal, plus ] }; key { [ BackSpace, BackSpace ] }; key { [ Tab, ISO_Left_Tab ] }; key { [ q, Q ] }; key { [ w, W ] }; key { [ e, E ] }; key { [ r, R ] }; key { [ t, T ] }; key { [ y, Y ] }; key { [ u, U ] }; key { [ i, I ] }; key { [ o, O ] }; key { [ p, P ] }; key { [ bracketleft, braceleft ] }; key { [ bracketright, braceright ] }; key { [ Return ] }; key { [ Control_L ] }; key { [ a, A ] }; key { [ s, S ] }; key { [ d, D ] }; key { [ f, F ] }; key { [ g, G ] }; key { [ h, H ] }; key { [ j, J ] }; key { [ k, K ] }; key { [ l, L ] }; key { [ semicolon, colon ] }; key { [ apostrophe, quotedbl ] }; key { [ grave, asciitilde ] }; key { [ Shift_L ] }; key { [ backslash, bar ] }; key { [ z, Z ] }; key { [ x, X ] }; key { [ c, C ] }; key { [ v, V ] }; key { [ b, B ] }; key { [ n, N ] }; key { [ m, M ] }; key { [ comma, less ] }; key { [ period, greater ] }; key { [ slash, question ] }; key { [ Shift_R ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Multiply, KP_Multiply, KP_Multiply, KP_Multiply, XF86ClearGrab ] }; key { [ Alt_L, Meta_L ] }; key { [ space ] }; key { [ Caps_Lock ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F1, F1, F1, F1, XF86Switch_VT_1 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F2, F2, F2, F2, XF86Switch_VT_2 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F3, F3, F3, F3, XF86Switch_VT_3 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F4, F4, F4, F4, XF86Switch_VT_4 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F5, F5, F5, F5, XF86Switch_VT_5 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F6, F6, F6, F6, XF86Switch_VT_6 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F7, F7, F7, F7, XF86Switch_VT_7 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F8, F8, F8, F8, XF86Switch_VT_8 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F9, F9, F9, F9, XF86Switch_VT_9 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F10, F10, F10, F10, XF86Switch_VT_10 ] }; key { [ Num_Lock ] }; key { [ Scroll_Lock ] }; key { [ KP_Home, KP_7 ] }; key { [ KP_Up, KP_8 ] }; key { [ KP_Prior, KP_9 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Subtract, KP_Subtract, KP_Subtract, KP_Subtract, XF86Prev_VMode ] }; key { [ KP_Left, KP_4 ] }; key { [ KP_Begin, KP_5 ] }; key { [ KP_Right, KP_6 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Add, KP_Add, KP_Add, KP_Add, XF86Next_VMode ] }; key { [ KP_End, KP_1 ] }; key { [ KP_Down, KP_2 ] }; key { [ KP_Next, KP_3 ] }; key { [ KP_Insert, KP_0 ] }; key { [ KP_Delete, KP_Decimal ] }; key { [ ISO_Level3_Shift ] }; key { [ less, greater, bar, brokenbar ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F11, F11, F11, F11, XF86Switch_VT_11 ] }; key { type= "CTRL+ALT", symbols[Group1]= [ F12, F12, F12, F12, XF86Switch_VT_12 ] }; key { [ Katakana ] }; key { [ Hiragana ] }; key { [ Henkan_Mode ] }; key { [ Hiragana_Katakana ] }; key { [ Muhenkan ] }; key { [ KP_Enter ] }; key { [ Control_R ] }; key { type= "CTRL+ALT", symbols[Group1]= [ KP_Divide, KP_Divide, KP_Divide, KP_Divide, XF86Ungrab ] }; key { type= "PC_ALT_LEVEL2", symbols[Group1]= [ Print, Sys_Req ] }; key { type= "TWO_LEVEL", symbols[Group1]= [ Alt_R, Meta_R ] }; key { [ Linefeed ] }; key { [ Home ] }; key { [ Up ] }; key { [ Prior ] }; key { [ Left ] }; key { [ Right ] }; key { [ End ] }; key { [ Down ] }; key { [ Next ] }; key { [ Insert ] }; key { [ Delete ] }; key { [ XF86AudioMute ] }; key { [ XF86AudioLowerVolume ] }; key { [ XF86AudioRaiseVolume ] }; key { [ XF86PowerOff ] }; key { [ KP_Equal ] }; key { [ plusminus ] }; key { type= "PC_CONTROL_LEVEL2", symbols[Group1]= [ Pause, Break ] }; key { [ XF86LaunchA ] }; key { [ KP_Decimal, KP_Decimal ] }; key { [ Hangul ] }; key { [ Hangul_Hanja ] }; key { [ Super_L ] }; key { [ Super_R ] }; key { [ Menu ] }; key { [ Cancel ] }; key { [ Redo ] }; key { [ SunProps ] }; key { [ Undo ] }; key { [ SunFront ] }; key { [ XF86Copy ] }; key { [ XF86Open ] }; key { [ XF86Paste ] }; key { [ Find ] }; key { [ XF86Cut ] }; key { [ Help ] }; key { [ XF86MenuKB ] }; key { [ XF86Calculator ] }; key { [ XF86Sleep ] }; key { [ XF86WakeUp ] }; key { [ XF86Explorer ] }; key { [ XF86Send ] }; key { [ XF86Xfer ] }; key { [ XF86Launch1 ] }; key { [ XF86Launch2 ] }; key { [ XF86WWW ] }; key { [ XF86DOS ] }; key { [ XF86ScreenSaver ] }; key { [ XF86RotateWindows ] }; key { [ XF86Mail ] }; key { [ XF86Favorites ] }; key { [ XF86MyComputer ] }; key { [ XF86Back ] }; key { [ XF86Forward ] }; key { [ XF86Eject ] }; key { [ XF86Eject, XF86Eject ] }; key { [ XF86AudioNext ] }; key { [ XF86AudioPlay, XF86AudioPause ] }; key { [ XF86AudioPrev ] }; key { [ XF86AudioStop, XF86Eject ] }; key { [ XF86AudioRecord ] }; key { [ XF86AudioRewind ] }; key { [ XF86Phone ] }; key { [ XF86Tools ] }; key { [ XF86HomePage ] }; key { [ XF86Reload ] }; key { [ XF86Close ] }; key { [ XF86ScrollUp ] }; key { [ XF86ScrollDown ] }; key { [ parenleft ] }; key { [ parenright ] }; key { [ XF86New ] }; key { [ Redo ] }; key { [ XF86Tools ] }; key { [ XF86Launch5 ] }; key { [ XF86Launch6 ] }; key { [ XF86Launch7 ] }; key { [ XF86Launch8 ] }; key { [ XF86Launch9 ] }; key { [ XF86AudioMicMute ] }; key { [ XF86TouchpadToggle ] }; key { [ XF86TouchpadOn ] }; key { [ XF86TouchpadOff ] }; key { [ Mode_switch ] }; key { [ NoSymbol, Alt_L ] }; key { [ NoSymbol, Meta_L ] }; key { [ NoSymbol, Super_L ] }; key { [ NoSymbol, Hyper_L ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioPause ] }; key { [ XF86Launch3 ] }; key { [ XF86Launch4 ] }; key { [ XF86LaunchB ] }; key { [ XF86Suspend ] }; key { [ XF86Close ] }; key { [ XF86AudioPlay ] }; key { [ XF86AudioForward ] }; key { [ Print ] }; key { [ XF86WebCam ] }; key { [ XF86Mail ] }; key { [ XF86Messenger ] }; key { [ XF86Search ] }; key { [ XF86Go ] }; key { [ XF86Finance ] }; key { [ XF86Game ] }; key { [ XF86Shop ] }; key { [ Cancel ] }; key { [ XF86MonBrightnessDown ] }; key { [ XF86MonBrightnessUp ] }; key { [ XF86AudioMedia ] }; key { [ XF86Display ] }; key { [ XF86KbdLightOnOff ] }; key { [ XF86KbdBrightnessDown ] }; key { [ XF86KbdBrightnessUp ] }; key { [ XF86Send ] }; key { [ XF86Reply ] }; key { [ XF86MailForward ] }; key { [ XF86Save ] }; key { [ XF86Documents ] }; key { [ XF86Battery ] }; key { [ XF86Bluetooth ] }; key { [ XF86WLAN ] }; modifier_map Control { }; modifier_map Shift { }; modifier_map Shift { }; modifier_map Mod1 { }; modifier_map Lock { }; modifier_map Mod2 { }; modifier_map Mod5 { }; modifier_map Control { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod4 { }; modifier_map Mod5 { }; modifier_map Mod1 { }; modifier_map Mod4 { }; modifier_map Mod4 { }; }; }; xkbcommon-libxkbcommon-54ee7ac/test/data/keymaps/no-types.xkb000066400000000000000000000664761510033435100245330ustar00rootroot00000000000000xkb_keymap { xkb_keycodes { minimum = 8; maximum = 255; = 9; = 10; = 11; = 12; = 13; = 14; = 15; = 16; = 17; = 18; = 19; = 20; = 21; = 22; = 23; = 24; = 25; = 26; = 27; = 28; = 29; = 30; = 31; = 32; = 33; = 34; = 35; = 36; = 37; = 38; = 39; = 40; = 41; = 42; = 43; = 44; = 45; = 46; = 47; = 48; = 49; = 50; = 51; = 52; = 53; = 54; = 55; = 56; = 57; = 58; = 59; = 60; = 61; = 62; = 63; = 64; = 65; = 66; = 67; = 68; = 69; = 70; = 71; = 72; = 73; = 74; = 75; = 76; = 77; = 78; = 79; = 80; = 81; = 82; = 83; = 84; = 85; = 86; = 87; = 88; = 89; = 90; = 91; = 92; = 94; = 95; = 96; = 97; = 98; = 99; = 100; = 101; = 102; = 103; = 104; = 105; = 106; = 107; = 108; = 109; = 110; = 111; = 112; = 113; = 114; = 115; = 116; = 117; = 118; = 119; = 120; = 121; = 122; = 123; = 124; = 125; = 126; = 127; = 128; = 129; = 130; = 131; = 132; = 133; = 134; = 135; = 136; = 137; = 138; = 139; = 140; = 141; = 142; = 143; = 144; = 145; = 146; = 147; = 148; = 149; = 150; = 151; = 152; = 153; = 154; = 155; = 156; = 157; = 158; = 159; = 160; = 161; = 162; = 163; = 164; = 165; = 166; = 167; = 168; = 169; = 170; = 171; = 172; = 173; = 174; = 175; = 176; = 177; = 178; = 179; = 180; = 181; = 182; = 183; = 184; = 185; = 186; = 187; = 188; = 189; = 190; = 191; = 192; = 193; = 194; = 195; = 196; = 197; = 198; = 199; = 200; = 201; = 202; = 203; = 204; = 205; = 206; = 207; = 208; = 209; = 210; = 211; = 212; = 213; = 214; = 215; = 216; = 217; = 218; = 219; = 220; = 221; = 222; = 223; = 224; = 225; = 226; = 227; = 228; = 229; = 230; = 231; = 232; = 233; = 234; = 235; = 236; = 237; = 238; = 239; = 240; = 241; = 242; = 243; = 244; = 245; = 246; = 247; = 248; = 249; = 250; = 251; = 252; = 253; indicator 1 = "Caps Lock"; indicator 2 = "Num Lock"; indicator 3 = "Scroll Lock"; indicator 4 = "Compose"; indicator 5 = "Kana"; indicator 6 = "Sleep"; indicator 7 = "Suspend"; indicator 8 = "Mute"; indicator 9 = "Misc"; indicator 10 = "Mail"; indicator 11 = "Charging"; indicator 12 = "Shift Lock"; indicator 13 = "Group 2"; indicator 14 = "Mouse Keys"; alias = ; alias

; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias = ; alias

= ;\n" " = 1;\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "keycodes-aliases-2.xkb" }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); /* * We use a new context because we want to check key name LUT is * correctly implemented */ struct xkb_context * const ctx2 = test_get_context(CONTEXT_NO_FLAG); assert(ctx2); assert(test_compile_output(ctx2, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); xkb_context_unref(ctx2); } /* Test random high keycodes do not trigger xkbcomp asserts */ static const unsigned int max_iterations = 1000; char buffer[2048] = ""; for (unsigned int i = 0; i < max_iterations; i++) { size_t available = sizeof(buffer); char *buf = buffer; int count = snprintf(buf, available, "default xkb_keymap { xkb_keycodes {\n"); assert(count > 0 && (size_t) count < available); available -= (size_t) count; buf += count; static const struct { xkb_keycode_t min; xkb_keycode_t max; unsigned int max_count; } bounds[] = { { .min = 10 << 3, /* Avoid issue with digits */ .max = XKB_KEYCODE_MAX_CONTIGUOUS, .max_count = 3 }, { .min = XKB_KEYCODE_MAX_CONTIGUOUS + 1, .max = XKB_KEYCODE_MAX, .max_count = 10 }, }; xkb_keycode_t keycodes[13] = {0}; unsigned int keycode_index = 0; for (size_t b = 0; b < ARRAY_SIZE(bounds); b++) { assert(bounds[b].min < bounds[b].max); const unsigned int keycode_count = rand() % (bounds[b].max_count + 1); for (unsigned int k = 0; k < keycode_count; k++) { /* Note: we do not care about keycode uniqueness */ const xkb_keycode_t kc = bounds[b].min + (rand() % (bounds[b].max - bounds[b].min + 1)); assert(keycode_index < ARRAY_SIZE(keycodes)); keycodes[keycode_index++] = kc; count = snprintf(buf, available, "<%"PRIu32"> = 0x%"PRIx32";\n", kc, kc); assert(count > 0 && (size_t) count < available); available -= (size_t) count; buf += count; } } count = snprintf(buf, available, "}; xkb_symbols {\n"); assert(count > 0 && (size_t) count < available); available -= (size_t) count; buf += count; for (unsigned int k = 0; k < keycode_index; k++) { const xkb_keycode_t kc = keycodes[k]; count = snprintf(buf, available, "key <%"PRIu32"> { [ 0x%"PRIx32" ] };\n", kc, (kc >> 3)); assert(count > 0 && (size_t) count < available); available -= (size_t) count; buf += count; } count = snprintf(buf, available, "}; };"); assert(count > 0 && (size_t) count < available); struct xkb_keymap * const keymap = xkb_keymap_new_from_string( ctx, buffer, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS ); assert(keymap); for (unsigned int k = 0; k < keycode_index; k++) { const xkb_keycode_t kc = keycodes[k]; const xkb_keysym_t *ks = NULL; count = xkb_keymap_key_get_syms_by_level(keymap, kc, 0, 0, &ks); assert_printf(count == 1, "%d\n", count); const xkb_keysym_t expected = kc >> 3; assert_printf(*ks == expected, "<%"PRIu32"> 0x%"PRIx32" != 0x%"PRIx32"\n", kc, *ks, expected); } xkb_keymap_unref(keymap); } } static void test_masks(struct xkb_context *ctx, bool update_output_files) { const struct keymap_test_data keymaps[] = { { .keymap = "xkb_keymap {\n" " xkb_compat {\n" /* Cannot be negative */ " virtual_modifiers Test1 = -1;\n" " };\n" "};", .expected = NULL }, { .keymap = "xkb_keymap {\n" " xkb_compat {\n" /* Out of range (expect 32bits) */ " virtual_modifiers Test1 = 0x100000000;\n" " };\n" "};", .expected = NULL }, { .keymap = "xkb_keymap {\n" " xkb_compat {\n" /* Out of range (expect 32bits) */ " virtual_modifiers Test1 = ~0x100000000;\n" " };\n" "};", .expected = NULL }, { .keymap = "xkb_keymap {\n" " xkb_compat {\n" /* Unsupported operator */ " virtual_modifiers Test1 = !Mod1;\n" " };\n" "};", .expected = NULL }, { .keymap = "xkb_keymap {\n" " xkb_types {\n" /* Try range */ " virtual_modifiers Test01 = 0;\n" " virtual_modifiers Test02 = 0xffffffff;\n" /* Try various operations on masks */ " virtual_modifiers Test11 = 0xf0 + 0x0f;\n" " virtual_modifiers Test12 = 0xff - 0x0f;\n" " virtual_modifiers Test13 = ~0xf;\n" " virtual_modifiers Test14 = ~none;\n" " virtual_modifiers Test15 = ~all;\n" " virtual_modifiers Test16 = ~0xffffffff;\n" " virtual_modifiers Test17 = all - ~Mod1 + Mod2;\n" " type \"XXX\" {\n" " modifiers = Test12;\n" /* Masks mappings are not resolved here, so: * map[Test12 - Mod5] <=> map[Test12] */ " map[Test12 - Mod5] = 2;\n" " };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "masks.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { = 38; };\n" " xkb_symbols {\n" " virtual_modifiers X = 0xf0000000;\n" " key { [ SetMods(mods = 0x00001100) ] };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "masks-extra-bits.xkb" } }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_interpret(struct xkb_context *ctx, bool update_output_files) { const struct keymap_test_data keymaps[] = { /* Invalid: empty string */ { .keymap = "xkb_keymap {\n" " xkb_compat { interpret \"\" { repeat = false; } };\n" "};", .expected = NULL }, /* Invalid UTF-8 encoding */ { .keymap = "xkb_keymap {\n" " xkb_compat { interpret \"\xff\" { repeat = false; }; };\n" "};", .expected = NULL }, /* Invalid single Unicode code point */ { .keymap = "xkb_keymap {\n" " xkb_compat { interpret \"\\u{0}\" { repeat = false; }; };\n" "};", .expected = NULL }, /* Invalid multiple Unicode code points */ { .keymap = "xkb_keymap {\n" " xkb_compat { interpret \"ab\" { repeat = false; }; };\n" "};", .expected = NULL }, /* Valid */ { .keymap = u8"xkb_keymap {\n" u8" xkb_compat {\n" u8" interpret 0x1 { repeat = false; };\n" u8" interpret 0xB { repeat = false; };\n" u8" interpret Shift_L { repeat = false; };\n" u8" interpret a { repeat = false; };\n" u8" interpret \"ä\" { repeat = false; };\n" u8" interpret \"✨\" { repeat = false; };\n" u8" interpret \"🎺\" { repeat = false; };\n" u8" };\n" u8"};", .expected = GOLDEN_TESTS_OUTPUTS "compat-interpret.xkb" }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_group_indices_names(struct xkb_context *ctx, bool update_output_files) { const struct { const char* keymap; const char* expected_v1; const char* expected_v2; } keymaps[] = { { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " <> = 1;\n" " indicator 1 = \"1\";\n" " indicator 2 = \"2\";\n" " };\n" " xkb_compat {\n" " interpret a { action = SetGroup(group=Group1); };\n" " interpret b { action = SetGroup(group=-Group2); };\n" " interpret c { action = SetGroup(group=+Group3); };\n" " indicator \"1\" { groups = Group4; };\n" " indicator \"2\" { groups = All-Group1; };\n" " };\n" " xkb_symbols {\n" " name[Group1] = \"1\";\n" " name[Group2] = \"2\";\n" " name[Group3] = \"3\";\n" " name[Group4] = \"4\";\n" " key <> {\n" " groupsredirect=Group4,\n" " symbols[Group1]=[a],\n" " symbols[Group2]=[b],\n" " symbols[Group3]=[c],\n" " symbols[Group4]=[d]\n" " };\n" " };\n" "};", .expected_v1 = GOLDEN_TESTS_OUTPUTS "group-index-names-1.xkb", .expected_v2 = GOLDEN_TESTS_OUTPUTS "group-index-names-1.xkb" }, { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " <> = 1;\n" " indicator 1 = \"1\";\n" " indicator 2 = \"2\";\n" " };\n" " xkb_compat {\n" " interpret a { action = SetGroup(group=Group32); };\n" " interpret b { action = SetGroup(group=-Group32); };\n" " interpret c { action = SetGroup(group=+Group32); };\n" " indicator \"1\" { groups = Group32; };\n" " indicator \"2\" { groups = All-Group32; };\n" " };\n" " xkb_symbols {\n" " name[Group1] = \"1\";\n" " name[Group4] = \"4\";\n" " name[Group5] = \"5\";\n" " name[Group8] = \"8\";\n" " name[Group32] = \"32\";\n" " key <> {\n" " groupsredirect=Group32,\n" " symbols[Group1]=[a],\n" " symbols[Group4]=[b],\n" " symbols[Group5]=[c],\n" " symbols[Group8]=[d],\n" " symbols[Group32]=[e]\n" " };\n" " };\n" "};", .expected_v1 = NULL, .expected_v2 = GOLDEN_TESTS_OUTPUTS "group-index-names-2.xkb" }, /* No names for groups above 32 */ { .keymap = "xkb_keymap {\n" " xkb_compat { interpret a { action = SetGroup(group=Group33); }; };\n" "};", .expected_v1 = NULL, .expected_v2 = NULL }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { indicator 1 = \"1\"; };\n" " xkb_compat { indicator \"1\" { groups = Group33; }; };\n" "};", .expected_v1 = NULL, .expected_v2 = NULL }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { name[Group33] = \"1\"; };\n" "};", .expected_v1 = NULL, .expected_v2 = NULL }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { key <> { groupsredirect=Group33 };\n" "};", .expected_v1 = NULL, .expected_v2 = NULL }, { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_symbols { key <> { symbols[Group33] = [a] };\n" "};", .expected_v1 = NULL, .expected_v2 = NULL } }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected_v1, update_output_files)); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected_v2, update_output_files)); } } static void test_level_indices_names(struct xkb_context *ctx, bool update_output_files) { const struct { const char* keymap; const char* expected; } keymaps[] = { { .keymap = "xkb_keymap {\n" " xkb_types {\n" " type \"X\" {\n" " modifiers = Shift;\n" " map[Shift] = Level2048;\n" " level_name[Level2048] = \"x\";\n" " };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "level-index-names.xkb" }, /* No names above 2048 */ { .keymap = "xkb_keymap {\n" " xkb_types {\n" " type \"X\" {\n" " modifiers = Shift;\n" " map[Shift] = Level2049;\n" " };\n" " };\n" "};", .expected = NULL, }, { .keymap = "xkb_keymap {\n" " xkb_types {\n" " type \"X\" {\n" " modifiers = Shift;\n" " level_name[Level2049] = \"x\";\n" " };\n" " };\n" "};", .expected = NULL, }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } /* Test various multi-{keysym,action} syntaxes */ static void test_multi_keysyms_actions(struct xkb_context *ctx, bool update_output_files) { /* Macro to create keymap for failing tests */ #define make_keymap(xs) \ "xkb_keymap {\n" \ " xkb_keycodes {\n" \ " = 10;\n" \ " };\n" \ " xkb_types { include \"basic\" };\n" \ " xkb_compat { include \"basic\" };\n" \ " xkb_symbols {\n" \ " key { [" xs "] };\n" \ " };\n" \ "};" #define make_keymaps_with(func, name, a, b, c, d) \ /* Test: valid keymaps */ \ { \ .keymap = \ "xkb_keymap {\n" \ " xkb_keycodes {\n" \ " <01> = 1;\n" \ " <02> = 2;\n" \ " <03> = 3;\n" \ " <04> = 4;\n" \ " <05> = 5;\n" \ " <06> = 6;\n" \ " <07> = 7;\n" \ " <08> = 8;\n" \ " <09> = 9;\n" \ " <10> = 10;\n" \ " <11> = 11;\n" \ " <12> = 12;\n" \ " <13> = 13;\n" \ " <14> = 14;\n" \ " <15> = 15;\n" \ " };\n" \ " xkb_types { include \"basic+extra\" };\n" \ " xkb_compat { include \"basic\" };\n" \ " xkb_symbols {\n" \ " key <01> { [ "a "] };\n" \ " key <02> { [ "a", "b" ] };\n" \ " key <03> { [ {} ] };\n" \ " key <04> { [ {}, "b" ] };\n" \ " key <05> { [ "a", {} ] };\n" \ " key <06> { [ {}, {} ] };\n" \ " key <07> { [ { "a" } ] };\n" \ " key <08> { [ { "a" }, { "b" } ] };\n" \ " key <09> { [ { "a", "b" } ] };\n" \ " key <10> { [ { "a", "b", "c" } ] };\n" \ " key <11> { [ "a", { "b", "c" } ] };\n" \ " key <12> { [ { "a", "b" }, "c" ] };\n" \ " key <13> { [ { "a", "b" }, { "c", "d" } ] };\n" \ " key <14> { [ { "a", "b" }, "c", { "d", "a" } ] };\n" \ " key <15> { [ { "a", "b" }, { "c", "d" }, "a" ] };\n" \ " };\n" \ "};", \ .expected = GOLDEN_TESTS_OUTPUTS "symbols-multi-" name ".xkb" \ }, \ /* Test: invalid keymaps */ \ { .keymap = func("{ {} }") , .expected = NULL }, \ { .keymap = func("{ "a", {} }") , .expected = NULL }, \ { .keymap = func("{ {}, "b" }") , .expected = NULL }, \ { .keymap = func("{ {}, {} }") , .expected = NULL }, \ { .keymap = func("{ "a", { "b" } }") , .expected = NULL }, \ { .keymap = func("{ { "a" }, "b" }") , .expected = NULL }, \ { .keymap = func("{ { "a", "b" }, "c" }") , .expected = NULL }, \ { .keymap = func("{ "a", { "b", "c" } }") , .expected = NULL }, \ { .keymap = func("{ "a", {}, "c" }") , .expected = NULL }, \ { .keymap = func("{ "a", "b", {} }") , .expected = NULL }, \ { .keymap = func("{ {}, "b", "c" }") , .expected = NULL }, \ { .keymap = func("{ { "a", "b" }, "c", "d" }") , .expected = NULL }, \ { .keymap = func("{ "a", { "b", "c" }, "d" }") , .expected = NULL }, \ { .keymap = func("{ "a", "b", { "c", "d" } }") , .expected = NULL }, \ { .keymap = func("{ { "a", "b" }, { "c", "d" } }"), .expected = NULL } const struct keymap_test_data keymaps[] = { make_keymaps_with(make_keymap, "keysyms", "a", "b", "c", "d"), make_keymaps_with(make_keymap, "actions", "SetMods(modifiers=Control)", "SetGroup(group=+1)", "Private(data=\"foo\")", "Private(data=\"bar\")"), { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " <10> = 10;\n" " <11> = 11;\n" " <12> = 12;\n" " <13> = 13;\n" " <14> = 14;\n" " <15> = 15;\n" " <16> = 16;\n" " <17> = 17;\n" " <18> = 18;\n" " <19> = 19;\n" " <20> = 20;\n" " <21> = 21;\n" " <22> = 22;\n" " <23> = 23;\n" " <30> = 30;\n" " <31> = 31;\n" " <32> = 32;\n" " <33> = 33;\n" " <34> = 34;\n" " <35> = 35;\n" " <36> = 36;\n" " <37> = 37;\n" " <38> = 38;\n" " <39> = 39;\n" " };\n" " xkb_types { include \"basic+extra\" };\n" " xkb_compat {\n" " interpret 1 { action = {}; };\n" " interpret 2 { action = {NoAction()}; };\n" " interpret 3 { action = {SetMods()}; };\n" " interpret 4 { action = {SetMods(), SetGroup(group=1)}; };\n" " };\n" " xkb_symbols {\n" /* Empty keysyms */ " key <10> { [any, any ] };\n" " key <11> { [{} , {} ] };\n" " key <12> { [any, any ], [SetMods(modifiers=Shift)] };\n" " key <13> { [{} , {} ], [SetMods(modifiers=Shift)] };\n" " key <14> { [any, any ], type = \"TWO_LEVEL\" };\n" " key <15> { [{} , {} ], type = \"TWO_LEVEL\" };\n" " key <16> { [a, A, any] };\n" " key <17> { [a, A, {} ] };\n" " key <18> { [a, A, any], type = \"FOUR_LEVEL_SEMIALPHABETIC\" };\n" " key <19> { [a, A, {} ], type = \"FOUR_LEVEL_SEMIALPHABETIC\" };\n" " key <20> { [a, A, ae, any] };\n" " key <21> { [a, A, ae, {} ] };\n" " key <22> { [a, A, ae, AE, any] };\n" " key <23> { [a, A, ae, AE, {} ] };\n" /* Empty actions */ " key <30> { [NoAction(), NoAction() ] };\n" " key <31> { actions=[{}, {} ] };\n" " key <32> { [NoAction(), NoAction() ], [a] };\n" " key <33> { actions=[{}, {} ], [a] };\n" " key <34> { [NoAction(), NoAction() ], type = \"TWO_LEVEL\" };\n" " key <35> { actions=[{}, {} ], type = \"TWO_LEVEL\" };\n" " key <38> { [NoAction(), NoAction() ], type = \"FOUR_LEVEL_SEMIALPHABETIC\" };\n" " key <39> { actions=[{}, {} ], type = \"FOUR_LEVEL_SEMIALPHABETIC\" };\n" " };\n" "};", .expected = GOLDEN_TESTS_OUTPUTS "symbols-multi-keysyms-empty.xkb" } }; for (size_t k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%zu ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V2, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } #undef make_keymaps_with #undef make_keymap /* V1 serialization */ const char keymap_str[] = "xkb_keymap {\n" " xkb_keycodes { <> = 1; };\n" " xkb_compat { interpret A { action = {SetMods(), SetGroup()}; }; };\n" " xkb_symbols { key <> { [{SetMods(), SetGroup()}] }; };\n" "};"; assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymap_str, ARRAY_SIZE(keymap_str), GOLDEN_TESTS_OUTPUTS "symbols-multi-actions-v1.xkb", update_output_files)); } /* Test keysyms as strings */ static void test_key_keysyms_as_strings(struct xkb_context *ctx, bool update_output_files) { const struct keymap_test_data keymaps[] = { /* Invalid UTF-8 encoding */ { .keymap = "xkb_keymap {\n" " xkb_keycodes { <> = 10; };\n" " xkb_symbols {\n" /* Invalid byte at string index 2 */ " key <> { [\"\xC3\xBC\xff\"] };\n" " };\n" "};", .expected = NULL }, /* Valid */ { .keymap = u8"xkb_keymap {\n" u8" xkb_keycodes {\n" u8" <10> = 10;\n" u8" <11> = 11;\n" u8" <12> = 12;\n" u8" <20> = 20;\n" u8" <21> = 21;\n" u8" <22> = 22;\n" u8" <23> = 23;\n" u8" <24> = 24;\n" u8" <25> = 25;\n" u8" <30> = 30;\n" u8" <31> = 31;\n" u8" <32> = 32;\n" u8" <33> = 33;\n" u8" <34> = 34;\n" u8" <35> = 35;\n" u8" <40> = 40;\n" u8" <41> = 41;\n" u8" <42> = 42;\n" u8" <50> = 50;\n" u8" <51> = 51;\n" u8" <52> = 52;\n" u8" <60> = 60;\n" u8" <61> = 61;\n" u8" <62> = 62;\n" u8" <63> = 63;\n" u8" <64> = 64;\n" u8" <65> = 65;\n" u8" <66> = 66;\n" u8" <67> = 67;\n" u8" <68> = 68;\n" u8" <69> = 69;\n" u8" <70> = 70;\n" u8" <71> = 71;\n" u8" <72> = 72;\n" u8" <73> = 73;\n" u8" <74> = 74;\n" u8" = 80;\n" u8" = 81;\n" u8" = 82;\n" u8" = 83;\n" u8" };\n" u8" xkb_types { include \"basic\" };\n" u8" xkb_compat {\n" u8" interpret.action = SetMods();\n" u8" interpret \"ä\" {};\n" u8" interpret \"✨\" {};\n" u8" interpret \"🎺\" {};\n" u8" interpret \"\\u{1F54A}\" {};\n" u8" interpret \"\\u{1}\" {};\n" u8" interpret \"\\u{a}\" {};\n" u8" interpret \"\\u{1f}\" {};\n" u8" interpret \"\\u{20}\" {};\n" u8" interpret \"\\u{7e}\" {};\n" u8" interpret \"\\u{7f}\" {};\n" u8" interpret \"\\u{80}\" {};\n" u8" interpret \"\\u{9f}\" {};\n" u8" interpret \"\\u{a0}\" {};\n" u8" interpret \"\\u{ff}\" {};\n" // u8" interpret \"\\u{d800}\" {};\n" // u8" interpret \"\\u{dfff}\" {};\n" u8" interpret \"\\u{fdd0}\" {};\n" u8" interpret \"\\u{fdef}\" {};\n" u8" interpret \"\\u{fffe}\" {};\n" u8" interpret \"\\u{ffff}\" {};\n" u8" interpret \"\\u{10000}\" {};\n" u8" interpret \"\\u{1ffff}\" {};\n" u8" interpret \"\\u{10ffff}\" {};\n" u8" };\n" u8" xkb_symbols {\n" /* Empty string */ u8" key <10> { [\"\", {b, \"\", c}] };\n" u8" key <11> { [{a, \"\"}, {b, \"\"}] };\n" u8" key <12> { [{\"\"}, {\"\", \"\"}] };\n" /* Single string: Plain */ u8" key <20> { [\"a\", \"bc\"] };\n" u8" key <23> { [\"✨\", \"🎺\"] };\n" // U+2728 ✨, U+1F3BA 🎺 u8" key <24> { [\"u\u0308\"] };\n" // u + U+0308 ◌̈ COMBINING DIAERESIS u8" key <25> { [\"∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა\"] };\n" /* Single string: Nested */ u8" key <30> { [{\"a\" }, {\"bc\" }] };\n" u8" key <31> { [{\"a\", \"\"}, {\"bc\", \"\"}] };\n" u8" key <32> { [{\"\", \"a\"}, {\"\", \"bc\"}] };\n" u8" key <33> { [{\"\\u{1F54A}\"}, {\"\\u{1f3f3}\\u{fe0f}\"}] };\n" // U+1F54A 🕊️, 🏳️ u8" key <34> { [{\"u\\u{0308}\"}] };\n" // u + U+0308 ◌̈ COMBINING DIAERESIS u8" key <35> { [{\"∀\\u{0}∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა\"}] };\n" /* Multi: string, literal */ u8" key <40> { [{\"a\", b}, {\"cde\", f}] };\n" u8" key <41> { [{\"a\", \"\", b}, {\"cde\", \"\", f}] };\n" u8" key <42> { [{\"a\", b, \"\"}, {\"cde\", f, \"\"}] };\n" /* Multi: literal, string */ u8" key <50> { [{a, \"b\"}, {c, \"def\"}] };\n" u8" key <51> { [{a, \"\", \"b\"}, {c, \"\", \"def\"}] };\n" u8" key <52> { [{a, \"b\", \"\"}, {c, \"def\", \"\"}] };\n" /* Multi: string, string */ u8" key <60> { [{\"a\", \"b\"}, {\"cd\", \"ef\"}] };\n" u8" key <61> { [{\"a\", \"\", \"b\"}, {\"cd\", \"\", \"ef\"}] };\n" u8" key <63> { [{\"a\", \"bcd\"}, {\"efg\", \"h\"}] };\n" u8" key <64> { [{\"a\", \"\", \"bcd\"}, {\"efg\", \"\", \"h\"}] };\n" /* Some special Unicode code points */ u8" key <65> { [\"\\u{0}\", \"\\u{10ffff}\"] };\n" u8" key <66> { [\"\\u{1}\", \"\\u{a}\"] };\n" u8" key <67> { [\"\\u{1f}\", \"\\u{20}\"] };\n" u8" key <68> { [\"\\u{7e}\", \"\\u{7f}\"] };\n" u8" key <69> { [\"\\u{80}\", \"\\u{9f}\"] };\n" u8" key <70> { [\"\\u{a0}\", \"\\u{ff}\"] };\n" u8" key <71> { [\"\\u{d800}\", \"\\u{dfff}\"] };\n" u8" key <72> { [\"\\u{fdd0}\", \"\\u{fdef}\"] };\n" u8" key <73> { [\"\\u{fffe}\", \"\\u{ffff}\"] };\n" u8" key <74> { [\"\\u{10000}\", \"\\u{1ffff}\"] };\n" /* Example from the doc */ u8" key { [ \"ij\" , \"IJ\" ] }; // IJ Dutch digraph\n" u8" key { [ \"g̃\" , \"G̃\" ] }; // G̃ Guarani letter\n" /* NOTE: We use U+200E LEFT-TO-RIGHT MARK in order to display the strings in * in the proper order. */ u8" key { [ \"لا\"‎ , \"لآ\"‎ ] }; // ⁧لا⁩ ⁧لآ⁩ Arabic Lam-Alef ligatures decomposed\n" u8" key { [ \"c’h\", \"C’h\" ] }; // C’H Breton trigraph\n" u8" modifier_map Mod1 { \"✨\", \"\\u{1F54A}\" };\n" u8" };\n" u8"};", .expected = GOLDEN_TESTS_OUTPUTS "string-as-keysyms.xkb" }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_invalid_symbols_fields(struct xkb_context *ctx) { /* Any of the following is invalid syntax, but also use to trigger * a NULL pointer deference, thus this regression test */ const char * const keymaps[] = { "xkb_keymap {\n" " xkb_keycodes { <> = 9; };\n" " xkb_symbols { key <> { vmods = [] }; };\n" "};", "xkb_keymap {\n" " xkb_keycodes { <> = 9; };\n" " xkb_symbols { key <> { repeat = [] }; };\n" "};", "xkb_keymap {\n" " xkb_keycodes { <> = 9; };\n" " xkb_symbols { key <> { type = [] }; };\n" "};", "xkb_keymap {\n" " xkb_keycodes { <> = 9; };\n" " xkb_symbols { key <> { groupswrap = [] }; };\n" "};", "xkb_keymap {\n" " xkb_keycodes { <> = 9; };\n" " xkb_symbols { key <> { groupsredirect = [] }; };\n" "};", /* Used to parse without error because the “repeats” key field is valid, * but we should fail in the following 2 keymaps */ "xkb_keymap {\n" " xkb_keycodes { <> = 9; };\n" " xkb_symbols { key <> { vmods=[], repeats=false }; };\n" "};", "xkb_keymap {\n" " xkb_keycodes { <> = 9; };\n" " xkb_symbols { key <> { repeats=false, vmods=[] }; };\n" "};" }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); const struct xkb_keymap *keymap = test_compile_buffer(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, keymaps[k], strlen(keymaps[k])); assert(!keymap); } } static void test_modifier_maps(struct xkb_context *ctx, bool update_output_files) { /* Only accept key and keysyms in the modifier_map list */ struct keymap_test_data keymaps[] = { { .keymap = u8"xkb_keymap {\n" u8" xkb_keycodes {\n" u8" = 66;\n" u8" alias = ;\n" u8" <0> = 0;" u8" <1> = 1;" u8" <2> = 2;" u8" <3> = 3;" u8" <4> = 4;" u8" <5> = 5;" u8" <6> = 6;" u8" <7> = 7;" u8" = 10;" u8" = 11;" u8" = 61;" u8" = 62;" u8" = 63;" u8" <100> = 100;" u8" };\n" u8" xkb_types { include \"basic\" };\n" u8" xkb_symbols {\n" u8" key { [Caps_Lock] };\n" u8" key { [any, A] };\n" u8" key { [none, N] };\n" u8" key <0> { [0] };\n" u8" key <1> { [1] };\n" u8" key <2> { [2] };\n" u8" key { [a] };\n" u8" key { [b] };\n" u8" key { [\"🎺\"] };\n" u8" key <3> { [NotAKeysym, 3] };\n" u8" key <4> { [\"\\u{0000001F54A}\"]};\n" u8" key <5> { [\"\\u{d800}\", \"\\u{dfff}\"]};\n" u8" key <6> { [\"\\u{fdd0}\", \"\\u{fdef}\"]};\n" u8" key <7> { [\"\\u{fffe}\", \"\\u{ffff}\"]};\n" u8" key <100> { [C] };\n" u8" modifier_map Lock {\n" u8" <100>, , any, none,\n" u8" 0, 1, 0x2, a, \"b\", \"🎺\", \"\\u{1F54A}\",\n" u8" \"\\u{d800}\", \"\\u{dfff}\",\n" u8" \"\\u{fdd0}\", \"\\u{fdef}\",\n" u8" \"\\u{fffe}\", \"\\u{ffff}\",\n" u8" NotAKeysym\n" u8" };\n" u8" };\n" u8"};", .expected = GOLDEN_TESTS_OUTPUTS "symbols-modifier_map.xkb" }, /* Invalid: empty string */ { .keymap = "xkb_keymap {\n" " xkb_symbols { modifier_map Lock { \"\" }; };\n" "};", .expected = NULL }, /* Invalid Unicode encoding */ { .keymap = "xkb_keymap {\n" " xkb_symbols { modifier_map Lock { \"\xff\" }; };\n" "};", .expected = NULL }, /* Invalid single Unicode code point */ { .keymap = "xkb_keymap {\n" " xkb_symbols { modifier_map Lock { \"\\u{0}\" }; };\n" "};", .expected = NULL }, /* Invalid multiple Unicode code points */ { .keymap = "xkb_keymap {\n" " xkb_symbols { modifier_map Lock { \"ab\" }; };\n" "};", .expected = NULL }, /* Invalid type: list */ { .keymap = "xkb_keymap {\n" " xkb_symbols { modifier_map Lock { [a] }; };\n" "};", .expected = NULL }, /* Invalid type: list */ { .keymap = "xkb_keymap {\n" " xkb_symbols { modifier_map Lock { {a, b} }; };\n" "};", .expected = NULL }, }; for (unsigned int k = 0; k < ARRAY_SIZE(keymaps); k++) { fprintf(stderr, "------\n*** %s: #%u ***\n", __func__, k); assert(test_compile_output(ctx, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_USE_ORIGINAL_FORMAT, compile_buffer, NULL, __func__, keymaps[k].keymap, strlen(keymaps[k].keymap), keymaps[k].expected, update_output_files)); } } static void test_empty_compound_statements(struct xkb_context *ctx, bool update_output_files) { struct keymap_test_data keymaps[] = { { .keymap = "xkb_keymap {\n" " xkb_keycodes {\n" " = 24;\n" " = 25;\n" " = 26;\n" " = 27;\n" " = 28;\n" " = 29;\n" " = 30;\n" " = 31;\n" " = 32;\n" "